Insérer plusieurs lignes SANS répéter la partie «INSÉRER DANS…» de l'instruction?

536

Je sais que je l'ai fait il y a des années, mais je ne me souviens pas de la syntaxe, et je ne la trouve nulle part en raison de la quantité de documents d'aide et d'articles sur les "importations en masse".

Voici ce que je veux faire, mais la syntaxe n'est pas tout à fait correcte ... s'il vous plaît, quelqu'un qui l'a déjà fait, aidez-moi :)

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

Je sais que cela est proche de la bonne syntaxe. Je pourrais avoir besoin du mot "VRAC" là-dedans, ou quelque chose, je ne me souviens pas. Une idée?

J'en ai besoin pour une base de données SQL Server 2005. J'ai essayé ce code, en vain:

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

Je suis en train Incorrect syntax near the keyword 'VALUES'.

Timothy Khouri
la source
4
Votre code ci-dessus est correct, il suffit d'ajouter «,» après la déclaration de valeurs
sam
4
INSÉRER DANS @blah (ID, Nom), VALEURS (123, 'Timmy'), VALEURS (124, 'Jonny'), VALEURS (125, 'Sally')
sam
1
Juste une mise en garde: vous ne pouvez insérer jusqu'à 1000 lignes que par cette méthode. INSÉRER DANS LES VALEURS #Test (LWPurchaseOrderID) (935791), (935933)
Anoop Verma
16
2005 n'est plus pris en charge. Pour 2008, 2012 et 2016, vous pouvez presque utiliser ce que vous mettez INSERT INTO @blah (ID, Name) VALUES (123, 'Timmy'), (124, 'Jonny'), (125, 'Sally') "VALEURS" n'apparaît qu'une seule fois et vous avez besoin de virgules entre les ensembles.
J. Chris Compton

Réponses:

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

Pour SQL Server 2008, vous pouvez le faire dans une clause VALUES exactement selon l'instruction de votre question (il vous suffit d'ajouter une virgule pour séparer chaque instruction values) ...

gbn
la source
10
Est-ce plus efficace que d'utiliser plusieurs instructions INSERT?
Code Commander
7
@Code Commander: non, car il est plus long à compiler. Oui, en ce que vous n'avez qu'un seul insert. Mais cela répond à la question: pas de répétition de laINSERT table (columnlist)
gbn
3
@VoidKing Je sais que cela arrive six mois plus tard et vous l'avez peut-être compris il y a longtemps, mais c'est vraiment très simple. En utilisant, selectvous créez un ensemble avec des colonnes et des lignes et, par conception, ces lignes peuvent être insertéditées dans une autre table avec un nombre égal de colonnes. Vous pouvez même utiliser un mélange de littéraux et de valeurs. Par exemple, l'utilisation de insertavec select 'A', ID from ATableinsère à chaque fois «A» dans la première colonne et la valeur de la colonne ID de la ligne correspondante de ATable dans la deuxième colonne.
MarioDS
1
Cela fonctionne également avec DB2 qui est un sidenote important pour ceux d'entre nous coincés dans une technologie obsolète. Les valeurs séparées par une virgule sont meilleures dans mon esprit pour ceux d'entre vous qui travaillent dans SQL Server 2008 ou plus récent. L'OP peut supprimer toutes les "valeurs" sauf la première et les remplacer par un,
JPK
1
@PRMan vous ne feriez pas cela après la version SQL Server 2008. Comme mentionné ...
gbn
510

