我正在考虑使用node.js/socket.io作为实时用户界面。 我习惯于使用PHP,它有一个很棒的,真正万无一失的准备语句系统。 例如:
$dbh->prepare('SELECT * FROM table WHERE val=:val1 OR val=:val2');
$dbh->execute(array('val1'=>'stuff','val2'=>'more stuff'));
现在,node.js没有这种奢侈,所以我正在考虑自己做一些事情来模拟它。 这里到底发生了什么?
谢谢!
使用
预准备语句或参数化语句以高效率重复执行同一语句。
基本工作流程
预准备语句执行包括两个阶段:准备和执行。在准备阶段,将语句模板发送到数据库服务器。服务器执行语法检查并初始化服务器内部资源供以后使用。
MySQL 服务器支持使用带有 ?
的匿名位置占位符。
1 第一阶段:准备
$mysqli = new mysqli("example.com", "user", "password", "database");
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
/* Prepared statement, stage 1: prepare */
if (!($stmt = $mysqli->prepare("INSERT INTO test(id) VALUES (?)"))) {
echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
}
2 执行
准备后执行。在执行期间,客户端绑定参数值并将其发送到服务器。服务器从语句模板和绑定值创建语句,以使用先前创建的内部资源执行该语句。
$id = 1;
if (!$stmt->bind_param("i", $id)) {
echo "Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error;
}
if (!$stmt->execute()) {
echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
}
3 重复执行
预准备语句可以重复执行。每次执行时,都会计算绑定变量的当前值并将其发送到服务器。不会再次分析该语句。语句模板不会再次传输到服务器。
/* Prepared statement: repeated execution, only data transferred from client to server */
for ($id = 2; $id < 5; $id++) {
if (!$stmt->execute()) {
echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
}
}
/* explicit close recommended */
$stmt->close();
预准备语句从根本上分离数据和命令。 当两者之间的界限因错误输入而变得模糊时,就会发生SQL注入。 将它们分开使注射变得不可能。
若要正确执行此操作,需要具有此功能的该数据库的数据库服务器和客户端。 正如您所发现的,许多数据库客户端实际上并不使用预准备语句功能,而只是转义数据以在查询中用于模拟预准备语句。 这仍然可以被认为是安全的...这些客户端通常经过严格测试。
请注意,当客户端只是模拟预准备语句时,您不会获得预准备语句的性能优势。