มีการจัดการคีย์ auto_increment ใน INSERT อย่างไร (เลือก * จาก ... )


13

ฉันมีtable1และtable2ใน MySQL ทั้งสองมีหลักสำคัญauto_incrementid

หากตาราง schemas ตรงกันและฉันจะINSERT INTO table1 (SELECT * FROM table2)เกิดอะไรขึ้นเกี่ยวกับแถวใหม่ที่แทรกเข้าไปtable1? พวกเขาเก็บidค่าเก่าของพวกเขาและสร้างความขัดแย้งเมื่อแถวจากtable1มีเหมือนกันidหรือไม่ ค่าใหม่ถูกสร้างขึ้นโดย auto_increment หรือไม่ มันขึ้นอยู่กับเครื่องมือจัดเก็บหรือล็อค?

คำตอบ:


13

คุณสามารถแทรกลงในคอลัมน์เพิ่มอัตโนมัติและระบุค่า นี่เป็นเรื่องปกติ มันเพียงแทนที่ตัวสร้างการเพิ่มอัตโนมัติ

ถ้าคุณพยายามแทรกค่า NULL หรือ 0 หรือDEFAULTหรือถ้าคุณไม่ใส่คอลัมน์เพิ่มอัตโนมัติจากคอลัมน์ในคำสั่ง INSERT ของคุณสิ่งนี้จะเปิดใช้งานตัวสร้างการเพิ่มอัตโนมัติ

ดังนั้นจึงเป็นเรื่องที่ดีINSERT INTO table1 SELECT * FROM table2(โดยคุณไม่จำเป็นต้องใช้วงเล็บ) ซึ่งหมายความว่าค่า id ในtable2จะถูกคัดลอกเป็นคำต่อคำและtable1จะไม่สร้างค่าใหม่

หากคุณต้องการ ที่จะสร้างค่านิยมใหม่ที่คุณไม่สามารถทำได้table1 SELECT *ไม่ว่าคุณจะใช้ null หรือ 0 สำหรับคอลัมน์ id:

INSERT INTO table1 SELECT 0, col1, col2, col3, ... FROM table2;

หรือมิฉะนั้นคุณจะละเว้นคอลัมน์จากรายการคอลัมน์ของคำสั่ง INSERT และรายการเลือกคำสั่ง SELECT

-- No id in either case:
INSERT INTO table1 (col1, col2, col3) SELECT col1, col2, col3, ... FROM table2;

ก่อนที่คุณจะถามไม่มีไวยากรณ์ใน SQL สำหรับ "select * ยกเว้นหนึ่งคอลัมน์" คุณต้องสะกดรายชื่อคอลัมน์ทั้งหมดที่คุณต้องการแทรก


ไม่มีตัวเลือกที่อนุญาต / ไม่อนุญาตให้แทรก 0 เป็นค่าหรือไม่ (เกี่ยวกับย่อหน้าที่ 2 ของคุณ)
Sascha Rambeaud

1
ใช่SQL_MODE = NO_AUTO_VALUE_ON_ZEROไม่เช่นนั้นเราจะไม่สามารถแทรกค่าศูนย์ตามตัวอักษรลงในคอลัมน์ AI ได้ หากคุณใช้โหมด SQL นี้ NULL ยังคงทำงานเพื่อเปิดใช้งานตัวสร้าง AI หรือเว้นคอลัมน์ก็ทำงานเช่นกัน
Bill Karwin

@BillKarwin เกี่ยวกับย่อหน้าสุดท้ายของคุณหลังจากรับ subresult select * from tableคุณไม่มีวิธีดำเนินการใน subresult นี้เพื่อลบคอลัมน์แรกหรือไม่
Pacerier

@Pacerier ถ้าผมเข้าใจถูกต้องที่คุณกำลังถามว่าอาจจะหมายถึงselect * select * except for the first columnคำตอบคือไม่ select *ขอคอลัมน์ทั้งหมดจากตารางนั้นเสมอ หากคุณต้องการเซ็ตย่อยคุณต้องสะกดคอลัมน์ที่คุณต้องการ
Bill Karwin

@BillKarwin, อืมฉันกำลังคิดที่จะหมุนโต๊ะเพื่อทำตามแนวที่คำสั่งจากนั้นหมุนมันกลับไปเช่นselect*from transpose(select*from(transpose(select*from table where Id=1))where col_name<>Id)หรืออาจจะรวบรัดขึ้นselect*from table where Id=1 and $col<>Idว่าคุณคิดอย่างไร?
Pacerier

3

ID จากตัวเลือกจะเป็นค่าเดียวกันที่แทรกเข้าไปในตาราง สิ่งนี้จะส่งผลให้เกิดข้อผิดพลาดหากคุณพยายามทำซ้ำแถวที่มีอยู่

Bill Karwin:ก่อนที่คุณจะถามไม่มีไวยากรณ์ใน SQL สำหรับ "select * ยกเว้นหนึ่งคอลัมน์"

สามารถทำได้ด้วยความคิดสร้างสรรค์:

SET @sql = CONCAT('INSERT INTO <table> SELECT null, 
    ', (SELECT GROUP_CONCAT(COLUMN_NAME) 
    FROM information_schema.columns 
    WHERE table_schema = '<database>' 
    AND table_name = '<table>' 
    AND column_name NOT IN ('id')), ' 
from <table> WHERE id = <id>');  

PREPARE stmt1 FROM @sql;
EXECUTE stmt1;

ซึ่งจะส่งผลให้แถวใหม่ได้รับรหัสที่เพิ่มขึ้นอัตโนมัติแทนที่จะเป็นรหัสจากแถวที่เลือก


2
ฉลาด แต่สำหรับฉันแล้วนับว่าเป็นการสะกดรายชื่อคอลัมน์ทั้งหมดที่คุณต้องการแทรก
Bill Karwin

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