Inserir várias linhas SEM repetir a parte "INSERT INTO ..." da instrução?

536

Sei que fiz isso antes de anos atrás, mas não me lembro da sintaxe e não consigo encontrá-la em nenhum lugar devido à obtenção de vários documentos e artigos de ajuda sobre "importações em massa".

Aqui está o que eu quero fazer, mas a sintaxe não está exatamente correta ... por favor, alguém que já fez isso antes, me ajude :)

INSERT INTO dbo.MyTable (ID, Name)
VALUES (123, 'Timmy'),
    (124, 'Jonny'),
    (125, 'Sally')

Eu sei que isso está próximo da sintaxe correta. Talvez eu precise da palavra "GRANEL" lá dentro, ou algo do tipo, não me lembro. Qualquer ideia?

Eu preciso disso para um banco de dados SQL Server 2005. Eu tentei esse código, sem sucesso:

DECLARE @blah TABLE
(
    ID INT NOT NULL PRIMARY KEY,
    Name VARCHAR(100) NOT NULL
)

INSERT INTO @blah (ID, Name)
    VALUES (123, 'Timmy')
    VALUES (124, 'Jonny')
    VALUES (125, 'Sally')

SELECT * FROM @blah

Estou entendendo Incorrect syntax near the keyword 'VALUES'.

Timothy Khouri
fonte
4
Seu código acima é bom, basta adicionar ',' após a declaração de valores
sam
4
INSERT INTO @blah (ID, Nome), VALUES (123, 'Timmy'), VALUES (124, 'Jonny'), VALUES (125, 'Sally')
sam
1
Apenas um aviso: você pode inserir até 1000 linhas apenas por esse método. INSERIR VALORES #Test (LWPurchaseOrderID) (935791), (935933)
Anoop Verma
16
2005 não é mais suportado. Para 2008, 2012 e 2016, você quase pode usar o que coloca INSERT INTO @blah (ID, Name) VALUES (123, 'Timmy'), (124, 'Jonny'), (125, 'Sally') "VALUES" apenas aparece uma vez e precisa de vírgulas entre os conjuntos.
31716 Chris J. J. Compton

Respostas:

328
INSERT INTO dbo.MyTable (ID, Name)
SELECT 123, 'Timmy'
UNION ALL
SELECT 124, 'Jonny'
UNION ALL
SELECT 125, 'Sally'

No SQL Server 2008, você pode fazer isso em uma cláusula VALUES exatamente conforme a declaração da sua pergunta (você só precisa adicionar uma vírgula para separar cada declaração de valores) ...

gbn
fonte
10
Isso é mais eficiente do que usar várias instruções INSERT?
Code Commander
7
@ Code Commander: não, na medida em que é mais compilado. Sim, na medida em que você tem apenas uma inserção. Mas ele responde à pergunta: sem repetição deINSERT table (columnlist)
gbn 25/10/11
3
@VoidKing Eu sei que isso acontece meio ano depois e você já deve ter percebido isso há muito tempo, mas é realmente muito simples. Ao usar, selectvocê cria um conjunto com colunas e linhas e, por design, essas linhas podem ser inserteditadas em outra tabela com uma quantidade igual de colunas. Você pode até usar uma mistura de literais e valores. Por exemplo, usar insertwith select 'A', ID from ATableinseria 'A' sempre na primeira coluna e o valor da coluna ID da linha correspondente de ATable na segunda coluna.
MarioDS
1
Isso também funciona com o DB2, que é uma nota importante para aqueles que estão presos em tecnologias desatualizadas. Os valores separados pela resposta de vírgula são melhores para mim, para aqueles que trabalham no SQL Server 2008 ou mais recente. O OP pode remover todos os "valores", exceto o primeiro, e substituí-lo por um,
JPK 16/07
1
@PRMan, você não faria isso após a versão do SQL Server 2008. Como mencionado ...
gbn 27/03
510

Sua sintaxe quase funciona no SQL Server 2008 (mas não no SQL Server 2005 1 ):

CREATE TABLE MyTable (id int, name char(10));

INSERT INTO MyTable (id, name) VALUES (1, 'Bob'), (2, 'Peter'), (3, 'Joe');

SELECT * FROM MyTable;

id |  name
---+---------
1  |  Bob       
2  |  Peter     
3  |  Joe       

1 Quando a pergunta foi respondida, não ficou evidente que a pergunta estava se referindo ao SQL Server 2005. Estou deixando essa resposta aqui, pois acredito que ainda é relevante.

Daniel Vassallo
fonte
Funciona no SQL Server 2012
user2601995
27
O Server 2008 não permite mais de 1000 linhas inseridas dessa maneira.
Michael - de onde Clay Shirky
1
O que acontece, se um conjunto de valores estiver com defeito? Todas as pastilhas foram revertidas ou apenas a linha com defeito?
Netblognet
2
@netblognet eu só testado que apenas as linhas com defeito não são inseridos (todos os todos os outros estão inseridos corretamente)
Mauricio Gracia Gutierrez
1
@ Michael Pode ser levantada stackoverflow.com/a/42703601/5070879
Lukasz Szozda
243

