PHP 更改 PDO 设置后重置自动增量功能不再起作用
PHP reset auto increment function no longer working after changing PDO settings
我有一个使用 PDO 连接到 MySQL 数据库的网站,我正在努力提高其安全性。
阅读this post后,我添加了行$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
,所以连接线现在是这样的:
$this->conn = new PDO("mysql:host=localhost;dbname=dbname;charset=utf8mb4", "user", "pass");
$this->conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
此更改后,网站的 PHP 功能似乎运行良好,但以下功能除外:
function resetidserials($table,$id){
$sql = "SET @num := 0;
UPDATE ".$table." SET ".$id." = @num := (@num+1);
ALTER TABLE ".$table." AUTO_INCREMENT = 1;";
$smt = $this->conn->prepare($sql);
$smt->execute();
}
此函数用于在删除行时重置自动递增的ID号。当行 $this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
不存在时,它按预期工作,当它存在时,我得到一个语法错误。为什么它不起作用,我怎样才能让它与现有的线路一起工作?提前致谢
MySQL的prepare()
不支持多查询。使用 prepare 时,不能 运行 多个语句以分号分隔。
参考:https://dev.mysql.com/doc/refman/8.0/en/sql-prepared-statements.html
SQL syntax for prepared statements does not support multi-statements (that is, multiple statements within a single string separated by ; characters).
如果您将 PDO::ATTR_EMULATE_PREPARES 设置为 false(我同意这是一件好事),那么您必须 运行 每个语句单独。
在你的情况下你不需要使用 prepare()
& execute()
,因为你的查询没有参数而且你只使用它一次。
但是无论如何都没有充分的理由使用多查询,无论您是使用准备还是直接执行查询。一次 运行 个查询更简单。由于这些 SQL 语句中的 none 有一个结果集,您可以使用 PDO::exec().
下面是我的编码方式:
function resetidserials($table,$id){
$sql = "SET @num = 0";
$this->conn->exec($sql);
$sql = "UPDATE `$table` SET `$id` = @num := (@num+1)";
$this->conn->exec($sql);
$sql = "ALTER TABLE `$table` AUTO_INCREMENT = 1";
$this->conn->exec($sql);
}
请注意,我使用了反引号来保护您,以防 table 名称或 id 列名称需要它们。我还使用 PHP variable interpolation syntax 而不是 .
的字符串连接。我相信 98% 的 PHP 的 .
的使用都会降低代码的可读性。
不过,我必须评论,在 table 中重新编号自动增量 ID 的整个想法并不是一个好主意。自增id不是行号。这些值必须是唯一的,不一定是连续的。
您不需要在删除行后重新设置自动递增的id。这可能经常发生,您不应该在每次删除后对整个 table 重新编号。如果 table 有 1 亿行怎么办?如果删除的行是 table 中的最后一行怎么办?
此外,除了删除之外,还有其他原因可能会导致 ID 序列出现空缺。如果 INSERT 被回滚怎么办?如果 INSERT 导致冲突,然后后续 INSERT 使用下一个更高的 id 值怎么办?如果自动递增机制在分配下一个 id 值时跳过一个值怎么办(这确实会发生)?
还有一条评论:不鼓励在 MySQL 中使用 :=
。原因见https://dev.mysql.com/doc/refman/8.0/en/user-variables.html。
我有一个使用 PDO 连接到 MySQL 数据库的网站,我正在努力提高其安全性。
阅读this post后,我添加了行$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
,所以连接线现在是这样的:
$this->conn = new PDO("mysql:host=localhost;dbname=dbname;charset=utf8mb4", "user", "pass");
$this->conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
此更改后,网站的 PHP 功能似乎运行良好,但以下功能除外:
function resetidserials($table,$id){
$sql = "SET @num := 0;
UPDATE ".$table." SET ".$id." = @num := (@num+1);
ALTER TABLE ".$table." AUTO_INCREMENT = 1;";
$smt = $this->conn->prepare($sql);
$smt->execute();
}
此函数用于在删除行时重置自动递增的ID号。当行 $this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
不存在时,它按预期工作,当它存在时,我得到一个语法错误。为什么它不起作用,我怎样才能让它与现有的线路一起工作?提前致谢
MySQL的prepare()
不支持多查询。使用 prepare 时,不能 运行 多个语句以分号分隔。
参考:https://dev.mysql.com/doc/refman/8.0/en/sql-prepared-statements.html
SQL syntax for prepared statements does not support multi-statements (that is, multiple statements within a single string separated by ; characters).
如果您将 PDO::ATTR_EMULATE_PREPARES 设置为 false(我同意这是一件好事),那么您必须 运行 每个语句单独。
在你的情况下你不需要使用 prepare()
& execute()
,因为你的查询没有参数而且你只使用它一次。
但是无论如何都没有充分的理由使用多查询,无论您是使用准备还是直接执行查询。一次 运行 个查询更简单。由于这些 SQL 语句中的 none 有一个结果集,您可以使用 PDO::exec().
下面是我的编码方式:
function resetidserials($table,$id){
$sql = "SET @num = 0";
$this->conn->exec($sql);
$sql = "UPDATE `$table` SET `$id` = @num := (@num+1)";
$this->conn->exec($sql);
$sql = "ALTER TABLE `$table` AUTO_INCREMENT = 1";
$this->conn->exec($sql);
}
请注意,我使用了反引号来保护您,以防 table 名称或 id 列名称需要它们。我还使用 PHP variable interpolation syntax 而不是 .
的字符串连接。我相信 98% 的 PHP 的 .
的使用都会降低代码的可读性。
不过,我必须评论,在 table 中重新编号自动增量 ID 的整个想法并不是一个好主意。自增id不是行号。这些值必须是唯一的,不一定是连续的。
您不需要在删除行后重新设置自动递增的id。这可能经常发生,您不应该在每次删除后对整个 table 重新编号。如果 table 有 1 亿行怎么办?如果删除的行是 table 中的最后一行怎么办?
此外,除了删除之外,还有其他原因可能会导致 ID 序列出现空缺。如果 INSERT 被回滚怎么办?如果 INSERT 导致冲突,然后后续 INSERT 使用下一个更高的 id 值怎么办?如果自动递增机制在分配下一个 id 值时跳过一个值怎么办(这确实会发生)?
还有一条评论:不鼓励在 MySQL 中使用 :=
。原因见https://dev.mysql.com/doc/refman/8.0/en/user-variables.html。