Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Adicione coluna à tabela e atualize-a dentro da transação


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 ).