2016-08-01 123 views
0

將可空參數傳遞給使用動態查詢運行表的存儲過程時遇到一些問題。SQL Server:使用動態查詢將可空參數傳遞給存儲過程

我需要做的是將null傳遞給所有可爲空的參數。如果我從動態SQL中取出這些代碼,它可以正常工作。

代碼:

ALTER proc [dbo].[TEST_spExtractNL_Dynamic] 
    @StartDate date, 
    @Company nvarchar(1) = null, 
    @Location1 nvarchar(1) = null, 
    @Location2 nvarchar(1) = null, 
    @Department nvarchar(1) = null, 
    @P1 nvarchar(1) = null, 
    @P2 nvarchar(1) = null, 
    @P3 nvarchar(1) = null, 
    @P4 nvarchar(1) = null, 
    @P5 nvarchar(1) = null, 
    @P6 nvarchar(1) = null, 
    @P7 nvarchar(1) = null, 
    @P8 nvarchar(1) = null 
as 
begin 
    Create table #TempTable 
    (
     [Type] [float] NOT NULL, 
     [Description] [nvarchar](100) NOT NULL 
    ) 

    DECLARE @DynamicQuery_CurrentActual AS NVARCHAR(MAX) 
    SET @DynamicQuery_CurrentActual = N'SELECT 
              SUM([Budget]) * -1 as [Type], 
              ''Current Actual'' as [Description] 
             FROM [TS_Group_Reports].[dbo].[SDCG_FINREP_DataDump] 
             WHERE 
    [Date] BETWEEN ''' + CONVERT(VARCHAR(10),DATEFROMPARTS(YEAR(@StartDate),MONTH(@StartDate),1), 101) + ''' AND ''' + CONVERT(VARCHAR(10),EOMONTH(@StartDate), 101) + ''' 
    AND 
    (''' + @Company + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),1,1) = ''' + @Company + ''')) 
    AND 
    (''' + @Location1 + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),2,1) = ''' + @Location1 + ''')) 
    AND 
    (''' + @Location2 + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),3,1) = ''' + @Location2 + ''')) 
    AND 
    (''' + @Department + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),4,1) = ''' + @Department + ''')) 

    AND 
    (''' + @P1 + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),5,1) = ''' + @P1 + ''')) 
    AND 
    (''' + @P2 + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),6,1) = ''' + @P2 + ''')) 
    AND 
    (''' + @P3 + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),7,1) = ''' + @P3 + ''')) 
    AND 
    (''' + @P4 + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),8,1) = ''' + @P4 + ''')) 
    AND 
    (''' + @P5 + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),9,1) = ''' + @P5 + ''')) 
    AND 
    (''' + @P6 + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),10,1) = ''' + @P6 + ''')) 
    AND 
    (''' + @P7 + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),11,1) = ''' + @P7 + ''')) 
    AND 
    (''' + @P8 + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),12,1) = ''' + @P8 + ''')) 
    AND 
    [Type] like ''_A''' 

DECLARE @DynamicQuery_CurrentBudget AS NVARCHAR(MAX) 
SET @DynamicQuery_CurrentBudget = 
N'SELECT 
    sum([Budget]) * -1 as [Type] 
    ,''Current Budget'' as [Description] 
FROM [TS_Group_Reports].[dbo].[SDCG_FINREP_DataDump] 
WHERE 
    [Date] BETWEEN ''' + CONVERT(VARCHAR(10),DATEFROMPARTS(YEAR(@StartDate),MONTH(@StartDate),1), 101) + ''' AND ''' + CONVERT(VARCHAR(10),EOMONTH(@StartDate), 101) + ''' 
    AND 
    (''' + @Company + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),1,1) = ''' + @Company + ''')) 
    AND 
    (''' + @Location1 + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),2,1) = ''' + @Location1 + ''')) 
    AND 
    (''' + @Location2 + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),3,1) = ''' + @Location2 + ''')) 
    AND 
    (''' + @Department + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),4,1) = ''' + @Department + ''')) 

    AND 
    (''' + @P1 + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),5,1) = ''' + @P1 + ''')) 
    AND 
    (''' + @P2 + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),6,1) = ''' + @P2 + ''')) 
    AND 
    (''' + @P3 + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),7,1) = ''' + @P3 + ''')) 
    AND 
    (''' + @P4 + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),8,1) = ''' + @P4 + ''')) 
    AND 
    (''' + @P5 + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),9,1) = ''' + @P5 + ''')) 
    AND 
    (''' + @P6 + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),10,1) = ''' + @P6 + ''')) 
    AND 
    (''' + @P7 + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),11,1) = ''' + @P7 + ''')) 
    AND 
    (''' + @P8 + ''' IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),12,1) = ''' + @P8 + ''')) 
    AND 
    [Type] like ''_B''' 

    insert into #TempTable 
     EXEC sp_executesql @DynamicQuery_CurrentActual 

    insert into #TempTable 
     EXEC sp_executesql @DynamicQuery_CurrentBudget 

    select * 
    from #TempTable 
END 

表:

CREATE TABLE [dbo].[SDCG_FINREP_DataDump] 
(
    [ID] [int] IDENTITY(1,1) NOT NULL, 
    [Accont] [bigint] NOT NULL, 
    [Description] [nvarchar](100) NOT NULL, 
    [Date] [date] NOT NULL, 
    [Budget] [float] NOT NULL, 
    [Type] [nvarchar](5) NOT NULL, 

    CONSTRAINT [PK_SDCG_FINREP_DataDump] 
     PRIMARY KEY CLUSTERED 
) ON [PRIMARY] 
+3

您正在使用'sp_executesql'。現在,正確使用它,並傳遞as * parameters *中的值,而不是將查詢暴露給SQL注入和潛在的語法錯誤。 –

+0

這個問題看起來像你試圖檢查'NULL'(作爲一個字符串)是否爲空(它不是)。你可以做一些像''''+ ISNULL(@var,'')+'''='''''或類似的東西。或者是Gordon用正確的參數說的。 – ZLK

+0

您應該使用此存儲過程的RECOMPILE選項,https://msdn.microsoft.com/en-ie/library/ms190439.aspx – Jodrell

回答

1

您應該使用sp_executesql與參數。在這裏我只展示了參數@Company的一個只有

SET @DynamicQuery_CurrentBudget = 
N'SELECT 
    sum([Budget]) * -1 as [Type] 
    ,''Current Budget'' as [Description] 
FROM [TS_Group_Reports].[dbo].[SDCG_FINREP_DataDump] 
WHERE 
    [Date] BETWEEN ''' + CONVERT(VARCHAR(10),DATEFROMPARTS(YEAR(@StartDate),MONTH(@StartDate),1), 101) + ''' AND ''' + CONVERT(VARCHAR(10),EOMONTH(@StartDate), 101) + ''' 
    AND 
    ('@Company IS NULL OR (SUBSTRING(CAST([Accont] as nvarchar(12)),1,1) = @Company)) 

,然後使用sp_executesql的帶參數

EXEC sp_executesql @DynamicQuery_CurrentActual, N'@Company nvarchar(1)', @Company 
相關問題