GO não é um comando T-SQL. É um delimitador de lote. A ferramenta cliente (SSM, sqlcmd, osql etc) a usa para cortar efetivamente o arquivo em cada GO e enviar ao servidor os lotes individuais. Então, obviamente, você não pode usar GO dentro de IF, nem pode esperar que as variáveis abranjam o escopo entre os lotes.
Além disso, você não pode capturar exceções sem verificar o
XACT_STATE()
para garantir que a transação não esteja condenada. Usar GUIDs para IDs é sempre pelo menos suspeito.
Usando restrições NOT NULL e fornecendo um 'guid' padrão como
'{00000000-0000-0000-0000-000000000000}'
também não pode estar correto. Atualizada:
- Separe o ALTER e o UPDATE em dois lotes.
- Use extensões sqlcmd para interromper o script em caso de erro. Isso é suportado pelo SSMS quando o modo sqlcmd está ativado , sqlcmd, e é trivial suportá-lo também em bibliotecas de cliente:dbutilsqlcmd .
- use
XACT_ABORT
para forçar o erro a interromper o lote. Isso é frequentemente usado em scripts de manutenção (alterações de esquema). Procedimentos armazenados e scripts de lógica de aplicativo em geral usam blocos TRY-CATCH, mas com o devido cuidado:Tratamento de exceção e transações aninhadas .
roteiro de exemplo:
:on error exit
set xact_abort on;
go
begin transaction;
go
if columnproperty(object_id('Code'), 'ColorId', 'AllowsNull') is null
begin
alter table Code add ColorId uniqueidentifier null;
end
go
update Code
set ColorId = '...'
where ...
go
commit;
go
Apenas um script bem-sucedido alcançará o
COMMIT
. Qualquer erro abortará o script e reverterá. Eu usei
COLUMNPROPERTY
para verificar a existência da coluna, você pode usar qualquer método que desejar (por exemplo, lookup sys.columns
).