在MySQL中插入多行数据

349

如果我一次性插入多行数据,数据库查询会更快吗?

例如:

INSERT....

UNION

INSERT....

UNION

(我需要插入大约 2-3000 行)


8
UNION 用于选择操作。 - Jacob
1
行是怎么来的?你是直接在MySQL查询浏览器上编写SQL,还是从PHP、C#或其他什么地方使用?如果你属于后者,请查看以下链接:插入100k条记录的最快方法 多行快速插入 - RKh
优化MySQL查询 - 多行快速插入 - Pavel Shkleinik
5个回答

1420

INSERT语句使用VALUES语法可以插入多行。为此,请包含多个列值列表,每个列表都在括号内,并由逗号分隔。

示例:


请保留HTML标记。
INSERT INTO tbl_name
    (a,b,c)
VALUES
    (1,2,3),
    (4,5,6),
    (7,8,9);


@RPK。我同意你的观点,但我不知道她的数据源是什么。正如我之前所写的那样,如果她有一个文件,我会像cularis建议的那样使用load data语法。 :) - Nicola Cossu
也可以使用INSERT INTO Table SELECT 1, '14/05/2012', 3 UNION SELECT 2, '05/14/2012', 3。当然,如果插入的值来自不同的表,则这种方法会更好。 - Zohar Peled
105
有时候我会忘记一些简单的语法,这个有用的参考资料可以帮到我。 - Captain Hypertext
4
不,它们是要按照相同顺序插入值的表格列名。 - BeetleJuice
不要忘记索引,特别是在大表上,它们对于快速更新至关重要。相比创建非常复杂的代码或插入语句,可能更加明智。 - sastorsl
显示剩余3条评论

64
如果您的数据在文本文件中,可以使用LOAD DATA INFILE

从文本文件加载表格时,请使用LOAD DATA INFILE。这通常比使用INSERT语句快20倍。

优化INSERT语句

您可以在上面的链接中找到更多关于如何加速INSERT语句的技巧。


3
重复记录怎么办? - Matteo
2
@Matteo 根据您定义的模式,数据库将插入或拒绝重复数据。 - ankush981
使用MySQL多查询功能 - Francisco Yepes Barrera
1
第二个链接 404。 - dimir
1
损坏的链接“插入语句的速度”现在已经包含在以下内容中:优化INSERT语句 - Kenneth M. Kolano
@Matteo 如果你将一个字段设置为唯一的,那么在插入语句中使用 Insert IGNORE 可以避免因重复记录而导致插入失败。这样可以跳过重复的记录。 - user3649739

34

只需使用SELECT语句获取所选列的多行值,并一次性将这些值放入另一个表的列中。例如,表“test_a”的列“size”和“price”会填充到表“test_b”和“test_c”的相应列“size”和“price”中。

BEGIN;
INSERT INTO test_b (size, price)
  SELECT size, price
  FROM   test_a;
INSERT INTO test_c (size, price) 
  SELECT size, price
  FROM   test_a;
COMMIT;

代码被嵌入在 BEGINCOMMIT 中,只有当这两个语句都正常工作时才会运行它,否则到该点为止的整个运行将被撤销。


3
值得更多点赞,使用这个方法可以批量插入从其他表中检索到的数据。 - Novastorm
7
要是这段代码中所发生的事情能够有个解释就好了,因为我需要“批量插入从其他表检索出的数据”…… - Aleister Tanek Javas Mraz

-1

这里提供了一个适用于n:m(多对多关系)表的PHP解决方案:

// get data
$table_1 = get_table_1_rows();
$table_2_fk_id = 123;

// prepare first part of the query (before values)
$query = "INSERT INTO `table` (
   `table_1_fk_id`,
   `table_2_fk_id`,
   `insert_date`
) VALUES ";

//loop the table 1 to get all foreign keys and put it in array
foreach($table_1 as $row) {
    $query_values[] = "(".$row["table_1_pk_id"].", $table_2_fk_id, NOW())";
}

// Implode the query values array with a coma and execute the query.
$db->query($query . implode(',',$query_values));

编辑:在@john的评论后,我决定用更高效的解决方案来增强这个答案:

  • 将查询分成多个较小的查询
  • 使用rtrim()删除最后一个逗号而不是implod()
// limit of query size (lines inserted per query)
$query_values  = "";
$limit         = 100;
$table_1       = get_table_1_rows();
$table_2_fk_id = 123;

$query = "INSERT INTO `table` (
   `table_1_fk_id`,
   `table_2_fk_id`,
   `insert_date`
) VALUES ";

foreach($table_1 as $row) {
    $query_values .= "(".$row["table_1_pk_id"].", $table_2_fk_id, NOW()),";
    
    // entire table parsed or lines limit reached :
    // -> execute and purge query_values
    if($i === array_key_last($table_1) 
    || fmod(++$i / $limit) == 0) {
        $db->query($query . rtrim($query_values, ','));
        $query_values = "";
    }
}

1
使用implode()确实可以避免“最后一个字符”问题,但它会创建巨大的内存开销。她要求3000行,假设每行有1kb的数据,那么原始数据就已经达到了3MB。数组将占用30MB的内存,而她已经从$table_1中消耗了另外30MB,因此脚本将使用60MB的内存。只是说一下,否则这是一个不错的解决方案。 - John
1
这对我的情况非常有用。 - Bilal Şimşek

-16
// db table name / blog_post / menu /  site_title
// Insert into Table (column names separated with comma)
$sql = "INSERT INTO product_cate (site_title, sub_title) 
  VALUES ('$site_title', '$sub_title')";

// db table name / blog_post / menu /  site_title
// Insert into Table (column names separated with comma)
$sql = "INSERT INTO menu (menu_title, sub_menu)
  VALUES ('$menu_title', '$sub_menu', )";

// db table name / blog_post /  menu /  site_title
// Insert into Table (column names separated with comma)
$sql = "INSERT INTO blog_post (post_title, post_des, post_img)
  VALUES ('$post_title ', '$post_des', '$post_img')";

4
除了这个回应让人感到困惑之外,假设你正在使用 PHP,你也可能容易受到 SQL 注入攻击的威胁。 - ultrafez
4
  1. 你的SQL代码中有一个bug。
  2. 下一个$sql的值将替换之前的$sql的值。
- Marwan Salim
1
给未来的读者一个小提示,这是一个非常容易犯的错误,特别是对于新手来说。永远不要将原始字符串插入到 SQL 查询中,因为我们网站的用户可以使用一种相当恶劣的攻击方式来调用随机查询。更多信息请参见 https://owasp.org/www-community/attacks/SQL_Injection大多数库都会有一个过滤函数,将变量编辑成安全形式,以避免出现问题并转义引号。 - aqm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接