我可以重新定义相同的准备好的语句吗?

Posted

技术标签:

【中文标题】我可以重新定义相同的准备好的语句吗?【英文标题】:Can I redefine the same prepared statement? 【发布时间】:2015-09-20 14:52:05 【问题描述】:

我有一个脚本,可以在 5 个表上发送超过 10 个所有 CRUD 类型的查询(一些 SELECTs 和 JOINs)。最初,我对所有这些都使用了mysqli_* 函数。现在,为了提高安全性,我正在移植代码以使用准备好的语句

我以前没有使用准备好的陈述的经验,我对什么可以做什么和不可以做什么有一些疑问。例如,假设我从 SELECT 查询开始,然后是 UPDATE,最后是 INSERT

我的问题是:

我应该为每个查询重复mysqli_stmt_initmysqli_stmt_close,还是我可以在第一个查询之前启动一次prepare 每个查询的语句并使用它并在所有查询完成后最后关闭它?也就是说,方法2可以吗,还是我应该坚持方法1?

方法 1 - 不重复使用

// SELECT
$stmt = mysqli_stmt_init($link);
mysqli_stmt_prepare($stmt, "SELECT on table 1 and table 2");
...
mysqli_stmt_close($stmt);

// UPDATE
$stmt = mysqli_stmt_init($link);
mysqli_stmt_prepare($stmt, "UPDATE on table 3");
...
mysqli_stmt_close($stmt);

// INSERT
$stmt = mysqli_stmt_init($link);
mysqli_stmt_prepare($stmt, "INSERT INTO table 4");
...
mysqli_stmt_close($stmt);

方法 2 - 重用语句

// INIT
$stmt = mysqli_stmt_init($link);

// SELECT
mysqli_stmt_prepare($stmt, "SELECT on table 1 and table 2");
...

// UPDATE
mysqli_stmt_prepare($stmt, "UPDATE on table 3");
...

// INSERT
mysqli_stmt_prepare($stmt, "INSERT INTO table 4");
...

// CLOSE
mysqli_stmt_close($stmt);

【问题讨论】:

【参考方案1】:

不需要stmt_init()stmt_close(),mysqli_prepare()返回一个stmt对象,php处理清理,正确的顺序是mysqli_stmt::prepare => mysqli_stmt::bind_param => mysqli_stmt::execute

$mysqli = new mysqli( "host", "user", "pass", "db" );

$stmt = $mysqli->prepare( "SELECT * FROM table WHERE id = ?" );
$stmt->bind_param( "i", $id );

$id = 5;

$stmt->execute();

您可以使用不同的参数多次执行同一语句,例如:

$stmt = $mysqli->prepare( "SELECT * FROM table WHERE id = ?" );
$stmt->bind_param( "i", $id );

$id = 5;

$stmt->execute();    // executed: SELECT * FROM table WHERE id = 5

$id = 3;

$stmt->execute();    // executed: SELECT * FROM table WHERE id = 3

但如果是不同的语句,您必须分别准备每个语句。

【讨论】:

谢谢。但是,我使用的是程序风格,我不确定是否可以放弃初始化步骤。【参考方案2】:

是的,方法2没问题。

也不需要最终关闭它,因为它会在脚本结束时关闭。

【讨论】:

以上是关于我可以重新定义相同的准备好的语句吗?的主要内容,如果未能解决你的问题,请参考以下文章

MySql“视图”、“准备好的语句”和“准备好的语句需要重新准备”

如何摆脱 MySQL 错误“需要重新准备准备好的语句”

1615 准备好的语句需要在codeigniter中重新准备

当它们包含 ROW_NUMBER() 时,JDBC-driver / SQL Server 总是重新编译我准备好的语句

Golang使用准备好的SQL语句

在 MySQL 中使用准备好的语句可以防止 SQL 注入攻击吗?