mysql多行INSERT语法,其中一个占位符实际上是一个常量

时间:2019-02-17 12:10:19

标签: mysql bulkinsert

我正在使用mysql multiple-row INSERT syntax将大约3000条记录插入到mysql表中。为了简短的示例,此表只有两列。实际的表当然有更多的列,其中有有意义的索引...

mysql> INSERT INTO table (A, B) VALUES 
("constant", 1), 
("constant", 2),
("constant", 3);

您可能会注意到 A栏始终是相同的值。

这使我想到了一个实际的问题:是否有办法将 COLUMN A 定义为sql插入语句中的常量,如以下 pseudo code 中所述: / p>

mysql> INSERT INTO table (A="constant", B) VALUES 
(1), 
(2),
(3);

准备好的声明...

现在,这更加具体了。一些实际的perl代码:

#!/usr/bin/perl -W

use strict;
use warnings;
use DBI;

my $dbh = DBI->connect( 'lalalala' );
my $sth = $dbh->prepare( q|INSERT INTO table (A, B) VALUES ("constant",?)| );

foreach my $increment (1 .. 100000){

  $sth->execute( $increment );
}

... 

认为这是我想要的吗?不,很遗憾,不是。如前所述,我是通过TCP / IP与mysql对话。上面的代码实际上是在执行

INSERT INTO table (A, B) VALUES ("constant", 1);
INSERT INTO table (A, B) VALUES ("constant", 2);
etc ...

单个sql查询中的每个单个。现在,更不用说查询时间了,假设5ms的往返时间为网络开销。在上面的示例中,仅五秒钟。现在...我编写了一个函数来解决这个混乱,并创建了一个紧凑的查询,就像您在此问题的顶部看到的那样。现在,将一个简短的字符串想象成一个具有一百万次插入的查询。好吧。像个魅力。但是,通过省略VALUE A可以节省大约50%的流量,因为它实际上是一个不变的值,永远不变。

  

后圣经》

     

如果您想知道为什么,我会问这个,这是怎么回事?归结为一件事:总结   beeing的字符串(在我的情况下是通过网络发送到)的   然后,当一半的   信息是多余的...恕我直言。如果有   另一种方式-很好。如果不是的话,我会像以前那样……   “对我不舒服”的感觉

1 个答案:

答案 0 :(得分:1)

  

mysql>插入表(A =“ constant”,B)值

不,MySQL中没有这样的语法。这是MySQL中INSERT的语法参考页:https://dev.mysql.com/doc/refman/8.0/en/insert.html

如果要使用多行INSERT,则必须为每个行中的元组中的每一列提供一个表达式。表达式可以是每行相同的常量,如您的原始示例中所示:

mysql> INSERT INTO table (A, B) VALUES 
  ("constant", 1), 
  ("constant", 2),
  ("constant", 3);

或者它可以是一个会话变量(如上文@wchiquito所述)。

mysql> SET @c = 'constant';
mysql> INSERT INTO table (A, B) VALUES 
  (@c, 1), 
  (@c, 2),
  (@c, 3);

或者您可以将这些值加载到临时表中,然后将它们复制到最终表中(由上面的Mauricio Javier Biott注释):

mysql> CREATE TEMPORARY TABLE temptable (B INT);
mysql> INSERT INTO temptable (A, B) VALUES 
  (1), 
  (2),
  (3);
mysql> INSERT INTO table (A, B) 
  SELECT 'constant', B FROM temptable;

这是另一种解决方案。假设data.txt仅包含您需要为每行提供不同值的字段,则可以使用LOAD DATA LOCAL INFILE,并在最终的SET子句中设置不变列。

mysql> LOAD DATA LOCAL INFILE 'data.txt' 
  INTO TABLE mytable (B) 
  SET A = 'constant';

您在问题中再次发表了自己的看法:

  

...假定往返时间为5毫秒作为网络开销。

我认为这是一个不可能的假设。我刚刚测量了我的应用程序在数据中心中的网络延迟,它比您的建议小36至50倍。

64 bytes from (10.4.12.100): icmp_seq=1 ttl=64 time=0.112 ms
64 bytes from (10.4.12.100): icmp_seq=2 ttl=64 time=0.138 ms
64 bytes from (10.4.12.100): icmp_seq=3 ttl=64 time=0.103 ms
64 bytes from (10.4.12.100): icmp_seq=4 ttl=64 time=0.108 ms
...

大约是每个往返毫秒的十分之一,而不是5毫秒。

执行一条准备好的语句3000次的网络等待时间最多为414毫秒,而不是3000 * 5ms = 15秒。如果网络延迟使您的任务产生了无法接受的开销,则需要改善网络。

最后,您可能想看看我为演示文稿所做的基准测试Load Data Fast!,我将单行INSERT与多行INSERT与LOAD DATA进行了比较。