Вставить несколько строк БЕЗ повторения части «INSERT INTO…» оператора?

536

Я знаю, что сделал это несколько лет назад, но не могу вспомнить синтаксис и не могу его найти нигде из-за загрузки тонны справочных документов и статей о «массовом импорте».

Вот что я хочу сделать, но синтаксис не совсем правильный ... пожалуйста, кто-то, кто делал это раньше, помогите мне :)

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

Я знаю, что это близко к правильному синтаксису. Мне может понадобиться слово «BULK» или что-то еще, я не могу вспомнить. Есть идеи?

Мне это нужно для базы данных SQL Server 2005. Я пробовал этот код, но безрезультатно:

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

Я получаю Incorrect syntax near the keyword 'VALUES'.

Тимоти Хоури
источник
4
Вышеупомянутый код в порядке, просто нужно добавить оператор ',' после значений
Сэм
4
INSERT INTO @blah (идентификатор, имя), ЦЕННОСТИ (123, «Тимми»), ЦЕННОСТИ (124, «Джонни»), ЦЕННОСТИ (125, «Салли»)
Сам
1
Только предостережение: вы можете вставить до 1000 строк только этим методом. INSERT INTO # TEST (LWPurchaseOrderID) ЗНАЧЕНИЯ (935791), (935933)
Anoop Verma
16
2005 больше не поддерживается. В 2008, 2012 и 2016 годах вы почти можете использовать то, что вы добавили, INSERT INTO @blah (ID, Name) VALUES (123, 'Timmy'), (124, 'Jonny'), (125, 'Sally') «ЗНАЧЕНИЯ» появляются только один раз, и вам нужно запятые между наборами.
Дж. Крис Комптон

Ответы:

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

Для SQL Server 2008, можете сделать это в одном предложении VALUES точно в соответствии с оператором в вашем вопросе (вам просто нужно добавить запятую для разделения каждого оператора значений) ...

ГБН
источник
10
Является ли это более эффективным, чем использование нескольких операторов INSERT?
Code Commander
7
@Code Commander: нет, в том, что он дольше компилируется. Да, в том, что у вас есть только одна вставка. Но это отвечает на вопрос: нет повторенияINSERT table (columnlist)
gbn
3
@VoidKing Я знаю, что это произойдет через полгода, и вы, возможно, уже поняли это, но это действительно довольно просто. Используя его, selectвы создаете набор со столбцами и строками, и, создавая эти строки, они могут быть insertпреобразованы в другую таблицу с равным количеством столбцов. Вы даже можете использовать смесь литералов и значений. Например, использование insertwith select 'A', ID from ATableбудет вставлять «A» в первый столбец каждый раз, а значение столбца ID соответствующей строки ATable во втором столбце.
MarioDS
1
Это также работает с DB2, которая является важной характеристикой для тех из нас, кто застрял в устаревшей технологии. Значения, разделенные запятым ответом, лучше для тех из вас, кто работает в SQL Server 2008 или новее. ОП может удалить все «значения», кроме первого, и заменить на,
JPK
1
@PRMan, вы бы не сделали этого после версии SQL Server 2008. Как уже упоминалось ...
gbn
510

Ваш синтаксис почти работает в SQL Server 2008 (но не в 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 Когда на вопрос был дан ответ, не было ясно, что речь шла о SQL Server 2005. Я оставляю этот ответ здесь, так как считаю, что он все еще актуален.

Даниэль Вассалло
источник
Работает в SQL Server 2012
user2601995
27
Server 2008 не позволяет вставлять более 1000 строк таким образом.
Майкл - Где Клэй Ширки
1
Что происходит, если один набор значений неисправен? Будут ли откатываться все вставки или просто неисправный ряд?
netblognet
2
@netblognet Я только что проверил, что не вставляются только ошибочные строки (все остальные вставлены правильно)
Маурисио Грасия Гутьеррес
1
@Michael Это может быть отменено stackoverflow.com/a/42703601/5070879
Лукаш Шозда
243

Если ваши данные уже есть в вашей базе данных, вы можете сделать:

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

Если вам нужно жестко закодировать данные, то SQL 2008 и более поздние версии позволят вам сделать следующее ...

INSERT INTO MyTable (Name, ID)
VALUES ('First',1),
('Second',2),
('Third',3),
('Fourth',4),
('Fifth',5)
Джордж
источник
28

Использование INSERT INTO ... VALUESсинтаксиса, как в ответе Даниэля Вассалло, имеет одно досадное ограничение:

Из MSDN

Максимальное количество строк, которое можно построить путем вставки строк непосредственно в список ЗНАЧЕНИЙ, составляет 1000.

Самый простой способ обойти это ограничение - использовать производную таблицу, например:

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

LiveDemo


Это будет работать, начиная с SQL Server 2008+

Лукаш Шозда
источник
Могу ли я получить ссылку на статью об этом 'sub' синтаксисе.
CodeCamper
2
@CodeCamper docs.microsoft.com/en-us/sql/t-sql/queries/… раздел:C. Specifying multiple values as a derived table in a FROM clause
Лукаш Шозда
3
Преимущество этого ответа заключается в том, что он позволяет указывать одинаковые значения без их повторения (что я и искал). Например, с третьим столбцом, который идентичен, вам не нужно будет повторять это тысячу раз.
Вадим Берман
1
@VadimBerman Да, это хороший сценарий, когда для таблицы не определено значение по умолчанию.
Лукаш Шозда
14

Вы могли бы сделать это (некрасиво, но это работает):

INSERT INTO dbo.MyTable (ID, Name) 
select * from
(
 select 123, 'Timmy'
  union all
 select 124, 'Jonny' 
  union all
 select 125, 'Sally'
 ...
) x
davek
источник
10

Это достигнет того, о чем вы спрашиваете:

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

Для будущих разработчиков вы также можете вставить из другой таблицы :

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

Или даже из нескольких таблиц :

INSERT INTO table1 (column2, column3)
    SELECT 
         t2.column, 
         t3.column
    FROM table2 t2
         INNER JOIN table3 t3
         ON t2.ID = t3.ID
Tigerjz32
источник
8

Вы можете использовать союз:

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)
Кейд Ру
источник
6

