通常,我可以在MySQL表中插入一行并last_insert_id
取回。现在,尽管如此,我想将许多行批量插入表中并获取ID数组。有人知道我该怎么做吗?
有一些类似的问题,但并不完全相同。我不想将新ID插入任何临时表;我只想找回ID数组。
通常,我可以在MySQL表中插入一行并last_insert_id
取回。现在,尽管如此,我想将许多行批量插入表中并获取ID数组。有人知道我该怎么做吗?
有一些类似的问题,但并不完全相同。我不想将新ID插入任何临时表;我只想找回ID数组。
OUTPUT
子句。我相信你可以在MySQL触发做到这一点
Answers:
旧线程,但只是研究了一下,所以去了:如果您在MySQL的最新版本上使用InnoDB,则可以使用LAST_INSERT_ID()
和获得ID列表ROW_COUNT()
。
如果innodb_autoinc_lock_mode
设置为0(传统)或1(连续),InnoDB保证批量插入时自动递增的序号。因此,您可以添加添加第一个IDLAST_INSERT_ID()
和最后一个ID ROW_COUNT()-1
。
假设我们有一个名为temptable的表,其中有两个cols uid,col1,其中uid是一个自动递增字段。进行如下操作将返回结果集中所有插入的ID。您可以遍历结果集并获取ID。我意识到这是一个过时的帖子,并且此解决方案可能不适用于每种情况。但是对于其他人而言,这也许就是原因,所以我要回复它。
# lock the table
lock tables temptable write;
#bulk insert the rows;
insert into temptable(col1) values(1),(2),(3),(4);
#get the value of first inserted row. when bulk inserting last_insert_id() #should give the value of first inserted row from bulk op.
set @first_id = last_insert_id();
#now select the auto increment field whose value is greater than equal to #the first row. Remember since you have write lock on that table other #sessions can't write to it. This resultset should have all the inserted #id's
select uid from temptable where uid >=@first_id;
#now that you are done don't forget to unlock the table.
unlock tables;
我认为您将必须处理应用程序中的交易ID或应用程序中的项目ID,才能做到这一点。
假设您所有插入均成功(!),一种可行的方法如下:
然后,您可以使用循环获取受影响的行数的插入的ID,以循环数(从lastid(批量插入的第一个插入的ID)开始)开始。因此,我检查了它是否工作正常。.请注意,例如HeidiSQL不会为ROW_COUNT()返回正确的值,可能是因为它是一个cr脚的GUI,在执行随机操作时我们不要求这样做-但是从任何一个角度来看都是完全正确的命令行或PHP mysqli-
START TRANSACTION;
BEGIN;
INSERT into test (b) VALUES ('1'),('2'),('3');
SELECT LAST_INSERT_ID() AS lastid,ROW_COUNT() AS rowcount;
COMMIT;
在PHP中看起来像这样(local_sqle是对mysqli_query的直接调用,local_sqlec是对mysqli_query的调用+将结果集转换为PHP数组):
local_sqle("START TRANSACTION;
BEGIN;
INSERT into test (b) VALUES ('1'),('2'),('3');");
$r=local_sqlec("SELECT LAST_INSERT_ID() AS lastid,ROW_COUNT() AS rowcount;");
local_sqle("
COMMIT;");
$i=0;
echo "last id =".($r[0]['lastid'])."<br>";
echo "Row count =".($r[0]['rowcount'])."<br>";
while($i<$r[0]['rowcount']){
echo "inserted id =".($r[0]['lastid']+$i)."<br>";
$i++;
}
查询分开的原因是因为我无法使用我自己的函数来获得结果,如果您使用标准函数来执行此操作,则可以将其放回一个语句中,然后检索所需的结果(应该是结果编号2-假设您使用的扩展程序可以处理多个结果集/查询。
我不确定自动递增值将使项目增加1。如果您的数据库具有Master // Master复制并解决auto_increment重复排除项,将会出现很大的问题。AI将是+2而不是+1,而且如果还会有一个大师,它将变为+3。所以像AUTO_INCREMENT之类的东西接力1将杀死您的项目。
我只看到一些不错的选择。
该SQL代码段在使用多个主数据库时不会有任何问题,并且在只需要插入记录之前就可以提供良好的结果。在没有事务的情况下处理多个请求可以捕获其他插入记录。
START TRANSACTION;
SELECT max(id) into @maxLastId FROM `main_table`;
INSERT INTO `main_table` (`value`) VALUES ('first'), ('second') ON DUPLICATE KEY UPDATE `value` = VALUES(`value`);
SELECT `id` FROM `main_table` WHERE id > @maxLastId OR @maxLastId IS NULL;
COMMIT;
(如果您还需要通过DUPLICATE KEY UPDATE来更新记录),则需要稍微重构数据库,SQL看起来将类似于下一个(对于事务是安全的,并且在一个连接中没有事务。)
#START TRANSACTION
INSERT INTO bulk_inserts VALUES (null);
SET @blukTransactionId = LAST_INSERT_ID();
SELECT @blukTransactionId, LAST_INSERT_ID();
INSERT INTO `main_table` (`value`, `transaction_id`) VALUES ('first', @blukTransactionId), ('second', @blukTransactionId) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`), `transaction_id` = VALUES(`transaction_id`);
SELECT @blukTransactionId, LAST_INSERT_ID();
SELECT id FROM `main_table` WHERE `transaction_id` = @blukTransactionId;
#COMMIT
两种情况都可以跨国。第一个将只显示您插入的记录,第二个将显示所有记录,甚至已更新。
这些选项即使在INSERT IGNORE下也可以使用...
这个线程很旧,但是所有这些解决方案都没有帮助我,所以我想出了自己的方法。
首先,计算要插入的行数
假设我们需要添加5行:
LOCK TABLE tbl WRITE;
SELECT `AUTO_INCREMENT` FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'my_db' AND TABLE_NAME = 'tbl'
然后使用刚刚选择的auto_increment进行下一个查询:
ALTER TABLE tbl AUTO_INCREMENT = {AUTO_INCREMENT}+5;
UNLOCK TABLES;
最后插入
使用保留的自动增量范围插入ID。
警告:此解决方案需要提升对表的访问级别。但是通常,批量插入是由crons和importer脚本运行的,否则,它们可能仍会使用特殊的访问权限。您不会仅将其用于少量插入。
如果使用ON DUPLICATE KEY UPDATE,这可能会留下未使用的ID。