見http://www.php.net/manual/en/pdo.prepare.php
注:
模擬預處理語句不與數據庫 服務器通信,以PDO ::準備()不檢查語句。
(其實真正準備好的語句不是立即發送反正看答案下面Q2)
反正你可以發出:
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
獲得與SQL PREPARE實現真正準備好的發言命令。 更多信息請參見http://www.php.net/manual/en/pdo.setattribute.php。
在進一步的討論和測試,出現了兩個問題:
Q1。爲什麼pdo::getAttribute(PDO::ATTR_EMULATE_PREPARES)
會產生錯誤?
事實上setAttribute
不報錯了,但getAttribute(PDO::ATTR_EMULATE_PREPARES)
說:
'SQLSTATE [IM001]:驅動器不支持此功能:驅動程序 不支持屬性'
綜觀documentation for pdo::getAttribute,它表示適用於數據庫連接的常量如下,以及從PDO::ATTR_AUTOCOMMIT
到PDO::ATTR_TIMEOUT
之間的一些常量,並且很顯着的是PDO::ATTR_EMULATE_PREPARES
是不在其中。所以嚴格來說,無論如何我們都不應該期待getAttribute(PDO::ATTR_EMULATE_PREPARES)
的工作。
現在看看源代碼,可以肯定,看來該pdo_pgsql
驅動程序提供了一個pdo_pgsql_get_attribute
功能,有一個開關聲明:
- PDO_ATTR_CLIENT_VERSION
- PDO_ATTR_SERVER_VERSION
- PDO_ATTR_CONNECTION_STATUS
- PDO_ATTR_SERVER_INFO
就是這樣。沒有任何PDO_ATTR_EMULATE_PREPARES的痕跡,這就是爲什麼最終會出現此錯誤。
在另一方面,該功能pdo_pgsql_set_attr
對switch語句:
- PDO_ATTR_EMULATE_PREPARES
- PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT
這證實了當設置該屬性實際上是考慮。 因此,PDO與getAttribute
不符,與setAttribute
不符。
Q2 - 當準備仿真爲false時,爲什麼準備好時虛假聲明不立即引發錯誤?
考慮pgsql_statement.c
這段代碼:
if (!S->is_prepared) {
stmt_retry:
/* we deferred the prepare until now, because we didn't
* know anything about the parameter types; now we do */
S->result = PQprepare(H->server, S->stmt_name, S->query,
stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0,
S->param_types);
這表明PQprepare
使用(所以這是一個「真正的」事先準備好的聲明),也證明這種說法是沒有立即發送到服務器。這就是爲什麼dbo::prepare("bogus statement")
不會返回false:由於缺少參數類型,它實際上不會發送到服務器。
Postgres PDO驅動程序沒有實現ATTR_EMULATE_PREPARES。 – CXJ
它似乎被仿效。我在問爲什麼,當Postgres本地支持準備好的語句,實際上,PHP的Postgres的「本地」API,例如pg_prepare(),正確執行此操作。這是奇怪的PDO驅動程序。它壞了嗎?無證?只是我的版本? – CXJ
準備好的語句是在2003年發佈的PG-7.4的客戶端 - 服務器協議中實現的。PDO for PG幾乎在同一時間首次發佈,所以它必須與現有的7.3以下版本一起工作,因此需要仿真。 –