Як обробляються ключі автоматичного посилення в INSERT (SELECT * FROM…)


13

У мене є table1і table2в MySQL. Обидва мають первинний auto_incrementключ id.

Якщо схеми таблиці збігаються, і я роблю, 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 як значення? (Щодо вашого другого абзацу)
Саша Рамбо

1
Так, SQL_MODE = NO_AUTO_VALUE_ON_ZERO , інакше ми ніколи не можемо вставити буквальне нульове значення у стовпець AI. Якщо ви користуєтесь цим режимом SQL, NULL все ще працює для активації генератора AI або пропускання стовпця теж працює.
Білл Карвін

@BillKarwin, Що стосується вашого останнього абзацу, після отримання підрезультату select * from table, чи немає способу оперувати цим субрезультатом, щоб видалити його перший стовпець?
Pacerier

@Pacerier, якщо я правильно зрозумів, ви запитуєте, чи select *може це означати select * except for the first column. Відповідь - ні. select *завжди запитує всі стовпці з цієї таблиці. Якщо ви хочете підмножину, ви повинні прописати потрібні стовпці.
Білл Карвін

@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

Ідентифікатор вибору буде тим самим значенням, що вставляється в таблицю. Це призведе до помилки, якщо ви намагаєтесь дублювати існуючі рядки.

Білл Карвін: Перш ніж запитати, у 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
Розумний, але для мене це враховує написання повного списку імен стовпців, які ви хочете вставити.
Білл Карвін

1
Ну, це mysql автоматично виписує його проти того, як це робити вручну. Якщо у вас є таблиці з великою кількістю стовпців, це не дозволить вам пропустити одну або неправильно написати кілька.
кривда
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.