好的,我已经确认这与PHP明确有效。
$ php --version
PHP 5.6.16 (cli) (built: Dec 30 2015 15:09:50) (DEBUG)
<pdo version>
pdo_pgsql
PDO Driver for PostgreSQL enabled
PostgreSQL(libpq) Version 9.4.0
Module version 1.0.2
Revision $Id: fe003f8ab9041c47e97784d215c2488c4bda724d $
我想使用PDO在PHP中重新创建以下SQL:
UPDATE relationships SET status = 4 WHERE created > NOW() - interval '2 seconds';
此脚本正在运行:
<?php
$db = new PDO('pgsql:dbname=db;host=localhost;user=stevetauber');
$stmt = $db->prepare("UPDATE relationships SET status = 4 WHERE created > NOW() - interval '?'");
$stmt->execute(array("2 seconds"));
这里是命名占位符:
<?php
$db = new PDO('pgsql:dbname=db;host=localhost;user=stevetauber');
$stmt = $db->prepare("UPDATE relationships SET status = 4 WHERE created > NOW() - interval ':blah'");
$stmt->execute(array(":blah" => "2 seconds"));
出现此错误:
Warning: PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: :blah in ... line 5
现在根据PHP documentation,
示例#6使用占位符无效:
<?php
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name LIKE '%?%'");
$stmt->execute(array($_GET['name']));
// placeholder must be used in the place of the whole value
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name LIKE ?");
$stmt->execute(array("%$_GET[name]%"));
?>
以下是更新后的代码:
<?php
$db = new PDO('pgsql:dbname=db;host=localhost;user=stevetauber');
$stmt = $db->prepare("UPDATE relationships SET status = 4 WHERE created > NOW() - :blah");
$stmt->execute(array(":blah" => "interval '2 seconds'"));
产生这些数据库错误(没有脚本错误):
ERROR: operator does not exist: timestamp with time zone > interval at character 51
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
STATEMENT: UPDATE relationships SET status = 4 WHERE created > NOW() - $1
PDO在这里做了一些奇怪的事情,因为:
# select NOW() - interval '2 seconds' as a , pg_typeof(NOW() - interval '2 seconds') as b;
a | b
-------------------------------+--------------------------
2015-12-30 18:02:20.956453+00 | timestamp with time zone
(1 row)
那么我如何使用PostgreSQL和间隔的命名占位符?
答案 0 :(得分:3)
占位符用于纯值,而不是用单位(或其他任何东西)装饰的值。
要在占位符中表达interval '2 seconds'
,有两个选项:
,写下:secs * interval '1 second'
并将:secs
绑定到php
或写:cast(:mystring as interval)
,并将:mystring
绑定到字符串'2 seconds'
。它将通过显式强制转换动态解释。
在尝试使用psql命令行客户端与PDO驱动程序进行比较时,请使用PREPARE
和EXECUTE
SQL语句与postgres本地$N
占位符,而不是使用参数值已在字面上逐字写入查询。当PDO::ATTR_EMULATE_PREPARES
设置为false时,这将匹配PHP驱动程序实际执行的操作。
在你的问题的最后一部分,在psql中尝试这个时(你的查询,只是简化为不需要表):
select now() > now() - interval '2 seconds';
它确实起作用并返回&#39; (真)。
但如果你尝试过:
prepare p as select now() > now() - $1;
如果失败
错误:运算符不存在:带时区的时间戳&gt;间隔
与PDO的准备/执行错误相同。
另一方面,这确实有效:
=> prepare p as select now() > now() - interval '1 second'*$1;
PREPARE
=> execute p(2);
?column?
----------
t