簡體   English   中英

MySQL PDO准備語句與未准備語句的結果不同

[英]mySQL PDO Prepared Statement Different Results from Non-Prepared Statement

我在PDO方面的經驗有限,我已經堅持了一段時間。 問題是,當我未經准備運行代碼時(因為事實證明這是調試PDO的唯一方法),我得到了想要的結果。 當我將其作為准備好的語句運行時,會得到不同的結果。 見下文:

未准備的代碼:

$interval = array("hourly" => "1 HOUR", "daily" => "1 DAY", "weekly" => "7 DAY", "monthly" => "30 DAY", "yearly" => "1 YEAR");
$intervalString = "INTERVAL " . $interval[$p_sLimitType];

$SQL = "SELECT COUNT(*) as `counted` FROM tbl_transaction" .
       " WHERE type='" . $p_sPostType . "'" . 
       " AND catID=" . $p_nCatID .
       " AND serviceID=" . $p_nServiceID .
       " AND serviceIdentity=" . $p_nServiceUserID .
       " AND timestamp BETWEEN DATE_SUB(NOW(), $intervalString . ") AND NOW()";

$theQuery = $DB->Query($SQL);
echo "\r\n\r\nQuery:";
print_r($theQuery);

echo "\r\nResult:";
$result = $theQuery->fetch(PDO::FETCH_ASSOC);
print_r($result);

未准備的結果:

Query:PDOStatement Object
(
    [queryString] => SELECT COUNT(*) as `counted` FROM tbl_transaction WHERE type='pudding' AND catID=13 AND serviceID=1 AND serviceIdentity=3324848959 AND timestamp BETWEEN DATE_SUB(NOW(), INTERVAL 1 DAY) AND NOW()
)

Result:Array
(
    [counted] => 15
)

現在准備好的代碼

$interval = array("hourly" => "1 HOUR", "daily" => "1 DAY", "weekly" => "7 DAY", "monthly" => "30 DAY", "yearly" => "1 YEAR");
$intervalString = "INTERVAL " . $interval[$p_sLimitType];

$SQL = "SELECT COUNT(*) as `counted` FROM tbl_transaction" .
       " WHERE type=:postType" . 
       " AND catID=:catID" .
       " AND serviceID=:serviceID" .
       " AND serviceIdentity=:serviceIdentity" .
       " AND timestamp BETWEEN DATE_SUB(NOW(), :interval) AND NOW()";

// Execute the statement

try { 
    $stmt = $DB->prepare($SQL);
    $stmt->bindParam(':postType', $p_sPostType, PDO::PARAM_STR, 30);
    $stmt->bindParam(':catID', $p_nCatID, PDO::PARAM_INT);
    $stmt->bindParam(':serviceID', $p_nServiceID, PDO::PARAM_INT);
    $stmt->bindParam(':serviceIdentity', $p_nServiceUserID, PDO::PARAM_INT);
    $stmt->bindParam(':interval', $intervalString, PDO::PARAM_STR, 30);
    $result = $stmt->execute();
} catch(PDOException $e) {
    mm_die($e->getMessage());
}

echo "\r\n\$SQL = $SQL";
//          echo "\r\n\$p_nLimitValue = $p_nLimitValue\r\n";
echo "\r\nRow Count: " .$stmt->rowCount() . "\r\n";

以及准備的結果:

$SQL = SELECT COUNT(*) as `counted` FROM tbl_transaction WHERE type=:postType AND siloID=:siloID AND serviceID=:serviceID AND serviceIdentity=:serviceIdentity AND timestamp BETWEEN DATE_SUB(NOW(), :interval) AND NOW()
Row Count: 0

注意在准備好的語句中“行數”為零。 我盯着這個看了比我想承認更多的時間。 誰能看到為什么一個返回結果而另一個不返回結果? 謝謝!

問題在於DATE_SUB()的第二個參數必須是一個間隔,但是您要提供一個字符串。 字符串"INTERVAL 1 HOUR不會自動轉換為相應的間隔。您只能將占位符用於INTERVAL表達式的數字部分,而不能用於關鍵字。

將時間單位從關聯數組中取出,並將所有內容表示為小時。

$interval = array("hourly" => 1, "daily" => 24, "weekly" => 7*24, "monthly" => 30*24, "yearly" => 365*24);

然后,您可以執行以下操作:

$SQL = "SELECT COUNT(*) as `counted` FROM tbl_transaction" .
       " WHERE type=:postType" . 
       " AND catID=:catID" .
       " AND serviceID=:serviceID" .
       " AND serviceIdentity=:serviceIdentity" .
       " AND timestamp BETWEEN DATE_SUB(NOW(), INTERVAL :interval HOUR) AND NOW()";

$stmt->bindParam(':interval', $interval[$p_sLimitType], PDO::PARAM_INT);

占位符不能代表查詢的任意部分,而只能是完整的字符串或數字文字。

因此,您不能綁定間隔的一部分。

只要您在上面的代碼中將間隔列入白名單 ,就可以並且必須堅持使用舊的間隔方法。

select count(*)不可能返回0行。 它總是會返回至少一行 ,包含匹配/中的行數。 獲取0行意味着查詢完全失敗,並且沒有返回結果集,即period。

您是否在PDO中啟用了例外? 默認情況下,它會針對失敗執行“ return false”操作,除非明確啟用它們,否則不會拋出異常。 如果未啟用它們,則您的try/catch無效。

暫無
暫無

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

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