AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 191146
Accepted
Louis Somers
Louis Somers
Asked: 2017-11-18 03:57:22 +0800 CST2017-11-18 03:57:22 +0800 CST 2017-11-18 03:57:22 +0800 CST

Usando colunas de origem na cláusula OUTPUT INTO de uma instrução INSERT (SQL Server)

  • 772

Estou escrevendo uma instrução de inserção de processamento em lote e gostaria de usar uma tabela temporária para acompanhar os IDs inseridos em vez de fazer um loop pelos itens e chamar SCOPE_IDENTITY() para cada linha inserida.

Os dados que precisam ser inseridos possuem ID's (temporários) ligando-os a outros dados que também devem ser inseridos em outra tabela, então preciso de uma referência cruzada do Id real e do Id temporário.

Este é um exemplo do que tenho até agora:

-- The existing table 
DECLARE @MyTable TABLE (ID INT IDENTITY(1,1), [Name] NVARCHAR(MAX));

-- My data I want to insert
DECLARE @MyInsertData TABLE (ID INT, [Name] NVARCHAR(MAX));
INSERT INTO @MyInsertData ( ID,Name)
VALUES ( -1 , 'bla'),(-2,'test'),(-3,'last');

DECLARE @MyCrossRef TABLE ([NewId] INT, OldId INT);

INSERT INTO @MyTable ( [Name] )
   OUTPUT Inserted.ID, INS.ID INTO @MyCrossRef
   SELECT [NAME] FROM @MyInsertData INS

-- Check the result
SELECT * FROM @MyCrossRef

O problema é que não consigo fazer com que a cláusula OUTPUT INTO aceite o ID, já tentei @MyInsertData.IDe outros truques juntando a tabela a ela mesma, mas nada parece funcionar.

insert output-clause
  • 2 2 respostas
  • 27186 Views

2 respostas

  • Voted
  1. Best Answer
    Daniel Hutmacher
    2017-11-20T09:55:16+08:002017-11-20T09:55:16+08:00

    Na verdade, você pode conseguir a mesma coisa alterando seu INSERTpara um arquivo MERGE. Embora a MERGEinstrução seja realmente uma maneira bem legal de fazer "upserts" no SQL Server, não há nada que impeça você de usá-la apenas para inserir:

    -- The existing table 
    DECLARE @MyTable TABLE (ID INT IDENTITY(1,1), [Name] NVARCHAR(MAX));
    
    -- My data I want to insert
    DECLARE @MyInsertData TABLE (ID INT, [Name] NVARCHAR(MAX));
    INSERT INTO @MyInsertData ( ID,Name)
    VALUES ( -1 , 'bla'),(-2,'test'),(-3,'last');
    
    DECLARE @MyCrossRef TABLE ([NewId] INT, OldId INT);
    
    MERGE INTO @MyTable AS dest
    USING @MyInsertData AS ins ON 1=0   -- always false
    
    WHEN NOT MATCHED BY TARGET          -- happens for every row, because 1 is never 0
        THEN INSERT ([Name])
             VALUES (ins.[NAME])
    
    OUTPUT inserted.ID, ins.ID
    INTO @MyCrossRef (NewId, OldId);
    
    -- Check the result
    SELECT * FROM @MyCrossRef
    

    Uma das coisas boas MERGEé que ele permite que você acesse as colunas de origem , bem como as tabelas internas insertede na cláusula.deletedOUTPUT

    Meu código pode conter erros, pois na verdade não testei. Minha postagem no blog de alguns anos atrás entra em um pouco mais de detalhes, incluindo o desempenho da consulta.

    • 40
  2. David Spillett
    2017-11-18T04:22:20+08:002017-11-18T04:22:20+08:00

    A cláusula de saída só pode acessar dados nas linhas de destino e constantes/variáveis, não dados de outro lugar na origem SELECT, como se você estivesse operando em um gatilho.

    https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql afirma:

    Qualquer referência a colunas na tabela que está sendo modificada deve ser qualificada com o prefixo INSERTED ou DELETED.

    Então, para obter o ID original, você precisaria incluí-lo na tabela de destino para que a cláusula de saída pudesse ecoá-lo de volta, assim:

    -- The existing table 
    DECLARE @MyTable TABLE (ID INT IDENTITY(1,1), [Name] NVARCHAR(MAX), SourceID INT);
    
    -- My data I want to insert
    DECLARE @MyInsertData TABLE (ID INT, [Name] NVARCHAR(MAX));
    INSERT INTO @MyInsertData ( ID,Name)
    VALUES ( -1 , 'bla'),(-2,'test'),(-3,'last');
    
    DECLARE @MyCrossRef TABLE ([NewId] INT, OldId INT);
    
    INSERT INTO @MyTable ( [Name], SourceID )
       OUTPUT Inserted.ID, Inserted.SourceID INTO @MyCrossRef
       SELECT [NAME], ID FROM @MyInsertData INS
    
    -- Check the result
    SELECT * FROM @MyCrossRef
    

    embora alterar o esquema do objeto de destino possa não ser prático na sua situação, isso pode não ser aplicável.

    • 8

relate perguntas

  • Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

  • Inserir em um local específico na tabela Oracle DB?

  • aninhar SELECT em INSERT

  • Obtendo o erro "ORA-00911" quando tento inserir mais de 1 linha

  • Como posso saber POR QUE uma inserção em uma determinada tabela é lenta?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve