¿Insertar varias filas SIN repetir la parte "INSERTAR EN ..." de la declaración?

536

Sé que he hecho esto antes hace años, pero no puedo recordar la sintaxis, y no puedo encontrarla en ningún lado debido a la extracción de toneladas de documentos de ayuda y artículos sobre "importaciones masivas".

Esto es lo que quiero hacer, pero la sintaxis no es exactamente la correcta ... por favor, alguien que haya hecho esto antes, ayúdame :)

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

Sé que esto está cerca de la sintaxis correcta. Puede que necesite la palabra "BULK" allí, o algo, no recuerdo. ¿Alguna idea?

Necesito esto para una base de datos SQL Server 2005. He intentado este código, en vano:

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

Me estoy poniendo Incorrect syntax near the keyword 'VALUES'.

Timothy Khouri
fuente
44
Su código anterior está bien, solo necesita agregar ',' después de la declaración de valores
sam
44
INSERTAR EN @blah (ID, Nombre), VALUES (123, 'Timmy'), VALUES (124, 'Jonny'), VALUES (125, 'Sally')
sam
1
Solo una precaución: puede insertar hasta 1000 filas solo con este método. INSERTAR EN #TEST (LWPurchaseOrderID) VALUES (935791), (935933)
Anoop Verma
16
2005 ya no es compatible. Para 2008, 2012 y 2016 casi puedes usar lo que pones INSERT INTO @blah (ID, Name) VALUES (123, 'Timmy'), (124, 'Jonny'), (125, 'Sally') "VALORES" solo aparece una vez y necesitas comas entre los conjuntos.
J. Chris Compton

Respuestas:

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

Para SQL Server 2008, puede hacerlo en una cláusula VALUES exactamente según la declaración en su pregunta (solo necesita agregar una coma para separar cada declaración de valores) ...

gbn
fuente
10
¿Es esto más eficiente que usar múltiples instrucciones INSERT?
Code Commander
77
@Code Commander: no, ya que es más largo compilar. Sí, ya que solo tiene un inserto. Pero responde a la pregunta: no se repite elINSERT table (columnlist)
gbn
3
@VoidKing Sé que esto ocurre medio año después y es posible que lo hayas descubierto hace mucho tiempo, pero es bastante simple. Al usarlo select, crea un conjunto con columnas y filas, y al diseñar estas filas se pueden insertincorporar a otra tabla con la misma cantidad de columnas. Incluso puede usar una mezcla de literales y valores. Por ejemplo, usar insertwith select 'A', ID from ATableinsertaría 'A' en la primera columna cada vez y el valor de la columna ID de la fila correspondiente de ATable en la segunda columna.
MarioDS
1
Esto también funciona con DB2, que es una nota importante para aquellos de nosotros atrapados en tecnología obsoleta. Los valores separados por una respuesta de coma son mejores en mi opinión para aquellos de ustedes que trabajan en SQL Server 2008 o posterior. El OP puede eliminar todos los "valores" excepto el primero y reemplazarlos con un,
JPK
1
@PRMan no haría eso después de la versión SQL Server 2008. Como se mencionó ...
gbn
510

