我正在尝试使用下面的示例代码学习如何编写预备语句。
我有一个初始SQL语句,对于每个返回的记录,请对返回的结果执行另一次SQL检查。
<?php
$sql_b = "SELECT fld_title, fld_tag FROM j_oracle_cat WHERE fld_tag IS NOT NULL ORDER BY fld_title";
if (!$result_b = $conn -> query($sql_b)) {
die('There was an error running the query [' . $conn -> error . ']');
} else {
if (!$result_b -> num_rows) {
echo "<h4>No Categories Defined</h4>";
} else {
while($row_b = $result_b -> fetch_assoc()) {
$cat_ttl = $row_b["fld_title"];
$cat_tag = $row_b["fld_tag"];
echo "<h4><a href='category.php?tag=" . $cat_tag . "'>" . $cat_ttl . "</a></h4>";
$sql_c = "SELECT p.fld_tag FROM j_oracle_cat c, j_oracle_pages p WHERE c.fld_id = p.fld_catid AND c.fld_tag = ?";
/* Prepare statement */
$stmt = $conn->prepare($sql_c);
if($stmt === false) {
trigger_error('Wrong SQL: ' . $sql_c . '<hr />Error: ' . $conn->error, E_USER_ERROR);
}
/* Bind parameters. Types: s = string, i = integer, d = double, b = blob */
$stmt->bind_param('s',$cat_tag);
/* Execute statement */
$stmt->execute();
}
$result_b -> free();
}
}
?>
当我运行代码时,它得到了这么远:
<h4><a href='category.php?tag=accounts-payable'>Accounts Payable</a></h4>
<h4><a href='category.php?tag=accounts-receivable'>Accounts Receivable</a></h4>
然后错误:
致命错误:错误的SQL:SELECT p.fld_is_parent FROM j_oracle_cat c,j_oracle_pages p WHERE c.fld_id = p.fld_catid AND c.fld_tag =? 错误:在 C:\ xampp \ htdocs \ php \ a.php 上 95
第95行就是这个:
trigger_error('Wrong SQL: ' . $sql_c . '<hr />Error: ' . $conn->error, E_USER_ERROR);
表格结构:
CREATE TABLE `j_oracle_cat` (
`fld_id` int(11) NOT NULL AUTO_INCREMENT,
`fld_title` varchar(255) DEFAULT NULL,
`fld_desc` varchar(255) DEFAULT NULL,
`fld_tag` varchar(255) DEFAULT NULL,
`fld_label` varchar(255) DEFAULT NULL,
`fld_parent` int(2) DEFAULT '0',
PRIMARY KEY (`fld_id`)
) ENGINE=MyISAM AUTO_INCREMENT=16 DEFAULT CHARSET=latin1
CREATE TABLE `j_oracle_pages` (
`fld_id` int(11) NOT NULL AUTO_INCREMENT,
`fld_title` varchar(255) DEFAULT NULL,
`fld_catid` int(11) DEFAULT NULL,
`fld_cols` int(2) DEFAULT '1',
`fld_left` text,
`fld_content` text,
`fld_tag` varchar(255) DEFAULT NULL,
`fld_date` date DEFAULT NULL,
`fld_is_parent` char(1) DEFAULT NULL,
PRIMARY KEY (`fld_id`)
) ENGINE=MyISAM AUTO_INCREMENT=83 DEFAULT CHARSET=latin1
我已尝试直接运行sql并且它没有错误,对于示例代码并且它返回例如3行:
SELECT p.fld_tag FROM j_oracle_cat c, j_oracle_pages p WHERE c.fld_id = p.fld_catid AND c.fld_tag = 'accounts-receivable';
与db的连接:
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "mydb";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
if($conn -> connect_errno > 0){
die('Unable to connect to database [' . $conn->connect_error . ']');
}
?>
据说我做的事情很傻,但我看不清楚是什么?
答案 0 :(得分:1)
所以这是我的建议;我没有看到您的代码有任何明显错误,但如果不能彻底解决问题,这些步骤应该可以更容易地诊断问题。首先,将prepare()
调用移出循环*。接下来,explicitly create the statement object,这样如果准备工作有问题,您可以直接从语句对象中获取错误。最后,在流程的每个阶段检查有效回报,包括parameter binding和statement execution。
$sql_b = "SELECT fld_title, fld_tag FROM j_oracle_cat WHERE fld_tag IS NOT NULL ORDER BY fld_title";
if (!$result_b = $conn->query($sql_b)) {
trigger_error("Error executing query: $conn->error<br/>SQL query: $sql_b", E_USER_ERROR);
} else {
if (!$result_b->num_rows) {
echo "<h4>No Categories Defined</h4>";
} else {
/* Prepare statement */
$sql_c = "SELECT p.fld_tag FROM j_oracle_cat c, j_oracle_pages p WHERE c.fld_id = p.fld_catid AND c.fld_tag = ?";
$stmt = $conn->stmt_init();
if (!$stmt) {
trigger_error("Error creating statement: $conn->error", E_USER_ERROR);
}
$result = $stmt->prepare($sql_c);
if(!$result) {
trigger_error("Error preparing statement: $stmt->error<br/>SQL query: $sql_c", E_USER_ERROR);
}
/* Bind parameters. Types: s = string, i = integer, d = double, b = blob */
// needs a dummy value for the initial bind
$row_b = array("fld_tag"=>"");
$result = $stmt->bind_param("s", $row_b["fld_tag"]);
if(!$result) {
trigger_error("Error binding parameter: $stmt->error<br/>", E_USER_ERROR);
}
while($row_b = $result_b -> fetch_assoc()) {
$cat_ttl = htmlspecialchars($row_b["fld_title"]);
$cat_tag = htmlspecialchars($row_b["fld_tag"]);
echo "<h4><a href='category.php?tag=$cat_tag'>$cat_ttl</a></h4>";
/* Execute statement */
$result = $stmt->execute();
if(!$result) {
trigger_error("Error executing statement: $stmt->error<br/>Bound parameter value: $row_b[fld_tag]", E_USER_ERROR);
}
// I assume you'll be doing something with $result down here?
}
$result_b->free();
$stmt->close();
}
}
一些附注:在将它们放入HTML之前,您应始终使用htmlspecialchars()
转义数据库结果,以避免注入风险。您可以在字符串内部use double quotes to include variables,并避免在任何地方拥有数十个不必要的.
运算符。这是个人偏好的问题,但许多人发现它更具可读性。
*预准备语句的一大好处是它们separate the preparation of the query from its execution,避免了设置MySQL运行查询所涉及的开销。通过反复准备声明,您可以完全取消该利益。