如何在存儲過程的IN操作中傳遞字符串變量


原始SQL如下:

SELECT   MONTH(OrderTime) AS datetype, SUM(DeliveryCount) AS decount, Region
FROM      (SELECT   dbo.mpc_Order.OrderTime, 
                                 dbo.mpc_Order.Province + '-' + dbo.mpc_Order.City + '-' + dbo.mpc_Order.Area AS Region, 
                                 dbo.mpc_Order_Delivery.DeliveryCount
                 FROM      dbo.mpc_Order INNER JOIN
                                 dbo.mpc_Order_Delivery ON dbo.mpc_Order.OrderID = dbo.mpc_Order_Delivery.OrderID) AS T1
                                  WHERE Region IN('天津市-市轄區-和平區','吉林省-長春市-市轄區')
GROUP BY Region, MONTH(OrderTime)

因為項目需要,我需要把IN里的字符串做為一個參數,並寫成存儲過程進行調用,IN里面明顯是一個字符串,所以很自然的寫出如下存儲過程:

ALTER PROCEDURE [dbo].[QueryAgentOrder] 
    -- Add the parameters for the stored procedure here
    @Region NVARCHAR(1000),
    @QueryBy NVARCHAR(10)
AS
BEGIN
    DECLARE @SQL NVARCHAR(1000);    --SQL
    DECLARE @PARAM NVARCHAR(1000);    --參數
    IF @QueryBy = 'MONTh' OR @QueryBy = 'YEAR'
    BEGIN
        --SET @Region = '''天津市-市轄區-和平區'',''山東省-濱州市-鄒平縣''';
        SET @SQL = N'SELECT ' + @QueryBy + '(OrderTime) AS datetype, SUM(DeliveryCount) AS decount, Region';
        SET @SQL = @SQL + ' FROM      (SELECT   dbo.mpc_Order.OrderTime, ';
        SET @SQL = @SQL + ' dbo.mpc_Order.Province + ''-'' + dbo.mpc_Order.City + ''-'' + dbo.mpc_Order.Area AS Region,';
        SET @SQL = @SQL + ' dbo.mpc_Order_Delivery.DeliveryCount';
        SET @SQL = @SQL + ' FROM      dbo.mpc_Order INNER JOIN';
        SET @SQL = @SQL + ' dbo.mpc_Order_Delivery ON dbo.mpc_Order.OrderID = dbo.mpc_Order_Delivery.OrderID';        
        SET @SQL = @SQL + ' ) AS T1';
        IF @Region IS NOT NULL
            BEGIN
                --這里傳遞@Region參數
                SET @SQL = @SQL + ' WHERE Region IN(@Region)';
            END
        SET @SQL = @SQL + ' GROUP BY Region, ' + @QueryBy + '(OrderTime)';

        --申明參數
        SET @PARAM = N'@Region NVARCHAR(1000),@QueryBy NVARCHAR(10)';

        --執行存儲過程
        EXEC sys.sp_executesql @SQL,@PARAM,@Region = @Region,@QueryBy = @QueryBy
    END
END

用以下方式調用,沒有得到的記錄:

EXEC    [dbo].[QueryAgentOrder]
        @Region = N'天津市-市轄區-和平區,吉林省-長春市-市轄區',
        @QueryBy = N'month'

換一種方式調用,還是不行:

EXEC    [dbo].[QueryAgentOrder]
        @Region = N'''天津市-市轄區-和平區'',''吉林省-長春市-市轄區''',
        @QueryBy = N'month'

 

其實關鍵還是出在如何傳遞Region變量上。后來看到兩篇帖子,經過測試,得到兩種正確的方法如下:

第一種方法:

在Region兩邊用單引號和加號+再連接一下,就可以。至於為什么,不清楚。。。

ALTER PROCEDURE [dbo].[QueryAgentOrder] 
    -- Add the parameters for the stored procedure here
    @Region NVARCHAR(1000),
    @QueryBy NVARCHAR(10)
