如果数据库中没有相同的电子邮件用户,我只想插入新用户。
我正在阅读这篇文章:MySQL - ignore insert error: duplicate entry但问题是在执行sql
语句后,我不知道新用户是否成功插入。
答案 0 :(得分:4)
执行sql语句后,我不知道是不是 成功与否
如果我理解正确,您想知道在使用INSERT IGNORE
后是否发生了插入。执行查询后调用LAST_INSERT_ID()
,如果返回0,则表示未插入行。
https://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id
如果使用INSERT IGNORE并忽略该行,则为AUTO_INCREMENT 计数器没有递增,LAST_INSERT_ID()返回0,这 反映没有插入行。
<强>测试强>
mysql> insert ignore into example (`id`, `data`) VALUES (2,'hello');
Query OK, 1 row affected (0.04 sec)
mysql> insert ignore into example (`id`, `data`) VALUES (3,'hello');
Query OK, 1 row affected (0.06 sec)
mysql> insert ignore into example (`id`, `data`) VALUES (2,'hello');
Query OK, 0 rows affected (0.00 sec)
mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 0 |
+------------------+
1 row in set (0.00 sec)
警告强>
某些版本的MySQL存在last_insert_id()
无法与INSERT IGNORE
正常工作的错误:http://bugs.mysql.com/bug.php?id=67535
答案 1 :(得分:2)
只需进行常规插入,然后检查错误代码:
$result = mysql_query("INSERT ... stuff that causes duplicate key error");
if (mysql_errno() == 1022) {
... account already exists ...
}
这比先选择“选择”以查看电子邮件是否存在,然后插入(如果不存在)更安全。另一个并行请求可能会从您的下方“窃取”该帐户。
这里记录了mysql错误代码:http://dev.mysql.com/doc/refman/5.0/en/error-messages-server.html
评论后续:
在某些情况下,我的回答可能更可靠,例如考虑一下:
mysql> create table foo (x int primary key auto_increment, y text);
Query OK, 0 rows affected (0.00 sec)
mysql> insert into foo (y) values ('bar1'); // id #1
Query OK, 1 row affected (0.00 sec)
mysql> insert into foo (y) values ('bar2'); // id #2
Query OK, 1 row affected (0.00 sec)
mysql> insert into foo (x,y) values (2, 'bar2'); // try to create a dupe id #2
ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY'
mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 2 |
+------------------+
1 row in set (0.00 sec)
注意你仍然得到一个last_insert_id()。那是因为它始终是最后 SUCCESSFUL 插入的值。由于插入失败,该值不会重置。
如果您使用数据库句柄进行多次插入,并尝试使用if last_insert_id == 0
技巧,那么您可能会得到一个错误的答案,因为您将获得一些成功的OTHER插入的ID,不是那个刚失败的人。
请注意insert ignore
也无济于事:
mysql> insert ignore into foo (x,y) values (1, 'bar1'); // create dupe id #1
Query OK, 0 rows affected (0.00 sec)
mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 2 |
+------------------+
1 row in set (0.00 sec)
答案 2 :(得分:1)
如果你使用 PDO ,那很简单:
try{
// INSERT new account
}
catch(PDOException $ex){ /* already exist -> errorInfo */ }
如果你有:
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
全部
<强>加入:强>
以防正确理解 - see comment :
任何DB-Layer,例如:
class TableExample
{
...
// sample with inner logic
public function createUser(...)
{
...
$this->db->query("INSERT INTO ...");
...
}
// sample with the AR etc.
public function updateFooBar(...)
{
...
$user->name = 'name';
$user->email = 'email';
$user->save();
...
}
}
某些X层:
class ModelStuff
{
....
public function foo()
{
try{
$this->example->createUser();
...
$this->example->updateFooBar();
...
}
catch(PDOException $ex){
// TODO: e.g. ($ex->getCode() == 23000)? ...
// all PDOException with TableExample catched here
}
}
}
等
编译了我的所有评论:
$ex->getCode();
// SQLSTATE - 23000,这是因为重复键错误而发生的$ex->errorInfo[1]
- 其中1是Driver specific error code