it-swarm.com.de

Keine Felder für in SQL gespeicherte dynamische SQL-Prozedur mit SET FMTONLY

Ich habe folgendes SP, das korrekt funktioniert, wenn es eigenständig ausgeführt wird:

USE [Orders]
GO
SET FMTONLY OFF; 

CREATE PROCEDURE [dbo].[Get_Details_by_Type]

@isArchived varchar(10),
@Type varchar(50)

AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;
    declare @sqlQuery nvarchar(max)
          IF(@isArchived = 'ALL')
            BEGIN
                set @sqlQuery  = 'SELECT *  FROM [dbo].[Orders] 
              WHERE ' + @Type + ' != € 
                ORDER BY [IDNumber]'
                exec sp_executesql @sqlQuery
            END
        ELSE
            BEGIN
            set @sqlQuery  = 'SELECT * FROM [dbo].[Orders] 
          WHERE ' + @Type + ' != € AND [isArchived] = ' + @isArchived + ' ORDER BY [IDNumber]'
            exec sp_executesql @sqlQuery
        END
END
SET FMTONLY ON; 

Das Problem, das ich habe, ist, dass wenn ich ein DataSet für einen SSRS-Bericht hinzufüge, keine Felder/Spalten im Abschnitt Felder gezogen werden. Ich vermute, es liegt an der dynamischen SQL?

Wie kann ich das beheben?

15
sd_dracula

Das Problem
Gespeicherte Prozeduren, die Dynamic Sql- und Temp-Tabellen enthalten, sind das Verderben von Assistenten wie SSRS- und ORM-Generatoren wie Linq2SQL und EF Reverse Engineering-Tools.

Dies liegt daran, dass die Tools SET FMTONLY ON; (oder in jüngster Zeit sp_describe_first_result_set ) vor der Ausführung von PROC verwendet werden, um das von PROC erstellte Resultset-Schema abzuleiten, sodass Zuordnungen für die ReportViewer-Benutzeroberfläche generiert werden können. Allerdings führen weder FMTONLY ON noch sp_describe_first_result den PROC tatsächlich aus.

z.B. Das Tool wird so etwas tun:

SET FMTONLY ON;
EXEC dbo.MyProc NULL;

Einige Problemumgehungen: 

  • Manuelles Bearbeiten der RDL/RDLC-Datei, um die tatsächlichen Spaltennamen und -typen der Ergebnismenge einzufügen.
  • Vorübergehendes Löschen der realen Prozedur durch eine, die einen Datensatz mit null oder mehr Zeilen mit den von der realen Prozedur zurückgegebenen Datentypen und Spaltennamen zurückgibt, den Assistenten ausführt und dann die echte Prozedur zurücksetzt.
  • Fügen Sie SET FMTONLY OFF; als erste Zeile in PROC hinzu - dies erzwingt die Ausführung von PROC (obwohl Ihre Prozedur möglicherweise aufgrund von Null- oder Dummy-Parametern fehlschlägt, die vom Tool übergeben werden). Außerdem ist FMTONLYveraltet
  • Fügen Sie am Anfang des proc eine Dummy-Anweisung hinzu, die das tatsächliche Schema (die Schemata) der Ergebnismenge (n) zurückgibt, die in einen bedingten Zweig eingeschlossen sind, der niemals ausgeführt wird.

Hier ist ein Beispiel für den letzten Hack:

CREATE PROCEDURE [dbo].[Get_Details_by_Type]
  @isArchived varchar(10),
  @Type varchar(50)
AS
BEGIN
   -- For FMTONLY ON tools only
   IF 1 = 2
     BEGIN
       -- These are the actual column names and types returned by the real proc
       SELECT CAST('' AS NVARCHAR(20)) AS Col1, 
              CAST(0 AS DECIMAL(5,3)) AS Col2, ...
     END;
-- Rest of the actual PROC goes here

FMTONLY ON/sp_describe_first_result_set werden von der Dummy-Bedingung getäuscht und übernehmen das Schema vom nie ausgeführten Zweig.