AS
BEGIN
    DECLARE @SQL NVARCHAR(1000);    --SQL
    DECLARE @PARAM NVARCHAR(1000);    --參數
    IF @QueryBy = 'MONTh' OR @QueryBy = 'YEAR'
    BEGIN
        SET @SQL = N'SELECT ' + @QueryBy + '(OrderTime) AS datetype, SUM(DeliveryCount) AS decount, Region';
        SET @SQL = @SQL + ' FROM      (SELECT   dbo.mpc_Order.OrderTime, ';
        SET @SQL = @SQL + ' dbo.mpc_Order.Province + ''-'' + dbo.mpc_Order.City + ''-'' + dbo.mpc_Order.Area AS Region,';
        SET @SQL = @SQL + ' dbo.mpc_Order_Delivery.DeliveryCount';
        SET @SQL = @SQL + ' FROM      dbo.mpc_Order INNER JOIN';
        SET @SQL = @SQL + ' dbo.mpc_Order_Delivery ON dbo.mpc_Order.OrderID = dbo.mpc_Order_Delivery.OrderID';        
        SET @SQL = @SQL + ' ) AS T1';
        IF @Region IS NOT NULL
            BEGIN
                --在@Region兩邊加單引號
                SET @SQL = @SQL + ' WHERE Region IN('+ @Region + ')';
            END
        SET @SQL = @SQL + ' GROUP BY Region, ' + @QueryBy + '(OrderTime)';

        --申明參數
        SET @PARAM = N'@Region NVARCHAR(1000),@QueryBy NVARCHAR(10)';

        --執行存儲過程
        EXEC sys.sp_executesql @SQL,@PARAM,@Region = @Region,@QueryBy = @QueryBy
    END
END

調用方法:

EXEC    [dbo].[QueryAgentOrder]
        @Region = N'''天津市-市轄區-和平區'',''吉林省-長春市-市轄區''',
        @QueryBy = N'month'

調用結果:

第二種方法:

 使用一個自定義函數,模擬split實現,然后通過select調用函數,感覺這種方法比較好。

ALTER PROCEDURE [dbo].[QueryAgentOrder] 
    -- Add the parameters for the stored procedure here
    @Region NVARCHAR(1000),
    @QueryBy NVARCHAR(10)
AS
BEGIN
    DECLARE @SQL NVARCHAR(1000);    --SQL
    DECLARE @PARAM NVARCHAR(1000);    --參數
    IF @QueryBy = 'MONTh' OR @QueryBy = 'YEAR'
    BEGIN
        SET @SQL = N'SELECT ' + @QueryBy + '(OrderTime) AS datetype, SUM(DeliveryCount) AS decount, Region';
        SET @SQL = @SQL + ' FROM      (SELECT   dbo.mpc_Order.OrderTime, ';
        SET @SQL = @SQL + ' dbo.mpc_Order.Province + ''-'' + dbo.mpc_Order.City + ''-'' + dbo.mpc_Order.Area AS Region,';
        SET @SQL = @SQL + ' dbo.mpc_Order_Delivery.DeliveryCount';
        SET @SQL = @SQL + ' FROM      dbo.mpc_Order INNER JOIN';
        SET @SQL = @SQL + ' dbo.mpc_Order_Delivery ON dbo.mpc_Order.OrderID = dbo.mpc_Order_Delivery.OrderID';        
        SET @SQL = @SQL + ' ) AS T1';
        IF @Region IS NOT NULL
            BEGIN
                --通過SPLIT函數分割生成結果集
                SET @SQL = @SQL + ' WHERE Region IN(SELECT * FROM DBO.F_SPLIT(@Region,'',''))';                
            END
        SET @SQL = @SQL + ' GROUP BY Region, ' + @QueryBy + '(OrderTime)';

        --申明參數
        SET @PARAM = N'@Region NVARCHAR(1000),@QueryBy NVARCHAR(10)';

        --執行存儲過程
        EXEC sys.sp_executesql @SQL,@PARAM,@Region = @Region,@QueryBy = @QueryBy
    END
END

調用方式也比較簡單,相比第一種不用輸入那么多的單引號:

EXEC    [dbo].[QueryAgentOrder]
        @Region = N'天津市-市轄區-和平區,吉林省-長春市-市轄區',
        @QueryBy = N'month'

調用結果:

附:分割函數如下:

create function f_split(@SourceSql varchar(8000),@StrSeprate varchar(10))
returns @temp table(a varchar(100))
--實現split功能 的函數
--date    :2003-10-14
as 
begin
    declare @i int
    set @SourceSql=rtrim(ltrim(@SourceSql))   --去掉字符中的空格
    set @i=charindex(@StrSeprate,@SourceSql)  --找分割符在字符中的位置
    while @i>=1
    begin
        insert @temp values(left(@SourceSql,@i-1))  
        set @SourceSql=substring(@SourceSql,@i+1,len(@SourceSql)-@i)
        set @i=charindex(@StrSeprate,@SourceSql)
    end
    if @SourceSql<>'' 
       insert @temp values(@SourceSql)
    return 
end

 

 

最后


上述兩種方法都可以實現在IN中傳遞字符串變量,對於防注方面,感覺第二種應該比第一種好,有精於此塊的朋友,也請不吝賜教。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM