INSERT INTO ... SELECT без детализации всех столбцов - PullRequest
20 голосов
/ 28 ноября 2011

Как вставить выбранные строки из table_source в table_target, используя SQL в MySQL, где:

  • Обе таблицы имеют одинаковую схему
  • Все столбцы должны быть перенесены, кромеавтоинкремент id
  • Без явной записи всех имен столбцов, поскольку это было бы утомительно

Тривиальный INSERT INTO table_target SELECT * FROM table_source завершается ошибкой при дублировании записей для первичного ключа.

Ответы [ 10 ]

20 голосов
/ 28 ноября 2011

Либо вы перечисляете все поля, которые вы хотите вставить ... выберите, либо вы используете что-то другое для создания списка для вас.

В SQL нет ничего похожего на SELECT * except somefield FROM, поэтому вам придется прикусить пулю и выписать имена полей.

18 голосов
/ 28 ноября 2011

Должны быть указаны имена столбцов -

INSERT INTO table_target SELECT NULL, column_name1, column_name2, column_name3, ...
  FROM table_source;

Просто передайте NULL в качестве значения для поля идентификатора автоинкремента.

5 голосов
/ 28 ноября 2011

Конечно, первичный ключ должен быть уникальным.Это зависит от того, чего вы хотите достичь, но вы можете исключить строки с первичным ключом, который уже существует.

INSERT INTO table_target SELECT * FROM table_source 
WHERE table_source.id NOT IN (SELECT id FROM table_target)

ОБНОВЛЕНИЕ : поскольку вам также нужны дополнительные строки, вы должны решитьконфликт первый, есть ли у table_source отношения?Если нет, вы можете изменить эти ключи:

UPDATE table_source SET id = id + 1000
WHERE id IN (SELECT id FROM table_target)

Где 1000 - это константа, достаточно большая, чтобы они шли после конца вашей таблицы.

4 голосов
/ 28 ноября 2011

Утомительно, но безопасно и правильно.

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

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

2 голосов
/ 01 августа 2016

Это мое окончательное решение для массового обновления с помощью команды «заменить вставку».

SET @@session.group_concat_max_len = @@global.max_allowed_packet;
SET @schema_db = 'db';
SET @tabl = 'table';
SET @cols = (SELECT CONCAT('`',GROUP_CONCAT(COLUMN_NAME SEPARATOR '`, `'), '`') FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = @schema_db AND TABLE_NAME = @tabl GROUP BY TABLE_NAME);
SET @Querystr = CONCAT('REPLACE INTO ',@schema_db,'.',@tabl,' SELECT ', @cols,' FROM import.tbl_', @tabl);

PREPARE stmt FROM @Querystr;
EXECUTE stmt;
1 голос
/ 28 ноября 2011

Я думаю, вы могли бы использовать синтаксис, такой как:

INSERT INTO table (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=c+1;

REF: http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html Надеюсь, это поможет

0 голосов
/ 13 марта 2018

Самый простой способ сделать это - использовать phpmyadmin, чтобы написать список столбцов, а затем изменить его по мере необходимости. В приведенном ниже примере я хочу дублировать строку с id = 1078, и в этой таблице у меня есть идентификатор уникального автоматического увеличения и псевдоним unique.t поэтому я создал свой запрос следующим образом, с идентификатором и псевдонимом заменить желаемое значение и это сработало как шарм.

INSERT INTO sy3_menu выберите 1079, menutype, title, "alias", note, path, link, type, published, parent_id, level, component_id, checked_out, checked_out_time, browserNav, access, img, template_style_id, params, lft, rgt, home, language client_id из sy3_menu где id = 1078

В качестве альтернативы, для автоматического увеличения идентификатора используйте следующий оператор Join: INSERT INTO sy3_menu выберите * от (ВЫБРАТЬ МАКС. (id + 1) из sy3_menu) а объединение (выберите menutype, title, "alias", note, path, link, type, published, parent_id, level, component_id, checked_out, checked_out_time, browserNav, access, img, template_style_id, params, lft, rgt, home, language, client_id от sy3_menu где id = 1079) b

0 голосов
/ 01 августа 2016

Кажется, что столбцы нельзя указывать в качестве заполнителя в подготовленном операторе MySQL.Я собрал следующее решение для тестирования:

SET @schema_db = 'DB';
SET @table = 'table';
SET @cols = (SELECT CONCAT(GROUP_CONCAT(COLUMN_NAME SEPARATOR ', '), "\n") FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = @schema_db AND TABLE_NAME = @table GROUP BY TABLE_NAME);
SET @Querystr = CONCAT('SELECT',' ', @cols,' ','FROM',' ',@schema_db,'.',@table,' ', 'Limit 5');
PREPARE stmt FROM @Querystr;
EXECUTE stmt;
0 голосов
/ 29 ноября 2011

Вы, вероятно, можете сделать это с помощью готовых заявлений.

PREPARE table_target_insert FROM 'INSERT INTO table_target SELECT ? FROM table_source';
SET @cols:='';
SELECT @cols:=GROUP_CONCAT(IF(column_name = 'id','NULL',column_name) separator ",") FROM information_schema.columns WHERE table_name='table_source';
EXECUTE table_target_insert USING @cols;
0 голосов
/ 28 ноября 2011

INSERT IGNORE просто «обойти» дублирующиеся строки.

http://dev.mysql.com/doc/refman/5.5/en/insert.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...