2016-08-01 67 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 
相关问题