Eu gosto de ser detalhado na minha codificação, então minha instrução de inserção típica se parece com isso:
INSERT INTO MyTable
(
Column1
,Column2
,Column3
,Column4
,Column5
,Column6
)
SELECT
Column1 = 'some value'
,Column2 = 'some value'
,Column4 = 'some value'
,Column3 = 'some value'
,Column5 = 'some value'
,Column6 = 'some value'
....
Se você não percebeu o problema com esta afirmação, então você foi enganado, assim como eu fui inúmeras vezes.
E a parte realmente insidiosa desse tipo de falha é que pode funcionar por muito tempo antes de causar qualquer problema e, quando falhar, se houver um erro, não indicará o verdadeiro erro.
Por exemplo, se as colunas 3 e 4 forem do tipo numérico e de string, respectivamente, apenas alguns valores causarão erros de tempo de execução para a coluna 4 (e nenhum para a coluna 3) com uma falha de conversão de tipo (por exemplo, '0' converte para um número perfeitamente mas 'asdf' não).
(No meu caso, isso foi enterrado dentro de um procedimento de ativação do Service Broker fora da seção de código protegido (era uma instrução de log), então, em vez desse erro, eu estava recebendo o erro de transação órfão mascarado como uma mensagem suspeita desativando minha fila.)
Existe alguma maneira de validar tal declaração que não exija revisão manual?
PS Eu sei que você pode dar os aliases que quiser, mas em um contexto completamente opcional, como uma INSERT
declaração, seria extremamente útil ter algum tipo de ferramenta automatizada (ou seja, IntelliSense) para apontar código acidental provável.
Atualização: abri este item de feedback para a Microsoft, por essa funcionalidade claramente ausente.
Eu não acho que há uma boa maneira de automatizar isso. Especialmente porque a maioria das pessoas, na minha experiência, que usa
INSERT ... SELECT
não escreveu oSELECT
especificamente para oINSERT
, mas o copiou de outro lugar. Se eles escreveram oSELECT
para oINSERT
, é improvável que tenham se dado ao trabalho de adicionar aliases de coluna (se a fonte é outra tabela com nomes de coluna diferentes ou apenas uma série de constantes), e se eles adicionaram aliases de coluna, não é garantido que eles os nomearam de forma que haja um mapeamento 1:1 dos nomes das colunas. Se realmente estamos falando deINSERT ... SELECT (a bunch of constants)
, é muito mais provável que sejaINSERT ... VALUES()
.Você pode enviar uma solicitação de recurso para a Microsoft , mas acho que você teria que definir o caso de uso muito bem para que isso ganhasse força em relação às muitas outras melhorias que a comunidade deseja ver.
Se estou tendo um dia de cabelo particularmente ruim, escreverei meu código assim:
e é mais fácil ver que cometi um erro.
Já me deparei com esse problema tantas vezes que minhas
INSERT ... SELECT
declarações ficaram assim:Eu prefiro CTEs sobre sub-consultas.
Ao usar
copy+paste
, esse método ajuda a garantir que você tenha todas as colunas listadas na mesma ordem.Bem, como os dados nas tabelas de origem e destino não estão vinculados de maneira permanente que eu conheça e a única maneira de validar é verificar a correção do tipo de dados, acredito que o SQL realmente não tenha outra maneira de dizer se sua consulta é realmente REALMENTE REALMENTE o que você deseja alcançar. Talvez alguma IA no futuro :)
Com tabelas temporárias, você pode tentar SELECT INTO em vez de INSERT..SELECT - desta forma, a ordem das colunas pode ser diferente após a criação, mas você obterá a coluna correta ao selecionar uma dessas tabelas temporárias.