Su sintaxis casi funciona en SQL Server 2008 (pero no en 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 Cuando se respondió la pregunta, no se hizo evidente que la pregunta se refería a SQL Server 2005. Dejo esta respuesta aquí, ya que creo que aún es relevante.

Daniel Vassallo
fuente
Funciona en SQL Server 2012
user2601995
27
Server 2008 no permite más de 1000 filas insertadas de esta manera.
Michael - ¿Dónde está Clay Shirky?
1
¿Qué sucede si un conjunto de valores es defectuoso? ¿Todos los insertos retrocederán o solo la fila defectuosa?
netblognet
2
@netblognet Acabo de probar que solo las filas defectuosas no se insertan (todas las demás se insertan correctamente)
Mauricio Gracia Gutiérrez
1
@Michael Se podría levantar stackoverflow.com/a/42703601/5070879
Lukasz Szozda
243

Si sus datos ya están en su base de datos, puede hacer:

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

Si necesita codificar los datos, SQL 2008 y versiones posteriores le permiten hacer lo siguiente ...

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

Usando la INSERT INTO ... VALUESsintaxis como en la respuesta de Daniel Vassallo hay una limitación molesta:

De MSDN

El número máximo de filas que se pueden construir insertando filas directamente en la lista VALUES es 1000

La forma más fácil de omitir esta limitación es usar una tabla 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


Esto funcionará a partir de SQL Server 2008+

Lukasz Szozda
fuente
¿Puedo tener un enlace a un artículo sobre esta sintaxis 'sub'?
CodeCamper
2
@CodeCamper docs.microsoft.com/en-us/sql/t-sql/queries/… sección:C. Specifying multiple values as a derived table in a FROM clause
Lukasz Szozda
3
La ventaja de esta respuesta es que proporciona una forma de especificar valores idénticos sin repetirlos (que es lo que estaba buscando). Por ejemplo, con una tercera columna que es idéntica, no necesitaría repetirla mil veces.
Vadim Berman,
1
@VadimBerman Sí, ese es un buen escenario cuando no hay un valor predeterminado definido en la tabla.
Lukasz Szozda
14

Podrías hacer esto (feo pero funciona):

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

Esto logrará lo que estás preguntando:

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

Para futuros desarrolladores, también puede insertar desde otra tabla :

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

O incluso de varias tablas :

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

Puedes usar una unión:

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
fuente
6

Esto parece correcto para SQL Server 2008. Para SS2005 y anteriores, debe repetir la instrucción VALUES.

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

EDITAR :: Mi mal. Debe repetir el 'INSERTAR EN' para cada fila en 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
fuente
6

Sería más fácil usar XML en SQL Server para insertar varias filas; de lo contrario, sería muy tedioso.

Vea el artículo completo con explicaciones de código aquí http://www.cyberminds.co.uk/blog/articles/how-to-insert-multiple-rows-in-sql-server.aspx

Copie el siguiente código en el servidor SQL para ver una muestra.

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
fuente
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

O PUEDE USAR OTRA MANERA

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

He estado usando lo siguiente:

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

Agregará diez filas con GUID únicos para ID y Nombre.

Nota: no finalice la última línea (GO 10) con ';' porque arrojará un error: se produjo un error de secuencia de comandos fatal. Se encontró una sintaxis incorrecta al analizar GO.

valentinvs
fuente
5

En correspondencia con INSERT (Transact-SQL) (SQL Server 2005) no puede omitir INSERT INTO dbo.Blahy debe especificarlo cada vez o usar otra sintaxis / enfoque,

abatishchev
fuente
2

Esto funciona muy rápido y eficiente en SQL. Supongamos que tienes tabla 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
)

Por lo tanto, no puede insertar múltiples registros en esta tabla utilizando la siguiente consulta sin repetir la instrucción de inserción,

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)

También con C # usando SqlBulkCopy bulkcopy = new SqlBulkCopy(con)

Puedes insertar 10 filas a la 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
fuente
0

Oracle SQL Server Insertar varias filas

En una inserción multitarea, inserta filas calculadas derivadas de las filas devueltas de la evaluación de una subconsulta en una o más tablas.

INSERTAR TODO incondicionalmente : - Para agregar varias filas a una tabla a la vez, utilice la siguiente forma de la instrucción INSERTAR:

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 múltiples insert_into_clauses para realizar una inserción multitarea incondicional. Oracle Database ejecuta cada insert_into_clause una vez para cada fila devuelta por la subconsulta.

Servidor MySQL Insertar múltiples filas

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

Consulta de inserción de fila única

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

Otros aquí han sugerido un par de sintaxis de registros múltiples. Explicando eso, sugiero que primero inserte en una tabla temporal e inserte su tabla principal desde allí.

La razón de esto es que cargar los datos de una consulta puede llevar más tiempo, y puede terminar bloqueando la tabla o las páginas más de lo necesario, lo que ralentiza otras consultas que se ejecutan en esa tabla.

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

Además, sus ID probablemente deberían ser de identidad (1,1) y probablemente no debería insertarlas, en la gran mayoría de las circunstancias. Deje que SQL decida eso por usted.

tsilb
fuente