mysql_insert_id() 用于 INSERT...SELECT 语句
mysql_insert_id() for INSERT...SELECT statement
我正在进行类似的 INSERT...SELECT 查询
INSERT INTO table (value1, value2)
SELECT 'stuff for value1', 'stuff for value2' FROM DUAL
WHERE NOT EXISTS (SELECT * FROM table
WHERE value1='stuff for value1' AND value2='stuff for value2')
LIMIT 1
,其中 table 具有自动生成的 ID。
当然,我想知道它是否已插入。我假设这样做的方法是使用 mysql_insert_id()
。它 return 如果没有插入发生则为 0,如果插入发生则为 1。查看更多详细信息 here.
If an INSERT ... SELECT statement is executed, and NO automatically
generated value is successfully inserted, mysql_insert_id() RETURNS
the ID of the last inserted row.
如果没有成功插入自动生成的 ID,return 会怎样?这是文档拼写错误吗?
更新1
到目前为止,我在 C 中进行了测试并且 mysql_insert_id()
return 如果插入没有发生,即使最后一次插入成功并且 mysql_insert_id()
returned 不- 零结果。上面提到的同一手册中的一段通过以下内容确认了此行为:
mysql_insert_id() returns 0 if the previous statement does not use an AUTO_INCREMENT value. ....
The value of mysql_insert_id() is affected only by statements issued within the current client connection. It is not affected by statements issued by other clients.
The LAST_INSERT_ID() SQL function will contain the value of the first automatically generated value that was successfully inserted. LAST_INSERT_ID() is not reset between statements because the value of that function is maintained in the server. ....
这感觉有点合乎逻辑,否则 INSERT...SELECT
在许多情况下将毫无用处,如果您无法在代码中知道您的插入是否有效。但这与上面的说法完全矛盾。有人有这方面的经验吗?
更新2
来自 MariaDB 手册,还建议在未发生插入的情况下该值应为零:
The mysql_insert_id() function returns the ID generated by a query on
a table with a column having the AUTO_INCREMENT attribute or the value
for the last usage of LAST_INSERT_ID(expr). If the last query wasn't
an INSERT or UPDATE statement or if the modified table does not have a
column with the AUTO_INCREMENT attribute and LAST_INSERT_ID was not
used, this function will return zero.
看起来它将 return 上次自动生成的 ID:
MariaDB [Whosebug]> desc a;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| a | varchar(20) | YES | | NULL | |
| b | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
MariaDB [Whosebug]> insert into a(a,b) values('haha', 'haha');
Query OK, 1 row affected (0.03 sec)
MariaDB [Whosebug]> select LAST_INSERT_ID() from dual;
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 1 |
+------------------+
MariaDB [Whosebug]> insert into a(a,b) select 'hi', 'hello' from dual;
Query OK, 1 row affected (0.01 sec)
Records: 1 Duplicates: 0 Warnings: 0
MariaDB [Whosebug]> select LAST_INSERT_ID() from dual;
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 2 |
+------------------+
1 row in set (0.00 sec)
MariaDB [Whosebug]> insert into a(a,b) select 'hi', 'hello' from dual where not exists (select * from a where a='hi' and b='hello') limit 1;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [Whosebug]> select LAST_INSERT_ID() from dual;
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 2 |
+------------------+
1 row in set (0.00 sec)
措辞可以更清楚,但它的意思是,如果你的 INSERT 导致错误,mysql_insert_id()(或 SQL 函数 last_insert_id()
)继续报告无论它根据之前的成功 INSERT.
做了什么
这是一个演示:
mysql> create table foo( id int auto_increment primary key);
mysql> create table bar( id int primary key);
mysql> insert into bar (id) values (1), (2), (10);
mysql> insert into foo select id from bar;
mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 0 |
+------------------+
没有生成新的 auto-inc 值,因为我的 INSERT 给出了要插入的特定值。
让我们生成一些新值:
mysql> insert into foo select null from bar;
Query OK, 3 rows affected (0.02 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 11 |
+------------------+
这是预期的,因为 last_insert_id() 将报告批量插入生成的 first id。您必须计算出插入了多少行,这样您才能知道其余的 id。这样生成的id保证唯一且连续。
现在让我们尝试插入一些重复项,这会导致错误:
mysql> insert into foo select id from bar;
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
现在是文档中句子的重点:last_insert_id() 报告的内容没有变化。
mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 11 |
+------------------+
同样,即使插入成功,但不会导致生成任何新的自动增量值,last_insert_id() 报告的内容也没有变化。
mysql> insert into foo select id+20 from bar;
Query OK, 3 rows affected (0.02 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 11 |
+------------------+
许多人假设 last_insert_id() 报告了最近插入的主键值,但事实并非如此。它仅报告由 auto-inc 功能自动生成的值。
mysql_affected_rows 是你的朋友。如果您成功插入行,它将大于 0(除非它 returns (my_ulonglong)-1,表示失败)。在你的情况下,因为你最多插入 1 行,你只需要检查它是否返回 1.
我正在进行类似的 INSERT...SELECT 查询
INSERT INTO table (value1, value2)
SELECT 'stuff for value1', 'stuff for value2' FROM DUAL
WHERE NOT EXISTS (SELECT * FROM table
WHERE value1='stuff for value1' AND value2='stuff for value2')
LIMIT 1
,其中 table 具有自动生成的 ID。
当然,我想知道它是否已插入。我假设这样做的方法是使用 mysql_insert_id()
。它 return 如果没有插入发生则为 0,如果插入发生则为 1。查看更多详细信息 here.
If an INSERT ... SELECT statement is executed, and NO automatically generated value is successfully inserted, mysql_insert_id() RETURNS the ID of the last inserted row.
如果没有成功插入自动生成的 ID,return 会怎样?这是文档拼写错误吗?
更新1
到目前为止,我在 C 中进行了测试并且 mysql_insert_id()
return 如果插入没有发生,即使最后一次插入成功并且 mysql_insert_id()
returned 不- 零结果。上面提到的同一手册中的一段通过以下内容确认了此行为:
mysql_insert_id() returns 0 if the previous statement does not use an AUTO_INCREMENT value. ....
The value of mysql_insert_id() is affected only by statements issued within the current client connection. It is not affected by statements issued by other clients.
The LAST_INSERT_ID() SQL function will contain the value of the first automatically generated value that was successfully inserted. LAST_INSERT_ID() is not reset between statements because the value of that function is maintained in the server. ....
这感觉有点合乎逻辑,否则 INSERT...SELECT
在许多情况下将毫无用处,如果您无法在代码中知道您的插入是否有效。但这与上面的说法完全矛盾。有人有这方面的经验吗?
更新2
来自 MariaDB 手册,还建议在未发生插入的情况下该值应为零:
The mysql_insert_id() function returns the ID generated by a query on a table with a column having the AUTO_INCREMENT attribute or the value for the last usage of LAST_INSERT_ID(expr). If the last query wasn't an INSERT or UPDATE statement or if the modified table does not have a column with the AUTO_INCREMENT attribute and LAST_INSERT_ID was not used, this function will return zero.
看起来它将 return 上次自动生成的 ID:
MariaDB [Whosebug]> desc a;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| a | varchar(20) | YES | | NULL | |
| b | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
MariaDB [Whosebug]> insert into a(a,b) values('haha', 'haha');
Query OK, 1 row affected (0.03 sec)
MariaDB [Whosebug]> select LAST_INSERT_ID() from dual;
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 1 |
+------------------+
MariaDB [Whosebug]> insert into a(a,b) select 'hi', 'hello' from dual;
Query OK, 1 row affected (0.01 sec)
Records: 1 Duplicates: 0 Warnings: 0
MariaDB [Whosebug]> select LAST_INSERT_ID() from dual;
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 2 |
+------------------+
1 row in set (0.00 sec)
MariaDB [Whosebug]> insert into a(a,b) select 'hi', 'hello' from dual where not exists (select * from a where a='hi' and b='hello') limit 1;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [Whosebug]> select LAST_INSERT_ID() from dual;
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 2 |
+------------------+
1 row in set (0.00 sec)
措辞可以更清楚,但它的意思是,如果你的 INSERT 导致错误,mysql_insert_id()(或 SQL 函数 last_insert_id()
)继续报告无论它根据之前的成功 INSERT.
这是一个演示:
mysql> create table foo( id int auto_increment primary key);
mysql> create table bar( id int primary key);
mysql> insert into bar (id) values (1), (2), (10);
mysql> insert into foo select id from bar;
mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 0 |
+------------------+
没有生成新的 auto-inc 值,因为我的 INSERT 给出了要插入的特定值。
让我们生成一些新值:
mysql> insert into foo select null from bar;
Query OK, 3 rows affected (0.02 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 11 |
+------------------+
这是预期的,因为 last_insert_id() 将报告批量插入生成的 first id。您必须计算出插入了多少行,这样您才能知道其余的 id。这样生成的id保证唯一且连续。
现在让我们尝试插入一些重复项,这会导致错误:
mysql> insert into foo select id from bar;
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
现在是文档中句子的重点:last_insert_id() 报告的内容没有变化。
mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 11 |
+------------------+
同样,即使插入成功,但不会导致生成任何新的自动增量值,last_insert_id() 报告的内容也没有变化。
mysql> insert into foo select id+20 from bar;
Query OK, 3 rows affected (0.02 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 11 |
+------------------+
许多人假设 last_insert_id() 报告了最近插入的主键值,但事实并非如此。它仅报告由 auto-inc 功能自动生成的值。
mysql_affected_rows 是你的朋友。如果您成功插入行,它将大于 0(除非它 returns (my_ulonglong)-1,表示失败)。在你的情况下,因为你最多插入 1 行,你只需要检查它是否返回 1.