我有一个MySQL表,我需要三个列,每个列在表中是唯一的,userName,userEmail和userUID。对于每个列,使用UNIQUE设置该表。为了防止竞争条件,我尝试单个插入新用户,然后选择重复的条目'错误,解析错误消息以确定哪个列出现问题,然后询问用户新信息。我正在尝试调试此代码并放置print_r($dbConn, true)
以捕获INSERT语句的结果,然后再对重复的列名进行任何测试。这打破了很长时间,因为它似乎消灭了mysqli连接对象中的errno
和error
值。这是一个说明问题的简化示例:
<?php
error_reporting(E_ALL);
echo 'PHP Version: ' . phpversion() . PHP_EOL;
$dbConn = @new mysqli('127.0.0.1', 'userX', 'passwordX', 'databaseX');
$dbConn->query('CREATE TABLE IF NOT EXISTS print_r_test (' .
'username VARCHAR(64), UNIQUE (username)');
echo 'Created print_r_test table.' . PHP_EOL;
$dbConn->query('TRUNCATE TABLE print_r_test');
echo 'Truncated print_r_test table.' . PHP_EOL;
$dbConn->query('INSERT INTO print_r_test (username) VALUES (\'testuser\')');
echo '' . 'INSERT#1: ' . $dbConn->errno . ': ' . $dbConn->error . PHP_EOL;
// This next one fails with duplicate entry 'testuser' for 'username'
$dbConn->query('INSERT INTO print_r_test (username) VALUES (\'testuser\')');
// echo '$dbConn: ' . print_r($dbConn, true) . PHP_EOL;
echo '' . 'INSERT#2: ' . $dbConn->errno . ': ' . $dbConn->error . PHP_EOL;
?>
请注意,第14行已注释掉。
如果按原样运行(在更改userX,passwordX和databaseX之后),它按预期工作:
H:>php print_r_test2.php
PHP Version: 5.4.10
Created print_r_test table.
Truncated print_r_test table.
INSERT#1: 0:
INSERT#2: 1062: Duplicate entry 'testuser' for key 'username'
第10行的第一个INSERT工作并报告errno = 0。第二个插入失败,错误为errno = 1-62,并显示一条消息,指示重复的用户名。
现在,删除第14行上的//,以便将$ dbConn内容打印到输出中,然后我得到:
H:>php print_r_test2.php
PHP Version: 5.4.10
Created print_r_test table.
Truncated print_r_test table.
INSERT#1: 0:
$dbConn: mysqli Object
(
[affected_rows] => -1
[client_info] => mysqlnd 5.0.10 - 20111026 - $Id: b0b3b15c693b7f6aeb3aa66b646fee339f175e39 $
[client_version] => 50010
[connect_errno] => 0
[connect_error] =>
[errno] => 1062
[error] => Duplicate entry 'testuser' for key 'username'
[error_list] => Array
(
[0] => Array
(
[errno] => 1062
[sqlstate] => 23000
[error] => Duplicate entry 'testuser' for key 'username'
)
)
[field_count] => 0
[host_info] => 127.0.0.1 via TCP/IP
[info] =>
[insert_id] => 0
[server_info] => 5.6.19
[server_version] => 50619
[stat] => Uptime: 26920 Threads: 2 Questions: 97 Slow queries: 0 Opens: 85 Flush tables: 1 Open tables: 61 Queries per second avg: 0.003
[sqlstate] => 00000
[protocol_version] => 10
[thread_id] => 20
[warning_count] => 0
)
INSERT#2: 0:
第二个INSERT报告0表示确定,但显然失败了。
这里似乎发生的是print_r($dbConn, true)
导致errno
连接对象的error
和$dbConn
属性设置为零。这导致我的代码查找1062错误无法找到它。
如果我将print_r
行注释掉并复制INSERT#2
行,则会打印出1062错误消息两次。
如果我复制了print_r
行,那么我会看到第二行打印出errno -> 0
而error
为空。我注意到的是,第二个显示连接Questions
中的stat
计数已增加1。所以我的想法是print_r
的{{1}}导致对MySQL的另一个查询成功并返回0表示确定并吹掉那里的先前值。
这似乎不是很有帮助,或者我在这里遗失了一些令人目眩的事情?
感谢。
在下面的@ Phil评论中,我的问题是我做错了什么(如果有的话)打破了$dbConn
对象中的errno
和error
回复?< / p>
它与$dbConn
无关。用以下代替最后一行:
print_r
导致输出为:
echo '' . 'INSERT#2: ' . $dbConn->errno . ': ' . $dbConn->error . PHP_EOL . $dbConn->stat . PHP_EOL;
echo '' . 'INSERT#2: ' . $dbConn->errno . ': ' . $dbConn->error . PHP_EOL . $dbConn->stat . PHP_EOL;
这样做:
INSERT#2: 1062: Duplicate entry 'testuser' for key 'username'
Uptime: 29364 Threads: 2 Questions: 136 Slow queries: 0 Opens: 91 Flush tables: 1 Open tables: 61 Queries per second avg: 0.004
INSERT#2: 0:
Uptime: 29364 Threads: 2 Questions: 137 Slow queries: 0 Opens: 91 Flush tables: 1 Open tables: 61 Queries per second avg: 0.004
结果:
echo '' . 'INSERT#2: ' . $dbConn->errno . ': ' . $dbConn->error . PHP_EOL;
echo '' . 'INSERT#2: ' . $dbConn->errno . ': ' . $dbConn->error . PHP_EOL;
如果读取连接对象不是幂等操作,那么这对我来说就像是一个陷阱,也是问题和挫折的根源。所以我的问题是,是否有一些我做错了或遗失的事情,或者这是mysqli的一些奇怪特征?
答案 0 :(得分:3)
如果查看documentation for mysqli->stat()
,它是一个在服务器上执行命令'mysqladmin status'的函数,并返回服务器返回的任何内容。如果您查看the documentation for mysqli->errno
,您会看到它“返回最近函数调用的错误代码”。
那会发生什么?
您执行查询,并阅读错误代码。然后执行另一个未失败的命令,并读取该命令的错误代码。这正是你应该发生的事情。
如果在调用stat()之后需要使用errno或error的值,则在调用stat()之前,没有任何内容阻止您将这些值存储在变量中:
$a = $dbConn->errno;
$b = $dbConn->error;
$c = $dbConn->stat();
echo $a . $b . $c;
答案 1 :(得分:2)
这是一个有趣的问题,我在查看文档后找到答案:http://php.net/manual/en/class.mysqli.php
这些是对象属性:错误,错误。因此,访问它们不会影响对象的状态。
另一方面,stat()是对象的方法调用。这意味着将更新errno和错误以反映该调用是成功还是失败。