Necesito ejecutar un gran conjunto de declaraciones SQL (creando un montón de tablas, vistas y procedimientos almacenados) desde un programa C #.
Estas declaraciones deben estar separadas por GO
declaraciones, pero SqlCommand.ExecuteNonQuery()
no le gustan las GO
declaraciones. Mi solución, que supongo que publicaré como referencia, fue dividir la cadena SQL en GO
líneas y ejecutar cada lote por separado.
¿Existe una manera mejor o más fácil?
fuente
TransactionScope
objeto, solo necesita alistar la conexión con la transacción ambiental actual. Verifique mi respuesta aquí: stackoverflow.com/a/18322938/1268570SqlConnection.InfoMessage
) para ver el resultado en la aplicación C # o guardar el resultado en eltxt
archivo, solo para saber si el script se ejecutó correctamente, porque recientemente lo usésqlcmd
cuando ejecuté un archivo de script de 150 mb en un host remoto, después de 55 minutos filas se efectuaron con este error,TCP Provider: An existing connection was forcibly closed by the remote host.
,communication link failure
. , no se puede conocer ninguna de las filas afectadas, pero me preocupan los mensajes de error al ejecutar el archivo de script generado por la base de datos.Esto es lo que hice para resolver mi problema inmediato.
Requiere que los comandos GO estén en su propia línea y no detectarán comentarios de bloque, por lo que este tipo de cosas se dividirán y causarán un error:
fuente
string sql
- ese es el script completo. Cuando me refiero a un "lote", me refiero a un fragmento de código SQL entre dos declaraciones "GO". El código agrega unGO
al final del script para que el código dentro delforeach
no omita el último lote si no finalizó su script con unGO
. Entonces, el código tal como está escrito ejecutará todo el SQL.StringBuilder sqlBatch
en su lugar.Puede utilizar objetos de administración SQL para realizar esto. Estos son los mismos objetos que utiliza Management Studio para ejecutar consultas. Creo
Server.ConnectionContext.ExecuteNonQuery()
que realizará lo que necesite.fuente
La palabra clave del separador de lotes "GO" es realmente utilizada por SQL Management Studio, de modo que sepa dónde terminar los lotes que está enviando al servidor, y no se pasa al servidor SQL. Incluso puede cambiar la palabra clave en Management Studio, si así lo desea.
fuente
Miro esto varias veces al final decidido con la implementación de EF Un poco modificado para
SqlConnection
fuente
Si no desea instalar objetos SMO, puede usar la herramienta gplex (consulte esta respuesta )
fuente
Basado en la solución de Blorgbeard.
fuente
Si no desea usar SMO, por ejemplo, porque necesita ser multiplataforma, también puede usar la clase ScriptSplitter de SubText.
Aquí está la implementación en C # y VB.NET
Uso:
Si tiene problemas con los comentarios de estilo c de varias líneas, elimine los comentarios con expresiones regulares:
La eliminación de comentarios de una sola línea está aquí:
fuente
/* Go */
caso?También enfrenté el mismo problema, y no pude encontrar otra manera que dividir la operación SQL única en archivos separados y luego ejecutarlos todos en secuencia.
Obviamente, el problema no es con listas de comandos DML, se pueden ejecutar sin GO en el medio; historia diferente con DDL (crear, alterar, soltar ...)
fuente
Si no desea seguir la ruta SMO, puede buscar y reemplazar "GO" por ";" y la consulta como lo haría. Tenga en cuenta que solo se devolverá el último conjunto de resultados.
fuente
Lo logré hoy cargando mi SQL desde un archivo de texto en una cadena. Luego utilicé la función String Split para separar la cadena en comandos individuales que luego se enviaron al servidor individualmente. Simples :)
Me acabo de dar cuenta de que necesitas dividir en \ nGO en caso de que las letras GO aparezcan en alguno de los nombres de tus tablas, etc. ¡Supongo que tuve suerte allí!
fuente
Si no desea utilizar SMO (que es mejor que la solución a continuación, pero quiero dar una alternativa ...) puede dividir su consulta con esta función.
Es:
Prueba de cadena (ejemplo de impresión 'no go')
fuente
use el siguiente método para dividir la cadena y ejecutar lote por lote
fuente
Para evitar terceros, expresiones regulares, sobrecarga de memoria y un trabajo rápido con scripts grandes, creé mi propio analizador basado en flujo. Eso
puede reconocer comentarios con - o / ** /
puede reconocer cadenas literales con 'o "
y otras construcciones como
Cómo utilizar
Lector de scripts SQL basado en stream
fuente
Tuve el mismo problema en Java y lo resolví con un poco de lógica y expresiones regulares. Creo que se puede aplicar la misma lógica. Primero leo del archivo slq en la memoria. Luego aplico la siguiente lógica. Es más o menos lo que se ha dicho antes, sin embargo, creo que usar un enlace de palabras regex es más seguro que esperar un nuevo carácter de línea.
Básicamente, esto divide la cadena SQL en una matriz de cadenas SQL. La expresión regular es básicamente para detectar palabras 'go' completas, ya sea en minúsculas o mayúsculas. Luego, ejecuta las diferentes consultas de forma secuencial.
fuente
insert into books values ('1478355824', 'An Introduction To Programming in Go (paperback)', 9.00)
Encontré este mismo problema y finalmente lo resolví con un simple reemplazo de cadena, reemplazando la palabra GO con un punto y coma (;)
Todo parece funcionar bien mientras se ejecutan scripts con comentarios en línea, comentarios de bloque y comandos GO
fuente
--
, por ejemplo.Para cualquiera que todavía tenga el problema. Puede usar SMO oficial de Microsoft
https://docs.microsoft.com/en-us/sql/relational-databases/server-management-objects-smo/overview-smo?view=sql-server-2017
fuente
Demasiado difícil :)
Cree una matriz de cadenas str [] reemplazando GO con ", @":
Eso es todo, disfruta.
fuente