แทรกหลายแถวโดยไม่ต้องทำซ้ำคำสั่ง“ INSERT INTO …”?


536

ฉันรู้ว่าฉันเคยทำสิ่งนี้มาหลายปีแล้ว แต่ฉันจำไวยากรณ์ไม่ได้และไม่พบที่ใดก็ได้เนื่องจากดึงเอกสารช่วยเหลือและบทความจำนวนมากเกี่ยวกับ "การนำเข้าจำนวนมาก"

นี่คือสิ่งที่ฉันต้องการจะทำ แต่ไวยากรณ์ไม่ถูกต้อง ... โปรดคนที่เคยทำมาก่อนช่วยฉันด้วย :)

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

ฉันรู้ว่านี่อยู่ใกล้กับไวยากรณ์ที่ถูกต้อง ฉันอาจต้องการคำว่า "เป็นกลุ่ม" ในนั้นหรือบางสิ่งบางอย่างฉันจำไม่ได้ ความคิดใด ๆ

ฉันต้องการสิ่งนี้สำหรับฐานข้อมูล 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
โค้ดด้านบนของคุณใช้ได้เพียงแค่เพิ่ม ',' หลังจากข้อความสั่ง
sam

4
INSERT INTO @blah (ID, ชื่อ), ค่า (123, 'Timmy'), ค่า (124, 'Jonny'), ค่า (125, 'Sally')
sam

1
ข้อควรระวัง: คุณสามารถแทรกได้มากถึง 1,000 แถวโดยวิธีนี้ 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') "คุณค่า" จะปรากฏขึ้นครั้งเดียวและคุณต้องจุลภาคระหว่างชุด
J. Chris Compton

คำตอบ:


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

สำหรับ SQL Server 2008 สามารถทำได้ในหนึ่ง VALUES clause ตรงตามคำสั่งในคำถามของคุณ (คุณเพียงแค่ต้องเพิ่มเครื่องหมายจุลภาคเพื่อคั่นแต่ละคำสั่งค่า)


10
สิ่งนี้มีประสิทธิภาพมากกว่าการใช้คำสั่ง INSERT หลายรายการหรือไม่
ผู้บัญชาการรหัส

7
@ Code Commander: ไม่ในการคอมไพล์อีกต่อไป ใช่เพราะคุณมีส่วนแทรกอย่างเดียวเท่านั้น แต่มันก็ตอบคำถาม: อย่าทำซ้ำINSERT table (columnlist)
gbn

3
@VoidKing ฉันรู้ว่าสิ่งนี้เกิดขึ้นในครึ่งปีหลังและคุณอาจจะรู้เรื่องนี้มานานแล้ว แต่มันค่อนข้างง่ายจริงๆ โดยการใช้selectคุณสร้างชุดที่มีคอลัมน์และแถวและโดยการออกแบบแถวเหล่านี้สามารถแก้ไขinsertลงในตารางอื่นด้วยจำนวนคอลัมน์ที่เท่ากัน คุณสามารถใช้ตัวอักษรและค่าผสมได้ ตัวอย่างเช่นการใช้insertกับselect 'A', ID from ATableจะแทรก 'A' ในคอลัมน์แรกทุกครั้งและค่าคอลัมน์ ID ของแถวที่สอดคล้องกันของ ATable ในคอลัมน์ที่สอง
MarioDS

1
สิ่งนี้ยังทำงานร่วมกับ DB2 ซึ่งเป็นสิ่งสำคัญสำหรับเราที่ติดอยู่ในเทคโนโลยีที่ล้าสมัย ค่าที่คั่นด้วยคำตอบด้วยเครื่องหมายจุลภาคดีกว่าในใจสำหรับผู้ที่ทำงานใน SQL Server 2008 หรือใหม่กว่า OP สามารถลบ "ค่า" ทั้งหมดยกเว้นค่าแรกและแทนที่ด้วย,
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 ไม่อนุญาตให้แทรกมากกว่า 1,000 แถวด้วยวิธีนี้
ไมเคิล - Clay Shirky อยู่ที่ไหน

1
จะเกิดอะไรขึ้นหากชุดค่าหนึ่งมีข้อบกพร่อง เม็ดมีดทั้งหมดจะถูกม้วนกลับหรือเป็นเพียงแถวที่ผิดพลาดหรือไม่
netblognet

2
@netblognet ฉันเพิ่งทดสอบว่ามีเพียงแถวที่ผิดพลาดเท่านั้นที่ไม่ได้แทรก (แถวอื่นทั้งหมดถูกแทรกอย่างถูกต้อง)
Mauricio Gracia Gutierrez


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ไวยากรณ์เหมือนในคำตอบของ Daniel Vassalloมีข้อ จำกัด ที่น่ารำคาญ:

จากMSDN

จำนวนแถวสูงสุดที่สามารถสร้างได้โดยการแทรกแถวโดยตรงในรายการค่าคือ1,000

วิธีที่ง่ายที่สุดในการละเว้นข้อ จำกัด นี้คือการใช้ตารางที่ได้รับเช่น:

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+


ฉันขอลิงค์ไปยังบทความเกี่ยวกับไวยากรณ์ 'ย่อย' นี้ได้ไหม
CodeCamper

2
@CodeCamper docs.microsoft.com/en-us/sql/t-sql/queries/ ส่วน:C. Specifying multiple values as a derived table in a FROM clause
Lukasz Szozda

3
ข้อดีของคำตอบนี้คือให้วิธีการระบุค่าที่เหมือนกันโดยไม่ต้องทำซ้ำ (ซึ่งเป็นสิ่งที่ฉันกำลังมองหา) เช่นกับคอลัมน์ที่สามที่เหมือนกันคุณไม่จำเป็นต้องทำซ้ำเป็นพันครั้ง
Vadim Berman

1
@VadimBerman ใช่นั่นเป็นสถานการณ์ที่ดีเมื่อไม่มีการกำหนดค่าเริ่มต้นไว้ในตาราง
Lukasz Szozda

14

คุณสามารถทำได้ (น่าเกลียด แต่มันได้ผล):

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

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

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

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)

6

ฉันใช้สิ่งต่อไปนี้:

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

มันจะเพิ่มสิบแถวพร้อม GUID เฉพาะสำหรับ ID และชื่อ

หมายเหตุ: อย่าจบบรรทัดสุดท้าย (GO 10) ด้วย ';' เพราะจะทำให้เกิดข้อผิดพลาด: เกิดข้อผิดพลาดในการเขียนสคริปต์ที่ร้ายแรง พบไวยากรณ์ที่ไม่ถูกต้องขณะแยกวิเคราะห์ GO


5

สอดคล้องกับINSERT (Transact-SQL) (SQL Server 2005) คุณไม่สามารถละเว้นINSERT INTO dbo.Blahและต้องระบุทุกครั้งหรือใช้ไวยากรณ์ / แนวทางอื่น


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 แทรกหลายแถว

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

นอกจากนี้ ID ของคุณอาจเป็นข้อมูลประจำตัว (1,1) และคุณอาจไม่ควรแทรกในกรณีส่วนใหญ่ ให้ SQL ตัดสินสิ่งนั้นสำหรับคุณ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.