Estou gerando um script para migrar automaticamente as alterações de vários bancos de dados de desenvolvimento para teste / produção. Basicamente, ele pega um monte de scripts de mudança e os mescla em um único script, envolvendo cada script em uma IF whatever BEGIN ... END
instrução.
No entanto, alguns dos scripts requerem uma GO
instrução para que, por exemplo, o analisador SQL saiba sobre uma nova coluna após sua criação.
ALTER TABLE dbo.EMPLOYEE
ADD COLUMN EMP_IS_ADMIN BIT NOT NULL
GO -- Necessary, or next line will generate "Unknown column: EMP_IS_ADMIN"
UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever
No entanto, depois de embrulhar isso em um IF
bloco:
IF whatever
BEGIN
ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL
GO
UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever
END
Falha porque estou enviando um BEGIN
sem correspondência END
. Porém, se eu remover o GO
ele reclamará novamente de uma coluna desconhecida.
Existe alguma maneira de criar e atualizar a mesma coluna em um único IF
bloco?
sql
sql-server
tsql
sql-server-2008
BlueRaja - Danny Pflughoeft
fonte
fonte
GO
estar em uma linha por si só, então você pode pesquisar apenas esse caso, e não todas as ocorrências da palavraGO
. 2) Você sempre pode registrar quais declarações foram concluídas com êxito. Ou você poderia embrulhar tudo em um try / catch e usar seus próprios números de linha usando alguma variável, como @lineNo, que você acompanha e relata o erro. Como você os está gerando automaticamente, fazer alterações como essa deve ser muito fácil. Parece que você simplesmente não quer explorar essa rota, quando penso que há soluções a serem encontradas para todas as suas preocupações.Respostas:
Tive o mesmo problema e finalmente consegui resolvê-lo usando SET NOEXEC .
fonte
SQLCMD
script de modo SS (ou seja, um script de implantação mestre) que chama (via:r
comando) outros scripts SS (ou seja, scripts de sub-implantação) com algumas dessas chamadas dentro deif
instruções. As respostas de Oded, mellamokb e Andy Joiner de incluir todas essas declarações emexec
Chamadas /begin
-end
não são iniciais. Além disso, o métodobegin
-end
não funcionará se houver umacreate
declaração (por exemplo, requer um explícitogo
antes dela). Mas, cara, "Santo duplo negativo, Batman!" ;)if
), prefixaria o bloco com um-- If whatever
comentário, indentaria o bloco e pós-fixaria o bloco com um--end If whatever
comentário.GO
não é SQL - é simplesmente um separador de lote usado em algumas ferramentas MS SQL.Se você não usar isso, precisará garantir que as instruções sejam executadas separadamente - em lotes diferentes ou usando SQL dinâmico para a população (obrigado @gbn):
fonte
IF
bloco.;
ajuda aqui? - Você acabou de editar sua resposta: o);
também não funciona - o analisador ainda está fornecendo "Nome de coluna inválido 'EMP_IS_ADMIN'."Você pode tentar
sp_executesql
, dividir o conteúdo entre cadaGO
instrução em uma string separada para ser executada, conforme demonstrado no exemplo abaixo. Além disso, há uma variável @statementNo para rastrear qual instrução está sendo executada para facilitar a depuração onde ocorreu uma exceção. Os números das linhas serão relativos ao início do número da instrução relevante que causou o erro.Você também pode executar facilmente instruções de várias linhas, conforme demonstrado no exemplo acima, simplesmente colocando-as entre aspas simples (
'
). Não se esqueça de deixar de lado as aspas simples contidas na string com aspas simples duplas (''
) ao gerar os scripts.fonte
SELECT * <newline> FROM whatever
. Se eu executar cada linha com sua própria instrução EXEC, haverá falha. Ou você está sugerindo que eu interrompa a cadaGO
afirmação?Por fim, consegui fazê-lo funcionar substituindo cada instância de
GO
em sua própria linha porIsso é muito preferível a envolver cada grupo de instruções em uma string, mas ainda está longe do ideal. Se alguém encontrar uma solução melhor, poste e eu aceitarei.
fonte
IF
bloco). Parece que não há uma boa maneira de fazer isso no SQL.set noexec
resposta de Mina Jacob é a ÚNICA resposta prática até agora para uso em umSQLCMD
script de modo SS (ou seja, um script de implantação mestre) que chama (via:r
comando) outros scripts SS (ou seja, scripts de sub-implantação) com algumas dessas chamadas dentro deif
instruções. As respostas de Oded, mellamokb e Andy Joiner de incluir todas essas declarações emexec
Chamadas /begin
-end
não são iniciais. Além disso, o métodobegin
-end
não funcionará se houver umacreate
Declaração (por exemplo, requer um explícitogo
antes dela).Você pode incluir as instruções em BEGIN e END em vez de GO no meio
(Testado no banco de dados Northwind)
Editar: (Provavelmente testado em SQL2012)
fonte
set noexec
resposta de Mina Jacob é a ÚNICA resposta prática até agora para uso em umSQLCMD
script de modo SS (ou seja, um script de implantação mestre) que chama (via:r
comando) outros scripts SS (ou seja, scripts de subdesenvolvimento) com algumas dessas chamadas dentro deif
instruções. As respostas de Oded, mellamokb e Andy Joiner de incluir todas essas declarações emexec
Chamadas /begin
-end
não são iniciais. Além disso, o métodobegin
-end
não funcionará se houver umacreate
Declaração (por exemplo, requer um explícitogo
antes dela).Você pode tentar esta solução:
fonte
Eu tenho usado
RAISERROR
no passado para estefonte
Você pode incorporar as instruções
GOTO
eLABEL
para ignorar o código, deixando assim asGO
palavras - chave intactas.fonte