簡體   English   中英

mysqli准備語句中的致命錯誤

[英]Fatal Error in mysqli prepared statement

我正在嘗試使用下面的一些示例代碼來學習如何編寫准備好的語句。

我有一個初始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:從j_oracle_cat c,j_oracle_pages p中選擇p.fld_is_parent,c.fld_id = p.fld_catid和c.fld_tag =嗎? 錯誤:第95行的C:\\ xampp \\ htdocs \\ php \\ a.php中

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';

連接到數據庫:

<?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 . ']');
}

?>

大概我在做些愚蠢的事情,但是我看不到什么?

所以這是我的建議; 我沒有發現您的代碼有任何明顯的錯誤,但是這些步驟應該可以更輕松地診斷問題,即使不能完全解決問題。 首先,將prepare()調用移出循環*。 接下來, 顯式創建statement對象 ,這樣,如果准備工作存在問題,則可以直接從Statement對象獲取錯誤。 最后,在流程的每個階段檢查有效的返回值,包括參數綁定語句執行

$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()進行轉義,以避免注入的風險。 您可以使用雙引號將變量包含在字符串中,並避免使用許多不必要的. 操作員無處不在。 這是個人喜好問題,但許多人認為它更具可讀性。

*預准備語句的一大好處是它們將查詢的准備與執行分開 ,從而避免了設置MySQL以運行查詢所帶來的開銷。 通過反復准備一份聲明,您可以完全刪除該好處。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM