Eu preciso executar um grande conjunto de instruções SQL (criando um monte de tabelas, visualizações e procedimentos armazenados) de dentro de um programa C #.
Essas declarações precisam ser separadas por GO
declarações, mas SqlCommand.ExecuteNonQuery()
não gosta de GO
declarações. Minha solução, que suponho que postarei como referência, foi dividir a string SQL em GO
linhas e executar cada lote separadamente.
Existe uma maneira mais fácil / melhor?
fonte
TransactionScope
objeto, você só precisa inscrever a conexão com a transação ambiente atual. Verifique minha resposta aqui: stackoverflow.com/a/18322938/1268570SqlConnection.InfoMessage
) para ver o resultado no aplicativo C # ou salvar o resultado emtxt
arquivo, apenas para saber se o script foi executado com sucesso, porque recentemente usandosqlcmd
quando executei um arquivo de script de 150 mb no host remoto, após 55 minutos alguns linhas foram efectuadas com este erro,TCP Provider: An existing connection was forcibly closed by the remote host.
,communication link failure
. , nenhuma das linhas afetadas pode ser conhecida, mas estou preocupado com as mensagens de erro ao executar o arquivo de script gerado pelo banco de dados.Foi isso que juntei para resolver meu problema imediato.
Exige que os comandos GO estejam em suas próprias linhas e não detectará comentários de bloqueio, portanto, esse tipo de coisa será dividido e causará um erro:
fonte
string sql
- esse é o script inteiro. Quando me refiro a um "lote", quero dizer um pedaço de código SQL entre duas instruções "GO". O código adiciona umGO
ao final do script para que o código dentro doforeach
não pule o último lote se você não finalizou seu script com umGO
. Portanto, o código conforme escrito executará todo o SQL.StringBuilder sqlBatch
.Você pode usar SQL Management Objects para fazer isso. Esses são os mesmos objetos que o Management Studio usa para executar consultas. Eu acredito que
Server.ConnectionContext.ExecuteNonQuery()
irá realizar o que você precisa.fonte
A palavra-chave separadora de lote "GO" é realmente usada pelo próprio SQL Management Studio, para que ele saiba onde encerrar os lotes que está enviando para o servidor e não é passada para o servidor SQL. Você pode até mesmo alterar a palavra-chave no Management Studio, se desejar.
fonte
Eu vejo isso algumas vezes no final decidido com a implementação EF Um pouco modificado para
SqlConnection
fonte
Se você não quiser instalar objetos SMO, você pode usar a ferramenta gplex (veja esta resposta )
fonte
Baseado na solução de Blorgbeard.
fonte
Se você não quiser usar SMO, por exemplo, porque precisa ser multiplataforma, também pode usar a classe ScriptSplitter do SubText.
Aqui está a implementação em C # e VB.NET
Uso:
Se você tiver problemas com comentários multilinhas no estilo C, remova os comentários com regex:
A remoção de comentários de uma única linha é aqui:
fonte
/* Go */
caso?Também enfrentei o mesmo problema e não consegui encontrar outra maneira a não ser dividir a única operação SQL em arquivos separados e, em seguida, executar todos eles em sequência.
Obviamente, o problema não é com listas de comandos DML, eles podem ser executados sem GO no meio; história diferente com DDL (criar, alterar, soltar ...)
fonte
Se você não quiser seguir a rota SMO, pode pesquisar e substituir "GO" por ";" e a consulta como você faria. Observe que apenas o último conjunto de resultados será retornado.
fonte
Eu fiz isso hoje carregando meu SQL de um arquivo de texto em uma string. Em seguida, usei a função Split da string para separar a string em comandos individuais que foram enviados ao servidor individualmente. Simples :)
Acabei de perceber que você precisa dividir em \ nGO para o caso de as letras GO aparecerem em algum dos nomes de sua mesa, etc. Acho que tive sorte!
fonte
Se você não quiser usar o SMO (que é melhor do que a solução abaixo, mas eu quero dar uma alternativa ...) você pode dividir sua consulta com esta função.
Isto é:
Prova de string (exemplo imprimir 'não vai')
fonte
use o seguinte método para dividir a string e executar lote por lote
fonte
Para evitar terceiros, regexes, sobrecargas de memória e trabalho rápido com scripts grandes, criei meu próprio analisador baseado em fluxo. isto
pode reconhecer comentários com - ou / ** /
pode reconhecer literais de string com 'ou "
e outras construções, como
Como usar
Leitor de script SQL baseado em fluxo
fonte
Tive o mesmo problema em java e resolvi com um pouco de lógica e regex. Acredito que a mesma lógica pode ser aplicada. Primeiro, li do arquivo slq para a memória. Então aplico a seguinte lógica. É praticamente o que foi dito antes, no entanto, acredito que usar o limite de palavras regex é mais seguro do que esperar um novo caractere de linha.
Basicamente, isso divide a string sql em uma matriz de strings sql. O regex é basicamente para detectar palavras completas em letras minúsculas ou maiúsculas. Então você executa as diferentes querys sequencialmente.
fonte
insert into books values ('1478355824', 'An Introduction To Programming in Go (paperback)', 9.00)
Eu encontrei esse mesmo problema e, finalmente, resolvi apenas substituindo uma string simples, substituindo a palavra GO por um ponto e vírgula (;)
Tudo parece estar funcionando bem durante a execução de scripts com comentários in-line, bloquear comentários e comandos GO
fonte
--
, por exemplo.Para quem ainda está tendo o problema. Você poderia usar oficial Microsoft SMO
https://docs.microsoft.com/en-us/sql/relational-databases/server-management-objects-smo/overview-smo?view=sql-server-2017
fonte
Muito difícil :)
Crie uma matriz de strings str [] substituindo GO por ", @":
Isso é tudo, aproveite.
fonte