Se seus dados já estão no seu banco de dados, você pode:

INSERT INTO MyTable(ID, Name)
SELECT ID, NAME FROM OtherTable

Se você precisar codificar os dados, o SQL 2008 e as versões posteriores permitem fazer o seguinte ...

INSERT INTO MyTable (Name, ID)
VALUES ('First',1),
('Second',2),
('Third',3),
('Fourth',4),
('Fifth',5)
George
fonte
28

Usando INSERT INTO ... VALUESsintaxe como na resposta de Daniel Vassallo, há uma limitação irritante:

Do MSDN

O número máximo de linhas que podem ser construídas inserindo linhas diretamente na lista VALUES é 1000

A maneira mais fácil de omitir essa limitação é usar tabela derivada como:

INSERT INTO dbo.Mytable(ID, Name)
SELECT ID, Name 
FROM (
   VALUES (1, 'a'),
          (2, 'b'),
          --...
          -- more than 1000 rows
)sub (ID, Name);

LiveDemo


Isso funcionará a partir do SQL Server 2008 ou superior

Lukasz Szozda
fonte
Posso ter um link para um artigo sobre esta sintaxe 'sub'.
CodeCamper 8/17/17
2
@CodeCamper docs.microsoft.com/en-us/sql/t-sql/queries/… seção:C. Specifying multiple values as a derived table in a FROM clause
Lukasz Szozda
3
A vantagem desta resposta é que ela fornece uma maneira de especificar valores idênticos sem repeti-los (que é o que eu estava procurando). Por exemplo, com uma terceira coluna idêntica, você não precisaria repeti-la mil vezes.
Vadim Berman
1
@VadimBerman Sim, esse é um bom cenário quando não há nenhum padrão definido na tabela.
Lukasz Szozda
14

Você poderia fazer isso (feio, mas funciona):

INSERT INTO dbo.MyTable (ID, Name) 
select * from
(
 select 123, 'Timmy'
  union all
 select 124, 'Jonny' 
  union all
 select 125, 'Sally'
 ...
) x
davek
fonte
10

Isso alcançará o que você está perguntando:

INSERT INTO table1 (ID, Name)
    VALUES (123, 'Timmy'), 
           (124, 'Jonny'), 
           (125, 'Sally');

Para futuros desenvolvedores, você também pode inserir de outra tabela :

INSERT INTO table1 (ID, Name)
    SELECT 
         ID, 
         Name 
    FROM table2

Ou mesmo de várias tabelas :

INSERT INTO table1 (column2, column3)
    SELECT 
         t2.column, 
         t3.column
    FROM table2 t2
         INNER JOIN table3 t3
         ON t2.ID = t3.ID
Tigerjz32
fonte
8

Você pode usar uma união:

INSERT INTO dbo.MyTable (ID, Name) 
SELECT ID, Name FROM (
    SELECT 123, 'Timmy'
    UNION ALL
    SELECT 124, 'Jonny'
    UNION ALL
    SELECT 125, 'Sally'
) AS X (ID, Name)
Cade Roux
fonte
6

Isso parece bom para o SQL Server 2008. Para SS2005 e versões anteriores, você precisa repetir a instrução VALUES.

INSERT INTO dbo.MyTable (ID, Name)  
VALUES (123, 'Timmy')  
VALUES (124, 'Jonny')   
VALUES (125, 'Sally')  

EDIT :: Meu mal. Você deve repetir o 'INSERT INTO' para cada linha no SS2005.

INSERT INTO dbo.MyTable (ID, Name)  
VALUES (123, 'Timmy')  
INSERT INTO dbo.MyTable (ID, Name)  
VALUES (124, 'Jonny')   
INSERT INTO dbo.MyTable (ID, Name)  
VALUES (125, 'Sally')  
DaveE
fonte
6

Seria mais fácil usar XML no SQL Server para inserir várias linhas, caso contrário, isso se tornará muito tedioso.

Veja o artigo completo com explicações de código aqui http://www.cyberminds.co.uk/blog/articles/how-to-insert-multiple-rows-in-sql-server.aspx

Copie o código a seguir no sql server para visualizar uma amostra.

declare @test nvarchar(max)

set @test = '<topic><dialog id="1" answerId="41">
        <comment>comment 1</comment>
        </dialog>
    <dialog id="2" answerId="42" >
    <comment>comment 2</comment>
        </dialog>
    <dialog id="3" answerId="43" >
    <comment>comment 3</comment>
        </dialog>
    </topic>'

declare @testxml xml
set @testxml = cast(@test as xml)
declare @answerTemp Table(dialogid int, answerid int, comment varchar(1000))

insert @answerTemp
SELECT  ParamValues.ID.value('@id','int') ,
ParamValues.ID.value('@answerId','int') ,
ParamValues.ID.value('(comment)[1]','VARCHAR(1000)')
FROM @testxml.nodes('topic/dialog') as ParamValues(ID)
Joe
fonte
6
USE YourDB
GO
INSERT INTO MyTable (FirstCol, SecondCol)
SELECT 'First' ,1
UNION ALL
SELECT 'Second' ,2
UNION ALL
SELECT 'Third' ,3
UNION ALL
SELECT 'Fourth' ,4
UNION ALL
SELECT 'Fifth' ,5
GO

