SQL Server:使用动态查询将可空参数传递给存储过程
问题描述:
将可空参数传递给使用动态查询运行表的存储过程时遇到一些问题。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]
答
您应该使用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
您正在使用'sp_executesql'。现在,正确使用它,并传递as * parameters *中的值,而不是将查询暴露给SQL注入和潜在的语法错误。 –
这个问题看起来像你试图检查'NULL'(作为一个字符串)是否为空(它不是)。你可以做一些像''''+ ISNULL(@var,'')+'''='''''或类似的东西。或者是Gordon用正确的参数说的。 – ZLK
您应该使用此存储过程的RECOMPILE选项,https://msdn.microsoft.com/en-ie/library/ms190439.aspx – Jodrell