Ich muss eine große Anzahl von SQL-Anweisungen (Erstellen einer Reihe von Tabellen, Ansichten und gespeicherten Prozeduren) in einem C # -Programm ausführen.
Diese Anweisungen müssen durch GO
Anweisungen getrennt werden , SqlCommand.ExecuteNonQuery()
mögen jedoch keine GO
Anweisungen. Meine Lösung, die ich vermutlich als Referenz veröffentlichen werde, bestand darin, die SQL-Zeichenfolge in GO
Zeilen aufzuteilen und jeden Stapel separat auszuführen.
Gibt es einen einfacheren / besseren Weg?
quelle
TransactionScope
Objekt verwenden möchten, nur die Verbindung mit der aktuellen Umgebungstransaktion herstellen müssen. Überprüfen Sie meine Antwort hier: stackoverflow.com/a/18322938/1268570SqlConnection.InfoMessage
), um das Ergebnis in der C # -Anwendung zu sehen oder das Ergebnis in einertxt
Datei zu speichern, nur um zu wissen, ob das Skript erfolgreich ausgeführt wurde, dasqlcmd
ich kürzlich nach 55 Minuten eine 150-MB-Skriptdatei auf einem Remote-Host ausgeführt habe Zeilen wurden mit diesem Fehler bewirkt,TCP Provider: An existing connection was forcibly closed by the remote host.
,communication link failure
. , keine der betroffenen Zeilen kann bekannt sein, aber ich bin besorgt über Fehlermeldungen beim Ausführen einer datenbankgenerierten Skriptdatei.Dies ist, was ich zusammen geklopft habe, um mein unmittelbares Problem zu lösen.
Es erfordert, dass GO-Befehle in einer eigenen Zeile stehen und keine Blockkommentare erkennen. Daher wird diese Art von Dingen aufgeteilt und verursacht einen Fehler:
quelle
string sql
- Das ist das gesamte Skript. Wenn ich mich auf einen "Stapel" beziehe, meine ich einen Teil des SQL-Codes zwischen zwei "GO" -Anweisungen. Der Code fügtGO
am Ende des Skripts ein a hinzu, sodass der Code im Skriptforeach
den letzten Stapel nicht überspringt, wenn Sie Ihr Skript nicht mit einem beendet habenGO
. Der geschriebene Code führt also das gesamte SQL aus.StringBuilder sqlBatch
stattdessen verwenden.Sie können dazu SQL-Verwaltungsobjekte verwenden . Dies sind dieselben Objekte, mit denen Management Studio Abfragen ausführt. Ich glaube
Server.ConnectionContext.ExecuteNonQuery()
, Sie werden das tun, was Sie brauchen.quelle
Das Batch-Trennzeichen-Schlüsselwort "GO" wird tatsächlich von SQL Management Studio selbst verwendet, damit es weiß, wo die an den Server gesendeten Batches beendet werden sollen, und es wird nicht an den SQL Server übergeben. Sie können das Schlüsselwort sogar in Management Studio ändern, wenn Sie dies wünschen.
quelle
Ich schaue mir das ein paar mal am Ende mit EF-Implementierung an. Ein bisschen modifiziert für
SqlConnection
quelle
Wenn Sie keine SMO-Objekte installieren möchten, können Sie das gplex-Tool verwenden (siehe diese Antwort ).
quelle
Basierend auf der Lösung von Blorgbeard.
quelle
Wenn Sie SMO nicht verwenden möchten, z. B. weil Sie plattformübergreifend sein müssen, können Sie auch die ScriptSplitter-Klasse von SubText verwenden.
Hier ist die Implementierung in C # & VB.NET
Verwendung:
Wenn Sie Probleme mit mehrzeiligen Kommentaren im C-Stil haben, entfernen Sie die Kommentare mit Regex:
Das Entfernen einzeiliger Kommentare finden Sie hier:
quelle
/* Go */
Fall?Ich hatte auch das gleiche Problem, und ich konnte keinen anderen Weg finden, als die einzelne SQL-Operation in separate Dateien aufzuteilen und dann alle nacheinander auszuführen.
Offensichtlich liegt das Problem nicht bei Listen von DML-Befehlen, sondern können ohne GO dazwischen ausgeführt werden. andere Geschichte mit DDL (erstellen, ändern, löschen ...)
quelle
Wenn Sie nicht auf die SMO-Route gehen möchten, können Sie "GO" nach ";" suchen und ersetzen. und die Abfrage wie Sie würden. Beachten Sie, dass nur die letzte Ergebnismenge zurückgegeben wird.
quelle
Ich habe dies heute erreicht, indem ich mein SQL aus einer Textdatei in eine Zeichenfolge geladen habe. Ich habe dann die String-Split-Funktion verwendet, um den String in einzelne Befehle zu unterteilen, die dann einzeln an den Server gesendet wurden. Simples :)
Ich habe gerade festgestellt, dass Sie sich auf \ nGO aufteilen müssen, nur für den Fall, dass die Buchstaben GO in einem Ihrer Tabellennamen usw. erscheinen. Ich schätze, ich hatte Glück!
quelle
Wenn Sie SMO nicht verwenden möchten (was besser ist als die unten stehende Lösung, aber ich möchte eine Alternative angeben ...), können Sie Ihre Abfrage mit dieser Funktion aufteilen.
Es ist:
String Proof (Beispieldruck 'no go')
quelle
Verwenden Sie die folgende Methode, um die Zeichenfolge zu teilen und Stapel für Stapel auszuführen
quelle
Um Dritte, reguläre Ausdrücke, Speicherkosten und schnelle Arbeit mit großen Skripten zu vermeiden, habe ich meinen eigenen Stream-basierten Parser erstellt. Es
kann Kommentare mit - oder / ** / erkennen
kann String-Literale mit 'oder "erkennen
und andere Konstruktionen wie
Wie benutzt man
Stream-basierter SQL-Skriptleser
quelle
Ich hatte das gleiche Problem in Java und habe es mit ein bisschen Logik und Regex gelöst. Ich glaube, dass die gleiche Logik angewendet werden kann. Zuerst lese ich aus der slq-Datei in den Speicher. Dann wende ich die folgende Logik an. Es ist so ziemlich das, was zuvor gesagt wurde, aber ich glaube, dass die Verwendung von Regex-Wort gebunden sicherer ist als die Erwartung eines neuen Zeilenzeichens.
Dadurch wird die SQL-Zeichenfolge im Wesentlichen in ein Array von SQL-Zeichenfolgen aufgeteilt. Der reguläre Ausdruck besteht im Wesentlichen darin, vollständige "go" -Wörter entweder in Klein- oder Großbuchstaben zu erkennen. Anschließend führen Sie die verschiedenen Abfragen nacheinander aus.
quelle
insert into books values ('1478355824', 'An Introduction To Programming in Go (paperback)', 9.00)
Ich bin auf dasselbe Problem gestoßen und habe es schließlich durch einen einfachen String-Ersatz gelöst, wobei das Wort GO durch ein Semikolon (;) ersetzt wurde.
Alles scheint gut zu funktionieren, wenn Skripte mit Inline-Kommentaren, Blockkommentaren und GO-Befehlen ausgeführt werden
quelle
--
, die enthalten .Für alle, die noch das Problem haben. Sie können offizielles Microsoft SMO verwenden
https://docs.microsoft.com/en-us/sql/relational-databases/server-management-objects-smo/overview-smo?view=sql-server-2017
quelle
Zu schwer :)
Erstellen Sie ein Array von Zeichenfolgen str [] und ersetzen Sie GO durch ", @":
Das ist alles, viel Spaß.
quelle