我正在对此进行类似的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()
。如果没有插入则返回0,如果插入发生则返回1。查看更多详情here。
如果执行INSERT ... SELECT语句,则自动执行 NO 生成的值已成功插入,mysql_insert_id() RETURNS 最后插入的行的ID。
如果没有成功插入自动生成的ID,它会返回什么?这是一个文字错字吗?
UPDATE1
到目前为止,我在C中进行了测试,如果即使最后一次插入成功并且mysql_insert_id()
返回非零结果也未发生插入,mysql_insert_id()
返回始终为0。上面提到的同一手册中的段落通过说:
如果前一个语句不使用AUTO_INCREMENT值,则mysp_insert_id()返回0。 ....mysql_insert_id()的值仅受当前客户端连接中发出的语句的影响。它不受其他客户发布的声明的影响。
LAST_INSERT_ID()SQL函数将包含第一个自动生成的值,该值已成功插入。 LAST_INSERT_ID()不会在语句之间重置,因为该函数的值在服务器中维护。 ....
这种感觉有点合乎逻辑,否则INSERT...SELECT
在许多情况下会无用,如果您在代码中无法知道您的插入是否有效。但这完全与上述说法相矛盾。有人有过这方面的经验吗?
UPDATE2
从MariaDB手册中,还建议在未插入的情况下该值应为零:
mysql_insert_id()函数返回查询生成的ID 包含具有AUTO_INCREMENT属性或值的列的表 最后一次使用LAST_INSERT_ID(expr)。如果最后一个查询不是 INSERT或UPDATE语句或修改后的表没有 具有AUTO_INCREMENT属性和LAST_INSERT_ID的列不是 使用后,此函数将返回零。
答案 0 :(得分:3)
措辞可能更清楚,但它意味着如果你的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()将报告批量插入生成的第一个 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 |
+------------------+
同样,即使INSERT成功,但不会导致生成任何新的auto-inc值,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功能自动生成的值。
答案 1 :(得分:2)
mysql_affected_rows是你的朋友。如果成功插入行,则大于0(除非它返回(my_ulonglong)-1,表示失败)。在您的情况下,由于您最多插入1行,您只需要检查它是否返回1.
答案 2 :(得分:1)
看起来它会返回上次自动生成的ID:
MariaDB [stackoverflow]> 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 [stackoverflow]> insert into a(a,b) values('haha', 'haha');
Query OK, 1 row affected (0.03 sec)
MariaDB [stackoverflow]> select LAST_INSERT_ID() from dual;
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 1 |
+------------------+
MariaDB [stackoverflow]> 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 [stackoverflow]> select LAST_INSERT_ID() from dual;
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 2 |
+------------------+
1 row in set (0.00 sec)
MariaDB [stackoverflow]> 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 [stackoverflow]> select LAST_INSERT_ID() from dual;
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 2 |
+------------------+
1 row in set (0.00 sec)