Nebenbei gesagt, für Ihren eigenen Verstand würde ich vorschlagen, dass Sie nicht SELECT * in Ihrem PROC - stattdessen explizit alle echten Spaltennamen auflisten, die von Orders zurückgegeben werden.

Stellen Sie schließlich sicher, dass Sie die SET FMTONLY ON;-Anweisung nicht in Ihr proc aufnehmen (von Ihrem Code oben!).

END - Proc
GO **
SET FMTONLY ON; ** This isn't part of the Proc!
19
StuartLC

Wenn noch jemand mit diesem Problem konfrontiert ist, habe ich ein ähnliches Problem mit ssrs und dynamischer SQL gelöst. 

  1. Für ssrs, um die Felder aus dem SP richtig zuzuordnen, 
  2. wählen Sie unter Abfragetyp die Option "Text" aus. 
  3. geben Sie den SP Namen und die Parameter ein, wie Sie es aus einem SSMS-Fenster aufrufen. sp_YourStoredProc @[email protected]
  4. Klicken Sie auf die Schaltfläche zum Aktualisieren der Felder. 
  5. Wenn die Anweisung ausgeführt wird, werden die Felder aktualisiert und Ihre Matrix wird aufgefüllt.

BTW, ich benutze SQL 2012

Hoffe das hilft.

4
ChadB

Folgendes habe ich getan, um das Problem zu überwinden - Felder sind nicht in SSRS aufgeführt

  1. Ursprünglich habe ich eine Prozedur gespeichert; und es gibt Daten zurück, wenn ich das Dataset ausführen. Die Felder sind jedoch nicht in SSRS aufgeführt

  2. Ich habe den Text der gespeicherten Prozedur kopiert und die Datenmenge als Text anstelle von Stored Procedure erstellt. Siehe Gewusst wie: Aktualisieren von Feldern für ein Dataset

  3. Es gab Fehler und ich habe diese Fehler "ignoriert". Refer Das SQL-Konstrukt oder die Anweisung Declare-Cursor-SQL wird nicht unterstützt.

  4. Jetzt habe ich überprüft, dass die Felder für SSRS ausgefüllt sind

  5. Jetzt habe ich den Datensatz aktualisiert, um meinen Stored Procedure zu verwenden.

Führen Sie nach den obigen Schritten eine Aktualisierung des Datasets wie folgt aus:

enter image description here

1
Lijo

Befolgen Sie die angegebenen Schritte 

•   Delete DataSource. Create a new Data Source .
•   Delete DataSet. Create a new DataSet .
•   Use Query Designer. 
•   Add valid parameter when asked  .
•   One should get result for provided prarameters . 
    Donot click on refresh Field .
•   Then Report parameters and Report field will appear .
•   Now Filter criteria should work.

ODER 

**Add the Report field manually . It works.**

Wenn die gespeicherte Prozedur keine Schemadaten oder Metadaten abrufen kann, sollten Sie die Berichtsfelder manuell angeben. 

0
Bhushan Mahajan

Dies ist eine sehr späte Ergänzung, aber für diejenigen, die noch nicht mit SSRS/Report-Design vertraut sind: Denken Sie daran, die Reihenfolge der Parameter im Bereich Berichtsdaten in Visual Studio zu überprüfen. Sie werden von oben nach unten erstellt, sodass ein Parameter oben nicht von einem Parameter unten abhängen kann. Dies war ein Problem, das ich mit einem Bericht hatte, aber die Fehlermeldung, die ich erhalten habe, hat das nicht gesagt, also habe ich meinen Schwanz stundenlang verfolgt und versucht, ihn zu lösen. 

0

Ich will keinen toten Thread wiederbeleben, sondern hat mich verrückt gemacht, als wir unsere Berichte von SSRS 2005 auf SSRS 2016 aktualisiert haben, wo Stored Procedures Openquery verwendet hat.

Wir haben es auf Berichte beschränkt, die Felder mit leeren Werten enthielten. Deshalb haben wir dies am Anfang der gespeicherten Prozedur hinzugefügt:

SET CONCAT_NULL_YIELDS_NULL OFF;

wir mussten also nicht jedes Feld CAST.

0
Phelzier