如何在mysql表中插入许多行并返回新的id?

093gszye  于 2021-06-20  发布在  Mysql
关注(0)|答案(7)|浏览(365)

通常我可以在mysql表中插入一行 last_insert_id 回来。不过,现在我想在表中批量插入许多行,并返回一个id数组。有人知道我怎么做吗?
有一些类似的问题,但它们并不完全相同。我不想在任何临时表中插入新的id;我只想拿回ID的数组。
我可以从批量插入中检索lastinsertid吗?
mysql mulitple row insert select语句,最后一个插入id()

epggiuax

epggiuax1#

旧线程,但只是研究了一下,所以这里是这样的:如果您在mysql的最新版本上使用innodb,您可以使用 LAST_INSERT_ID() 以及 ROW_COUNT() .
innodb保证在执行批量插入时自动递增的序列号 innodb_autoinc_lock_mode 设置为0(传统)或1(连续)。因此,您可以从 LAST_INSERT_ID() 最后加上 ROW_COUNT()-1 .

myzjeezk

myzjeezk2#

我认为您必须要么处理应用程序中的事务id,要么处理应用程序中的项目id,才能完美地完成这项工作。
一种可行的方法是,假设所有插入都成功(!),具体如下:
然后,您可以从lastid(大容量插入的第一个插入id)开始,使用受影响行数的循环来获取插入的id。因此,我检查了它的工作原理。。只是要小心,例如heidisql不会为row\u count()返回正确的值,可能是因为它是一个蹩脚的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\u sqle是对mysqli\u query的直接调用,local\u sqlec是对mysqli\u query+convert resultset to php array的调用):

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—假设使用处理多个结果集/查询的扩展名)。

t5fffqht

t5fffqht3#

我不确定自动递增值是否会将项目增加1。如果您的数据库使用master//master复制并解决自动增量重复排除问题,那么将会有巨大的问题。ai将是+2而不是+1,如果还有一个大师,它将变成+3。所以像自动增量1这样的东西会毁了你的项目。
我只看到一些好的选择。
这个sql代码段在多个主控形状下不会有问题,并且在您只需要插入记录之前会给出很好的结果。在没有事务的多个请求上,可以捕获其他insert记录。

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;

(如果您还需要通过重复密钥更新来更新记录)您将需要稍微重构数据库,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

这两种情况对跨国公司都是安全的。第一个将只显示插入的记录,第二个将显示所有更新的记录。
而且,这些选项将工作,甚至与插入忽略。。。

xzv2uavs

xzv2uavs4#

$query = "INSERT INTO TABLE (ID,NAME,EMAIL) VALUES (NULL,VALUE1, VALUE2)";
$idArray = array();
foreach($array as $key) {
 mysql_query($query);
 array_push($idArray, mysql_insert_id());
}
print_r($idArray);
b4wnujal

b4wnujal5#

这个线程是旧的,但所有这些解决方案没有帮助我,所以我想出了我自己的。
首先,计算要插入的行数
假设我们需要添加5行:

LOCK TABLE tbl WRITE;

SELECT `AUTO_INCREMENT` FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'my_db' AND TABLE_NAME   = 'tbl'

然后使用刚才选择的自动增量执行下一个查询:

ALTER TABLE tbl AUTO_INCREMENT = {AUTO_INCREMENT}+5;
UNLOCK TABLES;

最后做你的插入
使用保留的自动增量范围插入id。
警告:此解决方案需要提升对表的访问级别。但通常批量插入是由cron和importer脚本运行的,而不是那些可能使用特殊访问的脚本。你不会用这个来做一些插入。
如果在重复密钥更新时使用,这可能会留下未使用的id。

e5nqia27

e5nqia276#

我认为唯一可以做到的方法是,为插入的每一组行存储一个唯一标识符(guid),然后选择行id。例如:

INSERT INTO t1
(SELECT col1,col2,col3,'3aee88e2-a981-1027-a396-84f02afe7c70' FROM a_very_large_table);
COMMIT;

SELECT id FROM t1 
WHERE guid='3aee88e2-a981-1027-a396-84f02afe7c70';

您还可以使用在数据库中生成guid uuid()

p4rjhz4m

p4rjhz4m7#

假设我们有一个名为tentable的表,其中有两个coluid,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;

相关问题