添加 :start 作为要跳过的参数时出现以下错误。我知道如果我对 SKIP/NEXT 值进行硬编码并且 :customerID 保持不变,则 SQL 查询会起作用。如果我删除 :start 子句并将其保留为 SKIP 1 FIRST 5 ... WHERE t1.customer_num = :customerID ...
它工作得很好。我找不到错误发生的原因。
错误
exception 'PDOException' with message 'SQLSTATE[HY004]: Invalid SQL data type: -11064 [Informix][Informix ODBC Driver]SQL data type out of range
我尝试过的东西:
- 使用 BindParam 而不是 BindValue 通过引用绑定(bind)参数。
- 使用 PDO_STR 尝试将 :start 绑定(bind)为字符串。没有成功。
- SQL 查询本身中 :start 的硬编码值。这行得通。
- 使用
$sql->bindValue(':start', (int) 1, PDO:PARAM_INT);
— 不行。 - 通过首先分配给 PHP 变量来尝试编号 4,结果相同。
有什么建议吗?我正在使用 PHP 5.3。(最近的东西)和使用 PDO 连接器的 Informix 11。同样,它仅与 customerID 一起使用,但不适用于 :start 并返回上述错误。
$sql = null;
$sql= $conn->prepare('SELECT SKIP :start FIRST 5 TRIM(loc_esi_id) FROM customer t1,customer_ts_data t2 WHERE t1.customer_num = :customerID AND t1.customer_num = t2.customer_num');
//Bind values to parameters(by value)
$sql->bindValue(':start', $start ,PDO::PARAM_INT);
$sql->bindValue(':customerID', $customerID, PDO::PARAM_INT);
//$sql->bindParam(':count',$count,PDO::PARAM_INT);
$results = null;
try{
$sql->execute();
$results = $sql->fetchAll();
} catch (PDOException $e) {
//Error Handling, etc.
最佳答案
通常,占位符的 :start
表示法既不是标准 SQL 语法也不是(本地)Informix 语法。您需要使用 ?
作为占位符,因此:
$sql= $conn->prepare('SELECT SKIP ? FIRST 5 TRIM(loc_esi_id)
FROM customer t1
JOIN customer_ts_data t2 ON t1.customer_num = t2.customer_num
WHERE t1.customer_num = ? AND ');
(如果所有这些都需要在 PHP 中放在一行中,我为为了提高可读性而牺牲准确性而道歉)。
现在,PDO 系统有可能自动将 :start
符号转换为 ?
,在这种情况下我们会遇到不同的问题。但是除非你确定 :name
符号有效,否则......
不确定的原因之一是 bindValue()
调用似乎需要名称,而不是 ?
可能需要的数字。您的代码错误是否检查了 bindValue()
调用?
此 ESQL/C 代码有效,产生了我期望的输出。
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
$ char *dbase = "stores";
$ int num_skip = 3;
$ int num_fetch = 5;
if (argc > 2)
{
fprintf(stderr, "Usage: %s [dbase]\n", argv[0]);
exit(1);
}
if (argc == 2)
dbase = argv[1];
exec sql whenever error stop;
exec sql connect to :dbase;
exec sql prepare p from "select skip ? first ? tabid, tabname from informix.systables";
exec sql declare c cursor for p;
exec sql open c using :num_skip, :num_fetch;
while (sqlca.sqlcode == 0)
{
$ int4 tabid;
$ varchar tabname[129];
exec sql fetch c into :tabid, :tabname;
if (sqlca.sqlcode != 0)
break;
printf("%d: %s\n", tabid, tabname);
}
exec sql close c;
exec sql free c;
exec sql free p;
exec sql disconnect all;
return 0;
}
输出
4: systabauth
5: syscolauth
6: sysviews
7: sysusers
8: sysdepend
这表明如果正确使用占位符符号,则可以使用 SKIP 和 FIRST 参数。
如果您找不到使它与 PDO 一起工作的方法,您可能遇到了错误。如果您可以在将环境变量 SQLIDEBUG=2:/tmp/your_sub_dir/check
设置为某个类似值的情况下运行您的代码,那么您应该找到发送到服务器的内容的记录(除了连接设置)在名称为 /tmp/your_sub_dir/check_21484_0_aedc1e0
的文件中。数字模式有点可变。然后您可以在该文件上运行 sqliprint
程序并查看 PDO 发送到服务器的内容。这将是确定 PDO 或 Informix 中是否存在错误的一种非常快速的方法。
例如,我从 sqliprint
得到的部分输出是:
C->S (20) Time: 2012-05-29 17:55:08.65225
SQ_CONNECT
"stores" [6]
"stores" [6]
C->S (72) Time: 2012-05-29 17:55:08.65239
SQ_PREPARE
# values: 2
CMD.....: "select skip ? first ? tabid, tabname from informix.systables" [60]
SQ_NDESCRIBE
SQ_WANTDONE
SQ_EOT
可以很清楚的看到发送的SQL语句。如果你没有看到 ?
占位符,那么上游有问题; Informix 的 PDO 驱动程序没有正确地完成它的工作,或者它被滥用了。如果您看到 ?
占位符,我们将遇到一组不同的问题,但我认为如果这就是问题所在,我会感到惊讶。
SQLIDEBUG 机制中唯一需要注意的是,无论哪个进程连接到数据库,您都需要在环境中设置环境变量。对于独立的 ESQL/C 程序,这是微不足道的。如果您要通过网络服务器和 PHP,那可能会更棘手 — 但这是可以做到的。
关于php - Informix 的变量绑定(bind)返回错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10803475/