Как обрабатываются ключи auto_increment в INSERT (SELECT * FROM…)
13
У меня есть table1и table2в MySQL. У обоих есть первичный auto_incrementключ id.
Если схемы таблиц совпадают, и я делаю, INSERT INTO table1 (SELECT * FROM table2)что происходит с новыми строками, вставленными в table1? Сохраняют ли они свои старые idзначения и порождают ли конфликты, когда строка из table1них совпадает id? Новые значения генерируются auto_increment? Это зависит от системы хранения или блокировки?
Вы можете вставить в столбец автоинкремента и указать значение. Это хорошо; он просто переопределяет генератор автоинкремента.
Если вы попытаетесь вставить значение NULL или 0 или DEFAULT, или если вы опустите столбец автоинкремента из столбцов в вашем операторе INSERT, это активирует генератор автоинкремента.
Так что это нормально INSERT INTO table1 SELECT * FROM table2(кстати, вам не нужны скобки). Это означает, что значения id в table2будут скопированы дословно, и неtable1 будут генерировать новые значения.
Если вы хотитеtable1 генерировать новые значения, вы не можете сделать SELECT *. Либо вы используете ноль или 0 для столбца id:
Или же вы опускаете столбец как из списка столбцов оператора INSERT, так и из списка выбора оператора SELECT:
-- No id in either case:INSERTINTO 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 NOTIN('id')),'
from <table> WHERE id = <id>');
PREPARE stmt1 FROM@sql;EXECUTE stmt1;
Это приведет к тому, что новая строка получит автоматически увеличенный идентификатор вместо идентификатора из выбранной строки.
Умно, но для меня это считается полным списком имен столбцов, которые вы хотите вставить.
Билл Карвин
1
Ну, это MySQL автоматически по сравнению с выполнением вручную. Если у вас есть таблицы с большим количеством столбцов, это позволит вам не пропустить одну или несколько ошибок в написании.
select * from table
, нет ли способа воздействовать на этот подрезультат, чтобы удалить его первый столбец?select *
может ли это иметь в видуselect * except for the first column
. Ответ - нет.select *
всегда запрашивает все столбцы из этой таблицы. Если вы хотите подмножество, вы должны указать столбцы, которые вы хотите.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
, что вы думаете?Идентификатор из выбора будет таким же значением, вставленным в таблицу. Это приведет к ошибке, если вы попытаетесь дублировать существующие строки.
Это может быть достигнуто с некоторой креативностью:
Это приведет к тому, что новая строка получит автоматически увеличенный идентификатор вместо идентификатора из выбранной строки.
источник