J'ai besoin d'exécuter un grand ensemble d'instructions SQL (créant un tas de tables, vues et procédures stockées) à partir d'un programme C #.
Ces instructions doivent être séparées par des GO
instructions, mais SqlCommand.ExecuteNonQuery()
n'aime pas les GO
instructions. Ma solution, que je suppose que je publierai pour référence, était de diviser la chaîne SQL en GO
lignes et d'exécuter chaque lot séparément.
Existe-t-il un moyen plus simple / meilleur?
la source
TransactionScope
objet, il vous suffit d'enregistrer la connexion avec la transaction ambiante actuelle. Vérifiez ma réponse ici: stackoverflow.com/a/18322938/1268570SqlConnection.InfoMessage
) pour voir le résultat dans l'application C # ou enregistrer le résultat dans untxt
fichier, juste pour savoir si le script a été exécuté avec succès, car récemment en utilisantsqlcmd
quand j'ai exécuté un fichier de script de 150 Mo sur un hôte distant, après 55 minutes les lignes ont été effectuées avec cette erreur,TCP Provider: An existing connection was forcibly closed by the remote host.
,communication link failure
. , aucune des lignes affectées ne peut être connue, mais je suis préoccupé par les messages d'erreur lors de l'exécution du fichier de script généré par la base de données.C'est ce que j'ai rassemblé pour résoudre mon problème immédiat.
Cela nécessite que les commandes GO soient sur leur propre ligne et ne détectera pas les commentaires de bloc, donc ce genre de chose sera divisé et provoquera une erreur:
la source
string sql
- c'est tout le script. Quand je fais référence à un "lot", je veux dire un morceau de code SQL entre deux instructions "GO". Le code ajoute unGO
à la fin du script afin que le code à l'intérieur deforeach
ne saute pas le dernier lot si vous n'avez pas terminé votre script par unGO
. Ainsi, le code tel qu'il est écrit exécutera tout le SQL.StringBuilder sqlBatch
place.Vous pouvez utiliser des objets de gestion SQL pour effectuer cela. Ce sont les mêmes objets que Management Studio utilise pour exécuter des requêtes. Je crois que
Server.ConnectionContext.ExecuteNonQuery()
fera ce dont vous avez besoin.source
Le mot-clé de séparateur de lots "GO" est en fait utilisé par SQL Management Studio lui-même, afin qu'il sache où terminer les lots qu'il envoie au serveur, et il n'est pas transmis au serveur SQL. Vous pouvez même changer le mot-clé dans Management Studio, si vous le souhaitez.
source
Je regarde cela plusieurs fois à la fin décidé avec l' implémentation EF Un peu modifié pour
SqlConnection
source
Si vous ne souhaitez pas installer d'objets SMO, vous pouvez utiliser l'outil gplex (voir cette réponse )
source
Basé sur la solution de Blorgbeard.
source
Si vous ne souhaitez pas utiliser SMO, par exemple parce que vous devez être multiplateforme, vous pouvez également utiliser la classe ScriptSplitter de SubText.
Voici l'implémentation en C # et VB.NET
Usage:
Si vous rencontrez des problèmes avec les commentaires de style C multilignes, supprimez les commentaires avec regex:
La suppression des commentaires sur une seule ligne est ici:
la source
/* Go */
t-elle le cas?J'ai également rencontré le même problème, et je ne pouvais trouver d'autre moyen que de diviser l'opération SQL unique en fichiers séparés, puis de les exécuter tous dans l'ordre.
Évidemment, le problème n'est pas avec les listes de commandes DML, elles peuvent être exécutées sans GO entre les deux; histoire différente avec DDL (créer, modifier, déposer ...)
la source
Si vous ne voulez pas emprunter la route SMO, vous pouvez rechercher et remplacer "GO" par ";" et la requête comme vous le feriez. Notez que soly le dernier jeu de résultats sera renvoyé.
la source
J'ai accompli cela aujourd'hui en chargeant mon SQL à partir d'un fichier texte dans une chaîne. J'ai ensuite utilisé la fonction de fractionnement de chaîne pour séparer la chaîne en commandes individuelles qui ont ensuite été envoyées individuellement au serveur. Simples :)
Je viens de réaliser que vous devez vous séparer sur \ nGO au cas où les lettres GO apparaissent dans l'un de vos noms de table, etc. Je suppose que j'ai eu de la chance là-bas!
la source
Si vous ne souhaitez pas utiliser SMO (ce qui est mieux que la solution ci-dessous, mais je veux donner une alternative ...), vous pouvez diviser votre requête avec cette fonction.
C'est:
Preuve de chaîne (exemple d'impression 'no go')
la source
utilisez la méthode suivante pour diviser la chaîne et exécuter lot par lot
la source
Pour éviter les tiers, les expressions régulières, les surcharges de mémoire et le travail rapide avec de gros scripts, j'ai créé mon propre analyseur basé sur les flux. Il
peut reconnaître les commentaires avec - ou / ** /
peut reconnaître les chaînes littérales avec 'ou "
et d'autres constructions telles que
Comment utiliser
Lecteur de script SQL basé sur le flux
la source
J'ai eu le même problème en java et je l'ai résolu avec un peu de logique et de regex. Je crois que la même logique peut être appliquée. Premièrement, j'ai lu le fichier slq en mémoire. Ensuite, j'applique la logique suivante. C'est à peu près ce qui a été dit auparavant, mais je pense que l'utilisation de la liaison de mots regex est plus sûre que d'attendre un nouveau caractère de ligne.
Cela divise essentiellement la chaîne sql en un tableau de chaînes sql. Le regex sert essentiellement à détecter les mots «go» complets, en minuscules ou en majuscules. Ensuite, vous exécutez les différentes requêtes de manière séquentielle.
la source
insert into books values ('1478355824', 'An Introduction To Programming in Go (paperback)', 9.00)
J'ai rencontré le même problème et je l'ai finalement résolu par un simple remplacement de chaîne, en remplaçant le mot GO par un point-virgule (;)
Tout semble fonctionner correctement lors de l'exécution de scripts avec des commentaires en ligne, des commentaires de bloc et des commandes GO
la source
--
, par exemple.Pour tous ceux qui ont encore le problème. Vous pouvez utiliser Microsoft SMO officiel
https://docs.microsoft.com/en-us/sql/relational-databases/server-management-objects-smo/overview-smo?view=sql-server-2017
la source
Trop difficile :)
Créez un tableau de chaînes str [] en remplaçant GO par ", @":
C'est tout, profitez-en.
la source