INSERT INTO ... SELECT,不详细说明所有列

时间:2011-11-28 14:42:11

标签: mysql sql database

如何使用MySQL中的SQL将所选行从table_source插入table_target,其中:

  • 两个表都具有相同的架构
  • 除自动增量id
  • 外,所有列都应传输
  • 没有明确写出所有列名,因为这将是乏味的

琐碎的INSERT INTO table_target SELECT * FROM table_source在主键的重复条目上失败。

11 个答案:

答案 0 :(得分:18)

必须指定列名 -

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

只需将NULL作为自动增量ID字段的值传递。

答案 1 :(得分:17)

您可以在插入中列出所需的所有字段...选择,或者在外部使用其他内容为您构建列表。

SQL没有类似SELECT * except somefield FROM的内容,所以你必须咬紧牙关并写出字段名称。

答案 2 :(得分:4)

乏味但安全和正确。

编写INSERT语句而不提供列列表会导致难以调试的代码,更重要的是,如果表的定义发生更改,将会破坏非常脆弱的代码。

如果你绝对不能自己编写列名,那么在代码中构建一个工具会相对容易,它会为你创建逗号分隔列表。

答案 3 :(得分:3)

当然,主键必须是唯一的。这取决于您想要实现的目标,但您可以使用已存在的主键排除行。

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

UPDATE :既然你还需要额外的行,你应该首先解决冲突,table_source是否有关系?如果没有,你可以改变这些键:

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

1000,是一个常数,足够大,所以它们在你的桌子结束后去。

答案 4 :(得分:1)

我认为您可以使用如下语法:

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

参考:http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html 希望它有所帮助

答案 5 :(得分:1)

这是我使用'replace insert'命令进行批量更新的最终解决方案。

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;

答案 6 :(得分:0)

INSERT IGNORE只是“绕过”重复的行。

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

答案 7 :(得分:0)

你可以用准备好的陈述来做。

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;

答案 8 :(得分:0)

似乎无法在MySQL Prepared Statement中将列作为占位符给出。我编译了以下测试解决方案:

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;

答案 9 :(得分:0)

您可以使用动态查询:

expandableListDetail

答案 10 :(得分:-1)

最简单的方法是使用phpmyadmin编写列列表,然后根据需要进行更改,在下面的示例中,我想复制id = 1078的行,在此表中我有id唯一的自动增量和别名唯一。因此我创建了我的查询如下,id&别名替换为所需的值。它就像一个魅力。

INSERT INTO sy3_menu选择1079,menutypetitle," alias",notepathlinktypepublishedparent_idlevelcomponent_idchecked_outchecked_out_time,{ {1}},browserNavaccessimgtemplate_style_idparamslftrgt,{{1来自home的{​​{1}},其中id = 1078

或者,要自动增加id,请使用以下Join语句: INSERT INTO language选择* from(SELECT MAX(client_id + 1)来自sy3_menu)a 加入(选择sy3_menuid," sy3_menu",menutypetitlealias,{{1 }},notepathlinktypepublishedparent_idlevelcomponent_id来自{checked_outchecked_out_timebrowserNavaccessimgtemplate_style_idparamslft来自{ {1}}其中id = 1079)b