2016-08-01 20 views
0

Ich habe ein paar Probleme mit der Übergabe eines Nullable-Parameters an eine gespeicherte Prozedur, die dynamische Abfragen verwendet, um eine Tabelle auszuführen.SQL Server: Übergabe von Nullable-Parametern an eine gespeicherte Prozedur mit dynamischer Abfrage

Ich muss in der Lage sein, null an alle Parameter zu übergeben, die Nullable sein können. Wenn ich diesen Code aus dynamischem SQL herausnehme, funktioniert es gut.

Der Code:

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 

Die Tabelle:

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

Sie verwenden 'sp_executesql'. Verwenden Sie es nun korrekt und übergeben Sie die Werte als * parameters *, anstatt die Abfrage SQL-Injection- und potenziellen Syntaxfehlern auszusetzen. –

+0

Das Problem sieht so aus, als wollten Sie überprüfen, ob "NULL" (als String) null ist (nicht). Du könntest etwas wie '' '' + ISNULL (@var, '') + '' '=' '' 'oder so ähnlich machen. Oder was Gordon mit den richtigen Parametern gesagt hat. – ZLK

+0

sollten Sie die Option RECOMPILE für diese gespeicherte Prozedur verwenden, https://msdn.microsoft.com/en-ie/library/ms190439.aspx – Jodrell

Antwort

1

Sie sollten sp_executesql mit Parametern werden. Hier zeige ich nur einer der Parameter @Company nur

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)) 

und dann sp_executesql verwenden mit Parametern

EXEC sp_executesql @DynamicQuery_CurrentActual, N'@Company nvarchar(1)', @Company