SQL Inserir com dados de várias tabelas
-
22-09-2019 - |
Pergunta
Eu tenho quatro tabelas: mensagens, MessageCategory, Messagestatus e Messagelevel.
MessageCategory, Messagestatus e Messagelevel têm apenas três campos: identidade (chave primária), código e descrição. As mensagens referem -se a esses três campos e possuem alguns outros campos de dados, incluindo a identidade (chave primária) MessageText and Order. Os campos de identidade são campos incrementados automaticamente.
Agora preciso escrever um script SQL para adicionar alguns dados padrão às quatro tabelas. O problema é que preciso criar um script que será enviado a um cliente que executará esse script. Não posso escrever um código um pouco mais inteligente para fazer toda a atualização. E enquanto três tabelas são apenas declarações simples de inserção, é a tabela de mensagens que me causa algumas dores de cabeça adicionais.
Não posso remover nenhum índices e não posso assumir que ele começa a contar em 1 para as teclas primárias.
Então, como exemplo, ela são alguns dados:
INSERT INTO MessageCategory (Code) Values ('Cat01');
INSERT INTO MessageStatus (Code) Values ('Status01');
INSERT INTO MessageLevel (Code) Values ('Level01');
E as mensagens precisariam de algo assim:
INSERT INTO Messages(Category, Status, Level, MessageText, Order)
VALUES(
(SELECT Identity from MessageCategory where Code='Cat01'),
(SELECT Identity from MessageStatus where Code='Status01'),
(SELECT Identity from MessageLevel where Code='Level01'),
'Just some message',
1
);
Isso não vai funcionar, no entanto. Então, qual é o truque para fazer isso funcionar? (Mantendo o código legível também ...)
Infelizmente, não tenho acesso ao outro banco de dados. Eu posso testá-lo, mas uma vez que pareça funcionar, é apenas uma questão de enviar e fazer o seu trabalho ...
Solução
INSERT INTO Messages
(Category, Status, Level, MessageText, [Order])
SELECT
(SELECT TOP 1 [Identity] from MessageCategory where Code='Cat01') AS Category,
(SELECT TOP 1 [Identity] from MessageStatus where Code='Status01') AS Status,
(SELECT TOP 1 [Identity] from MessageLevel where Code='Level01') AS Level,
(SELECT 'Just some message') AS MessageText,
(SELECT 1) AS [Order]
O exposto acima funcionaria para o SQL Server. Observe que ambos Identity
e Order
são palavras-chave T-SQL reservadas e não devem ser usadas para nomes de colunas. Observe também que as sub-questões não devem retornar mais de uma linha para que isso funcione, para garantir que eu incluísse TOP 1
declarações.
A próxima coisa a observar é que os aliases da coluna (AS Category
etc.) não são estritamente necessários. A ordem deles é o que conta. Eu os incluiria para legibilidade, especialmente quando a lista de seleção ficar mais longa.
Outras dicas
Se for um único script, armazene suas identidades em variáveis:
declare MessageCategoryID int;
declare MessageStatusID int;
declare MessageLevel int;
INSERT INTO MessageCategory (Code) Values ('Cat01');
set @MessageCategoryID=scope_identity();
INSERT INTO MessageStatus (Code) Values ('Status01');
set @MessageStatudID=scope_identity();
INSERT INTO MessageLevel (Code) Values ('Level01');
set @MessageLevelID=scope_identity();
INSERT INTO Messages(Category, Status, Level, MessageText, Order)
VALUES(
@MessageCAtegoryID,
@MessageStatusID,
@MessageLevelID,
'Just some message',
1);