OU VOCÊ PODE USAR DE OUTRA MANEIRA

INSERT INTO MyTable (FirstCol, SecondCol)
VALUES 
('First',1),
('Second',2),
('Third',3),
('Fourth',4),
('Fifth',5)
gngolakia
fonte
6

Eu tenho usado o seguinte:

INSERT INTO [TableName] (ID, Name)
values (NEWID(), NEWID())
GO 10

Ele adicionará dez linhas com GUIDs exclusivos para ID e Nome.

Nota: não termine a última linha (GO 10) com ';' porque lançará um erro: Ocorreu um erro fatal de script. Sintaxe incorreta foi encontrada ao analisar o GO.

valentinvs
fonte
5

Correspondendo a INSERT (Transact-SQL) (SQL Server 2005), você não pode omitir INSERT INTO dbo.Blahe precisa especificá-lo toda vez ou usar outra sintaxe / abordagem,

abatishchev
fonte
2

Isso está funcionando muito rápido e é eficiente em SQL. Suponha que você tenha tabela Sample with 4 column a,b,c,d where a,b,d are int and c column is Varchar(50).

CREATE TABLE [dbo].[Sample](
[a] [int] NULL,
[b] [int] NULL,
[c] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[D] [int] NULL
)

Portanto, você não pode inserir vários registros nesta tabela usando a consulta a seguir sem repetir a instrução insert,

DECLARE @LIST VARCHAR(MAX)
SET @LIST='SELECT 1, 1, ''Charan Ghate'',11
     SELECT 2,2, ''Mahesh More'',12
     SELECT 3,3,''Mahesh Nikam'',13
     SELECT 4,4, ''Jay Kadam'',14'
INSERT SAMPLE (a, b, c,d) EXEC(@LIST)

Também com C # usando SqlBulkCopy bulkcopy = new SqlBulkCopy(con)

Você pode inserir 10 linhas por vez

   DataTable dt = new DataTable();
        dt.Columns.Add("a");
        dt.Columns.Add("b");
        dt.Columns.Add("c");
        dt.Columns.Add("d");
        for (int i = 0; i < 10; i++)
        {
            DataRow dr = dt.NewRow();
            dr["a"] = 1;
            dr["b"] = 2;
            dr["c"] = "Charan";
            dr["d"] = 4;
            dt.Rows.Add(dr);
        }
        SqlConnection con = new SqlConnection("Connection String");
        using (SqlBulkCopy bulkcopy = new SqlBulkCopy(con))
        {
            con.Open();
            bulkcopy.DestinationTableName = "Sample";
            bulkcopy.WriteToServer(dt);
            con.Close();
        }
Charan Ghate
fonte
0

Oracle SQL Server Inserir várias linhas

Em uma inserção multititativa, você insere linhas calculadas derivadas das linhas retornadas da avaliação de uma subconsulta em uma ou mais tabelas.

INSERT ALL incondicional : - Para adicionar várias linhas a uma tabela de uma só vez, use o seguinte formulário da instrução INSERT:

INSERT ALL
   INTO table_name (column_list) VALUES (value_list_1)
   INTO table_name (column_list) VALUES (value_list_2)
   INTO table_name (column_list) VALUES (value_list_3)
   ...
   INTO table_name (column_list) VALUES (value_list_n)
SELECT 1 FROM DUAL; -- SubQuery

Especifique ALL seguido de várias insert_into_clauses para executar uma inserção multitable incondicional. O Banco de Dados Oracle executa cada insert_into_clause uma vez para cada linha retornada pela subconsulta.

Servidor MySQL Insira várias linhas

INSERT INTO table_name (column_list)
VALUES
    (value_list_1),
    (value_list_2),
    ...
    (value_list_n);

Consulta de inserção de linha única

INSERT INTO table_name (col1,col2) VALUES(val1,val2);
Yash
fonte
0

Outros aqui sugeriram algumas sintaxes de vários registros. Explicando isso, sugiro que você insira uma tabela temporária primeiro e insira sua tabela principal a partir daí.

O motivo disso é que o carregamento dos dados de uma consulta pode demorar mais e você pode bloquear a tabela ou as páginas por mais tempo do que o necessário, o que atrasa outras consultas em execução nessa tabela.

-- Make a temp table with the needed columns
select top 0 *
into #temp
from MyTable (nolock)

-- load data into it at your leisure (nobody else is waiting for this table or these pages)
insert #temp (ID, Name)
values (123, 'Timmy'),
(124, 'Jonny'),
(125, 'Sally')

-- Now that all the data is in SQL, copy it over to the real table. This runs much faster in most cases.
insert MyTable (ID, Name)
select ID, Name
from #temp

-- cleanup
drop table #temp

Além disso, seus IDs provavelmente devem ser de identidade (1,1) e você provavelmente não deve inseri-los, na grande maioria das circunstâncias. Deixe o SQL decidir essas coisas para você.

tsilb
fonte