2016-03-24 15 views
1

Ich habe irgendwo gelesen, dass es nicht möglich ist, gespeicherte Prozeduren aus dynamischen Abfragen zu erstellen.Muss die Skalarvariable "@query" dynamic tsql zur gespeicherten Prozedur deklarieren

Ich habe einen Fehler, dass ich skalare Variable nicht deklariert habe.

Hier ist mein Tsql dynamischer Bericht, der arbeitet:

DECLARE 
@cols AS NVARCHAR(MAX), 
@selcols AS NVARCHAR(MAX), 
@query AS NVARCHAR(MAX), 
@startdate datetime, 
@enddate datetime, 
@paramdef nvarchar(max) 

SET @startdate = '2013-02-01' 
SET @enddate = '2013-05-10'; 
SET @paramdef = '@startdate datetime, @enddate datetime'; 


SELECT 
@selcols = STUFF((SELECT ','+'ISNULL(' + QUOTENAME(convert(varchar(10), [Date], 120)) + ', 0) AS ' + QUOTENAME(convert(varchar(10), [Date], 120)) 
       FROM AdeccoView 
       --where datein > @startdate 
       -- and datein <= @enddate 
       GROUP BY [Date] 
       ORDER BY [Date] 
       FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') 


    SELECT 
@cols = STUFF((SELECT ',' + QUOTENAME(convert(varchar(10), [Date], 120)) 
       FROM AdeccoView 
       --where datein > @startdate 
       -- and datein <= @enddate 
       GROUP BY [Date] 
       ORDER BY [Date] 
       FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') 

SET @query = N'SELECT CreatedBy,Name, Surname,EventTypeID,Event, '+ @selcols + ',Total 
    from 
    (
     select av.EventTypeID,av.CreatedBy,emp.Name,emp.Surname,Event, 
      convert(varchar(10), [Date], 120) [Date], 
      row_number() over(PARTITION BY [date],av.EventTypeID,av.CreatedBy order BY av.EventTypeID,av.CreatedBy) m, 
      count(*) over(partition by av.CreatedBy,av.EventTypeId) Total 
     from AdeccoView av 
     left join EventType et on et.EventTypeID = av.EventTypeID 
     left join Employee emp on av.CreatedBy = emp.EmployeeD 

    ) x 
    pivot 
    (
     max(m) 
     for [Date] in ('[email protected]+') 
    ) p ' 

exec sp_executesql @query, @paramdef, @startdate = @startdate, @enddate [email protected]; 

Und jetzt

ich es will durch Stored Procedure oder eine Ansicht (vielleicht einfacher ist, später in Entity Framework zu implementieren 6, asp.net). So sieht meine gespeicherte Prozedur wie folgt aus:

CREATE PROCEDURE GetEmployees 
(@startDateInput datetime = NULL, @endDateInput datetime = NULL) 
AS 
SET NOCOUNT ON; 

DECLARE 
@cols AS NVARCHAR(MAX), 
@selcols AS NVARCHAR(MAX), 
@query AS NVARCHAR(MAX), 
@startdate datetime, 
@enddate datetime, 
@paramdef nvarchar(max) 

SET @startdate = @startDateInput 
SET @enddate = @endDateInput 
SET @paramdef = '@startdate datetime, @enddate datetime'; 


SELECT 
@selcols = STUFF((SELECT ','+'ISNULL(' + QUOTENAME(convert(varchar(10), [Date], 120)) + ', 0) AS ' + QUOTENAME(convert(varchar(10), [Date], 120)) 
       FROM AdeccoView 
       --where datein > @startdate 
       -- and datein <= @enddate 
       GROUP BY [Date] 
       ORDER BY [Date] 
       FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') 


SELECT 
@cols = STUFF((SELECT ',' + QUOTENAME(convert(varchar(10), [Date], 120)) 
       FROM AdeccoView 
       --where datein > @startdate 
       -- and datein <= @enddate 
       GROUP BY [Date] 
       ORDER BY [Date] 
       FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') 

SET @query = N'SELECT CreatedBy,Name, Surname,EventTypeID,Event, '+ @selcols + ',Total 
    from 
    (
     select av.EventTypeID,av.CreatedBy,emp.Name,emp.Surname,Event, 
      convert(varchar(10), [Date], 120) [Date], 
      row_number() over(PARTITION BY [date],av.EventTypeID,av.CreatedBy order BY av.EventTypeID,av.CreatedBy) m, 
      count(*) over(partition by av.CreatedBy,av.EventTypeId) Total 
     from AdeccoView av 
     left join EventType et on et.EventTypeID = av.EventTypeID 
     left join Employee emp on av.CreatedBy = emp.EmployeeD 

    ) x 
    pivot 
    (
     max(m) 
     for [Date] in ('[email protected]+') 
    ) p ' 
    GO 
exec sp_executesql @query, @paramdef, @startdate = @startDateInput, @enddate [email protected]; 

EDIT:

Hier ist meine aktualisierte Code mit BEGIN und END, entfernt GO-Anweisung

CREATE PROCEDURE GetEmployees 
(@startDateInput datetime = NULL, @endDateInput datetime = NULL) 
AS 
SET NOCOUNT ON; 
BEGIN 
DECLARE 
@cols AS NVARCHAR(MAX), 
@selcols AS NVARCHAR(MAX), 
@query AS NVARCHAR(MAX), 
@startdate datetime, 
@enddate datetime, 
@paramdef nvarchar(max) 

SET @startdate = @startDateInput 
SET @enddate = @endDateInput 
SET @paramdef = '@startdate datetime, @enddate datetime'; 


SELECT 
@selcols = STUFF((SELECT ','+'ISNULL(' + QUOTENAME(convert(varchar(10), [Date], 120)) + ', 0) AS ' + QUOTENAME(convert(varchar(10), [Date], 120)) 
       FROM AdeccoView 
       --where datein > @startdate 
       -- and datein <= @enddate 
       GROUP BY [Date] 
       ORDER BY [Date] 
       FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') 


SELECT 
@cols = STUFF((SELECT ',' + QUOTENAME(convert(varchar(10), [Date], 120)) 
       FROM AdeccoView 
       --where datein > @startdate 
       -- and datein <= @enddate 
       GROUP BY [Date] 
       ORDER BY [Date] 
       FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') 

SET @query = N'SELECT CreatedBy,Name, Surname,EventTypeID,Event, '+ @selcols + ',Total 
    from 
    (
     select av.EventTypeID,av.CreatedBy,emp.Name,emp.Surname,Event, 
      convert(varchar(10), [Date], 120) [Date], 
      row_number() over(PARTITION BY [date],av.EventTypeID,av.CreatedBy order BY av.EventTypeID,av.CreatedBy) m, 
      count(*) over(partition by av.CreatedBy,av.EventTypeId) Total 
     from AdeccoView av 
     left join EventType et on et.EventTypeID = av.EventTypeID 
     left join Employee emp on av.CreatedBy = emp.EmployeeD 

    ) x 
    pivot 
    (
     max(m) 
     for [Date] in ('[email protected]+') 
    ) p ' 
END 

exec sp_executesql @query, @paramdef, @startdate = @startDateInput, @enddate [email protected]; 

Antwort

2

Die GO vor dem sp_executesql beendet die gespeicherte Prozedur Deklaration. Daher sind die in der gespeicherten Prozedur deklarierten Variablen nicht verfügbar. Mit anderen Worten definiert der Code die gespeicherte Prozedur. Dann versucht es zu laufen:

Beachten Sie, dass überraschenderweise keine der Variablen definiert ist, da sie lokal für die gespeicherte Prozedur sind.

Sie sollten nicht nur die GO entfernen, sondern BEGIN und END verwenden, um den Hauptteil der gespeicherten Prozedur zu definieren.

+0

Anbei finden Sie meinen bearbeiteten Code. Denkst du, dass es jetzt in Ordnung ist? Die gespeicherte Prozedur wurde erfolgreich abgeschlossen. Ich denke, dass deine Antwort Lösung ist. Vielen Dank! – Stefan0309

+0

@ Stefan0309. . . Ihr Code sieht ziemlich vernünftig aus (obwohl ich denke, dass der Text eingerückt sein sollte). –

Verwandte Themen