Это выглядит нормально для SQL Server 2008. Для SS2005 и более ранних версий вам необходимо повторить оператор VALUES.

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

РЕДАКТИРОВАТЬ :: Мой плохо. Вы должны повторить «INSERT INTO» для каждой строки в 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
источник
6

Было бы проще использовать XML в SQL Server для вставки нескольких строк, иначе это станет очень утомительным.

Посмотреть полную статью с объяснениями кода здесь http://www.cyberminds.co.uk/blog/articles/how-to-insert-multiple-rows-in-sql-server.aspx

Скопируйте следующий код на сервер sql, чтобы просмотреть образец.

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)
Джо
источник
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

ИЛИ ВЫ МОЖЕТЕ ИСПОЛЬЗОВАТЬ ДРУГОЙ ПУТЬ

INSERT INTO MyTable (FirstCol, SecondCol)
VALUES 
('First',1),
('Second',2),
('Third',3),
('Fourth',4),
('Fifth',5)
gngolakia
источник
6

Я использовал следующее:

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

Это добавит десять строк с уникальными идентификаторами GUID для идентификатора и имени.

Примечание: не заканчивайте последнюю строку (GO 10) знаком ';' потому что он выдаст ошибку: произошла фатальная ошибка скриптинга. При синтаксическом анализе GO обнаружен неправильный синтаксис.

valentinvs
источник
5

В соответствии с INSERT (Transact-SQL) (SQL Server 2005) вы не можете пропустить INSERT INTO dbo.Blahи должны указывать его каждый раз или использовать другой синтаксис / подход,

abatishchev
источник
2

Это работает очень быстро и эффективно в SQL. Предположим, у вас есть таблица 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
)

Таким образом, вы не можете вставить несколько записей в эту таблицу, используя следующий запрос, не повторяя оператор вставки,

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)

Также с использованием C # SqlBulkCopy bulkcopy = new SqlBulkCopy(con)

Вы можете вставить 10 строк одновременно

   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();
        }
Чаран Гейт
источник
0

Oracle SQL Server вставка нескольких строк

При множественной вставке вы вставляете вычисленные строки, полученные из строк, возвращенных в результате оценки подзапроса, в одну или несколько таблиц.

Безусловный INSERT ALL : - Чтобы добавить несколько строк в таблицу одновременно, вы используете следующую форму инструкции 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

Укажите ALL, а затем несколько insert_into_clauses для выполнения безусловной множественной вставки. Oracle Database выполняет каждый insert_into_clause один раз для каждой строки, возвращаемой подзапросом.

MySQL Server Вставка нескольких строк

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

Запрос вставки в одну строку

INSERT INTO table_name (col1,col2) VALUES(val1,val2);
Яши
источник
0

Другие здесь предложили пару синтаксисов из нескольких записей. Поясняя это, я предлагаю вам сначала вставить временную таблицу и оттуда вставить основную таблицу.

Причина этого заключается в том, что загрузка данных из запроса может занять больше времени, и вы можете в конечном итоге заблокировать таблицу или страницы дольше, чем это необходимо, что замедляет выполнение других запросов к этой таблице.

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

Кроме того, ваши идентификаторы должны быть идентичными (1,1), и вам, вероятно, не следует их вставлять в большинстве случаев. Пусть SQL решит это за вас.

tsilb
источник