Benutzer mit den meisten Antworten
Ergebnise einer SP im Script verwenden

Frage
-
Hallo zusammen,
ich habe gerade ein Brett vor dem Kopf...
Es müssen zwei SP's verwendet werden die von einem Drittanbieter erstellt und in dessen Produkt abgelegt/verwendet werden. Da ich nicht jedesmal meine Skripte anpassen möchte, plane ich die SP's zu verwenden.
Die erste SP gibt eine "Tabelle" mit einer Zeile und 5 Spalten zurück, die zweite SP gibt drei "Tabellen" mit je einer Zeile und unterschiedlicher Anzahl Spalten zurück.
Die Spalten sind soweit eindeutig benannt.
Da keine der beiden SP's mit Output-Parameter arbeitet, wie kann ich das ResultSet in Variablen etc abfassen damit ich mit den Werten weiter arbeiten kann?
Viele Grüsse,
Daniel
Antworten
-
Hallo Daniel,
wo willst Du das machen? In T-SQL? Oder was anderem? Falls letzteres: Was genau? C#? ...?
Zudem müsste man genauer wissen, was die SP wirklich zurückgibt. "Tabellen" heißt nun? Richtige Tabellen mit jeweils definierten Spalten? Oder was anderes? Frage nur, weil Du "Tabellen" in Anführungszeichen geschrieben hast, nicht dass das eigentlich was ganz anderes ist.
Die Tabellenrückgabe einer SP kannst Du vereinfacht gesagt mit einer Tabellenvariable und anschließendem INSERT INTO in ebendiese auslesen.
Also bspw. sowas:
DECLARE @Tabelle TABLE( ID INT NOT NULL, Name nvarchar( 255 ) NULL ); INSERT INTO @Tabelle EXEC DeineSP <Parameter>;
Dabei gibt es aber auch einiges zu beachten. Schau dir daher doch bitte auch mal diesen Artikel an:
How to Share Data between Stored Procedures
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport
- Bearbeitet Stefan FalzModerator Samstag, 9. März 2019 09:52
- Als Antwort markiert DniBo Mittwoch, 13. März 2019 18:24
-
Hi Daniel,
als Anregung hier mal eine VB ConsolenDemo, mit der 2 Ergebnis-Sets in den Client mit einem Zugriff gelesen werden, einmal in ein DataSet mittels DataAdapter, das zweite Execute (Execute2) mit einem "Weiterschalten" des DataReaders. Im Execute1 erkannt der DataAdapter, dass es zwei Ergebnis-Sets gibt und fügt weitere DataTables mit dem TableName= Table1 usw. dem DataSet hinzu.Imports System.Data.SqlClient Module Module04 Sub Main() Try Dim c As New Demo c.Execute1() c.Execute2() Catch ex As Exception Console.WriteLine(ex.ToString) End Try Console.WriteLine("Continue enter key") Console.ReadKey() End Sub Friend Class Demo Private cnString As String = "Data Source=fl-laptop5;Initial Catalog=DemoDB;Integrated Security=True" Friend Sub Execute1() Dim ds As New DataSet Using da As New SqlDataAdapter("Select * from Tab1; Select * from Tab2;", cnString) da.Fill(ds) End Using For Each dt As DataTable In ds.Tables Console.WriteLine($"{dt.TableName} - {dt.Rows.Count}") Next End Sub Friend Sub Execute2() Using cn As New SqlConnection(cnString) cn.Open() Using cmd As New SqlCommand("Select * from Tab1; Select * from Tab2;", cn) Dim rdr As SqlDataReader = cmd.ExecuteReader While rdr.Read Console.WriteLine(rdr(0).ToString) End While rdr.NextResult() While rdr.Read Console.WriteLine(rdr(0).ToString) End While End Using End Using End Sub End Class End Module
--
Viele Grüsse / Best Regards
Peter Fleischer (former MVP for Developer Technologies)
Homepage, Tipps, Tricks- Bearbeitet Peter Fleischer Samstag, 9. März 2019 11:42
- Als Antwort markiert DniBo Mittwoch, 13. März 2019 18:24
Alle Antworten
-
Hallo Daniel,
wo willst Du das machen? In T-SQL? Oder was anderem? Falls letzteres: Was genau? C#? ...?
Zudem müsste man genauer wissen, was die SP wirklich zurückgibt. "Tabellen" heißt nun? Richtige Tabellen mit jeweils definierten Spalten? Oder was anderes? Frage nur, weil Du "Tabellen" in Anführungszeichen geschrieben hast, nicht dass das eigentlich was ganz anderes ist.
Die Tabellenrückgabe einer SP kannst Du vereinfacht gesagt mit einer Tabellenvariable und anschließendem INSERT INTO in ebendiese auslesen.
Also bspw. sowas:
DECLARE @Tabelle TABLE( ID INT NOT NULL, Name nvarchar( 255 ) NULL ); INSERT INTO @Tabelle EXEC DeineSP <Parameter>;
Dabei gibt es aber auch einiges zu beachten. Schau dir daher doch bitte auch mal diesen Artikel an:
How to Share Data between Stored Procedures
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport
- Bearbeitet Stefan FalzModerator Samstag, 9. März 2019 09:52
- Als Antwort markiert DniBo Mittwoch, 13. März 2019 18:24
-
Hi Stefan,
sorry, vergessen, ist in T-SQL :-)
Mit Tabellen meine ich tatsächlich das die SP drei Tabellen zurück liefert.
An eine temporäre Sitzungs-Tabelle hatte ich auch schon gedacht, denke das hat keine nennenswerte Auswirkung wenn ich die Tabelle rund 10.000 mal erstelle/lösche?
Andere Frage, wie mache ich das wenn die SP nach dem Ausführen drei Result-Sets zurückgibt?
Gruss,
Daniel
- Bearbeitet DniBo Samstag, 9. März 2019 10:05
-
Hallo Daniel,
ich würde Tabellenvariablen anstelle von temporären Tabellen verwenden. Solltest Du die Inhalte dauerhaft und/oder auch außerhalb deiner SP benötigen, kannst Du auch eine richtige Tabelle verwenden und die ggfs. mit TRUNCATE leeren, bevor Du den nächsten Lauf startest.
Bei mehreren Resultsets wird es doch etwas schwerer/umständlicher. Welche SQL Server Version setzt Du ein? Falls eine Version mit direktem JSON Support, schau dir mal diesen Artikel an:
Using Stored Procedures in SQL Server that return several results.
IMHO ist es aber doch ein ziemlich schlechter Programmierstil, in einer SP mehrere Resultsets zurückzuliefern. Es kommt zwar immer auf den genauen Sinn und Zweck an, allerdings hat mir das noch nie gefallen und ich selbst hatte auch noch nie einen Anwendungszweck, bei dem ich das gebraucht hätte.
---
BTW: In anderen Umgebungen (.NET, ...) kannst Du eine SP mit mehreren Resultsets problemlos verwenden und die einzelnen Ergebnisse durchgehen. Aber das nutzt Du ja nicht.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport- Bearbeitet Stefan FalzModerator Samstag, 9. März 2019 11:06
-
Hi Daniel,
als Anregung hier mal eine VB ConsolenDemo, mit der 2 Ergebnis-Sets in den Client mit einem Zugriff gelesen werden, einmal in ein DataSet mittels DataAdapter, das zweite Execute (Execute2) mit einem "Weiterschalten" des DataReaders. Im Execute1 erkannt der DataAdapter, dass es zwei Ergebnis-Sets gibt und fügt weitere DataTables mit dem TableName= Table1 usw. dem DataSet hinzu.Imports System.Data.SqlClient Module Module04 Sub Main() Try Dim c As New Demo c.Execute1() c.Execute2() Catch ex As Exception Console.WriteLine(ex.ToString) End Try Console.WriteLine("Continue enter key") Console.ReadKey() End Sub Friend Class Demo Private cnString As String = "Data Source=fl-laptop5;Initial Catalog=DemoDB;Integrated Security=True" Friend Sub Execute1() Dim ds As New DataSet Using da As New SqlDataAdapter("Select * from Tab1; Select * from Tab2;", cnString) da.Fill(ds) End Using For Each dt As DataTable In ds.Tables Console.WriteLine($"{dt.TableName} - {dt.Rows.Count}") Next End Sub Friend Sub Execute2() Using cn As New SqlConnection(cnString) cn.Open() Using cmd As New SqlCommand("Select * from Tab1; Select * from Tab2;", cn) Dim rdr As SqlDataReader = cmd.ExecuteReader While rdr.Read Console.WriteLine(rdr(0).ToString) End While rdr.NextResult() While rdr.Read Console.WriteLine(rdr(0).ToString) End While End Using End Using End Sub End Class End Module
--
Viele Grüsse / Best Regards
Peter Fleischer (former MVP for Developer Technologies)
Homepage, Tipps, Tricks- Bearbeitet Peter Fleischer Samstag, 9. März 2019 11:42
- Als Antwort markiert DniBo Mittwoch, 13. März 2019 18:24
-
Hallo Peter,
danke für den Tipp :-)
Ich komme immer mehr zum Ergebnis das ich ein Tool schreiben muss. Die Tabellen und SP's sollen nicht verändert, benötigtes nicht hinzugefügt werden weil das System von einem Drittanbieter ist.
Verstehe da den Entscheid von unserem Management nicht, aber so soll es sein.
Was gegen ein Tool spricht, es ist nicht mehr wartbar von anderen Kollegen die ggf kein VB.net können.
Mit Powershell dürfte das auch etwas schwierig werden, wäre aber eine Sprache die auch andere können.
:-)
Gruss,
Daniel -
Hi Daniel,
mein Beispiel sollte nur ein Demo sein, die analog praktisch 1:1 auch als PowerShell implementiert werden kann. Für jemand, der PowerShell beherrscht, sollte das mit meiner Demo ohne Aufwand möglich sein.
--
Viele Grüsse / Best Regards
Peter Fleischer (former MVP for Developer Technologies)
Homepage, Tipps, Tricks- Bearbeitet Peter Fleischer Samstag, 9. März 2019 14:04
-
I.d.R. sollte eine SP max. 1 Tabelle zurückgeben.
In diesem Fall reicht da ein "Select * from (exec MySp()) as Hugo".Gibt eine Prozedur mehr als 1 Tabelle zurück, kann dies nur durch einen Client verwendet werden.
Hierfür erstellt man ein SQLCommand und erhält den Reader mit Execute.Der Reader wiederum hat eine Methode SQlDataReader.NextResult(), die den Reader auf das nächste Resultset wechselt.
https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqldatareader.nextresult?redirectedfrom=MSDN&view=netframework-4.7.2#System_Data_SqlClient_SqlDataReader_NextResulthttps://stackoverflow.com/questions/12715620/how-do-i-return-multiple-result-sets-with-sqlcommand/12715650
Dies setzt natürlich voraus, dass die SP dies auch so tut und nicht 3 temporäre Tabellen namentlich erstellt.
Diese wäre dann einfach per "Select * from Temptable" abfragbar.