Votre syntaxe fonctionne presque dans SQL Server 2008 (mais pas dans 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 Lorsque la question a été répondue, il n'était pas évident qu'elle faisait référence à SQL Server 2005. Je laisse cette réponse ici, car je pense qu'elle est toujours pertinente.

Daniel Vassallo
la source
Fonctionne dans SQL Server 2012
user2601995
27
Server 2008 n'autorise pas plus de 1 000 lignes insérées de cette façon.
Michael - Où est Clay Shirky
1
Que se passe-t-il si un ensemble de valeurs est défectueux? Tous les inserts seront-ils annulés ou uniquement la ligne défectueuse?
netblognet
2
@netblognet Je viens de tester que seules les lignes défectueuses ne sont pas insérées (toutes les autres sont insérées correctement)
Mauricio Gracia Gutierrez
1
@Michael Il pourrait être levé stackoverflow.com/a/42703601/5070879
Lukasz Szozda
243

Si vos données sont déjà dans votre base de données, vous pouvez faire:

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

Si vous avez besoin de coder en dur les données, SQL 2008 et les versions ultérieures vous permettent de faire ce qui suit ...

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

En utilisant la INSERT INTO ... VALUESsyntaxe comme dans la réponse de Daniel Vassallo, il y a une limitation ennuyeuse:

Depuis MSDN

Le nombre maximum de lignes pouvant être construites en insérant des lignes directement dans la liste VALUES est de 1000

La façon la plus simple d'omettre cette limitation est d'utiliser une table dérivée comme:

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

LiveDemo


Cela fonctionnera à partir de SQL Server 2008+

Lukasz Szozda
la source
Puis-je avoir un lien vers un article sur cette syntaxe «sous».
CodeCamper
2
@CodeCamper docs.microsoft.com/en-us/sql/t-sql/queries/… section:C. Specifying multiple values as a derived table in a FROM clause
Lukasz Szozda
3
L'avantage de cette réponse est qu'elle fournit un moyen de spécifier des valeurs identiques sans les répéter (c'est ce que je cherchais). Par exemple, avec une troisième colonne identique, vous n'auriez pas besoin de la répéter mille fois.
Vadim Berman
1
@VadimBerman Oui, c'est un bon scénario lorsqu'aucune valeur par défaut n'est définie sur la table.
Lukasz Szozda
14

Vous pouvez le faire (moche mais ça marche):

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

Cela permettra d'atteindre ce que vous demandez:

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

Pour les futurs développeurs, vous pouvez également insérer à partir d'une autre table :

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

Ou même à partir de plusieurs tables :

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

Vous pouvez utiliser une union:

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
la source
6

Cela semble OK pour SQL Server 2008. Pour SS2005 et versions antérieures, vous devez répéter l'instruction VALUES.

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

EDIT :: Mon mauvais. Vous devez répéter 'INSERT INTO' pour chaque ligne dans 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
la source
6

Il serait plus facile d'utiliser XML dans SQL Server pour insérer plusieurs lignes sinon cela devient très fastidieux.

Voir l'article complet avec des explications de code ici http://www.cyberminds.co.uk/blog/articles/how-to-insert-multiple-rows-in-sql-server.aspx

Copiez le code suivant sur le serveur SQL pour afficher un exemple.

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
la source
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 VOUS POUVEZ UTILISER UNE AUTRE FAÇON

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

J'utilise les éléments suivants:

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

Il ajoutera dix lignes avec des GUID uniques pour l'ID et le nom.

Remarque: ne terminez pas la dernière ligne (GO 10) par ';' car il générera une erreur: une erreur de script fatale s'est produite. Une syntaxe incorrecte a été rencontrée lors de l'analyse de GO.

valentinvs
la source
5

Correspondant à INSERT (Transact-SQL) (SQL Server 2005), vous ne pouvez pas omettre INSERT INTO dbo.Blahet devez le spécifier à chaque fois ou utiliser une autre syntaxe / approche,

abatishchev
la source
2

Cela fonctionne très rapidement et efficacement en SQL. Supposons que vous ayez Table 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
)

Donc, vous ne pouvez pas insérer plusieurs enregistrements dans ce tableau en utilisant la requête suivante sans répéter l'instruction d'insertion,

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)

Aussi avec C # en utilisant SqlBulkCopy bulkcopy = new SqlBulkCopy(con)

Vous pouvez insérer 10 lignes à la fois

   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
la source
0

Oracle SQL Server insérer plusieurs lignes

Dans une insertion multitable, vous insérez des lignes calculées dérivées des lignes renvoyées par l'évaluation d'une sous-requête dans une ou plusieurs tables.

INSERT ALL inconditionnel : - Pour ajouter plusieurs lignes à une table à la fois, vous utilisez la forme suivante de l'instruction 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

Spécifiez ALL suivi de plusieurs insert_into_clauses pour effectuer une insertion multitable inconditionnelle. Oracle Database exécute chaque insert_into_clause une fois pour chaque ligne renvoyée par la sous-requête.

Serveur MySQL insérer plusieurs lignes

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

Requête d'insertion sur une seule ligne

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

D'autres ici ont suggéré quelques syntaxes multi-enregistrements. Pour exposer cela, je vous suggère d'insérer d'abord dans une table temporaire et d'insérer votre table principale à partir de là.

La raison en est que le chargement des données à partir d'une requête peut prendre plus de temps et vous pouvez finir par verrouiller la table ou les pages plus longtemps que nécessaire, ce qui ralentit les autres requêtes s'exécutant sur cette table.

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

De plus, vos identifiants devraient probablement être des identités (1,1) et vous ne devriez probablement pas les insérer, dans la grande majorité des cas. Laissez SQL décider de ces choses pour vous.

tsilb
la source