【发布时间】:2016-11-10 08:57:49
【问题描述】:
注意:我已将此问题范围缩小到具体的 PDO,因为我能够使用 odbc_* 函数成功地准备和执行语句。
为什么我不能将此参数绑定到 PDO 准备语句?
这行得通:
$mssqldriver = 'ODBC Driver 13 for SQL Server';
$pdoDB = new PDO("odbc:Driver=$mssqldriver;Server=$hostname;Database=$dbname", $username, $password);
$pdoDB->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$sql = "SELECT 'value' AS col where 'this' = 'this'";
$stmt = $pdoDB->prepare($sql);
$params = [];
$stmt->execute($params);
print_r($stmt->fetch());
Array ( [col] => value [0] => value )
不起作用:
$sql = "SELECT 'value' AS col where 'this' = ?";
$stmt = $pdoDB->prepare($sql);
$params = ['this'];
$stmt->execute($params);
print_r($stmt->fetch());
Web 服务器正在 Linux Ubuntu 14.04 上运行 PHP 5.5.9,并使用适用于 SQL Server 的 ODBC 驱动程序 13 并连接到 Windows Server 2012 上的 Microsoft SQL Server 2012
这是完整的错误:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[22001]: String data, right truncated: 0 [Microsoft][ODBC Driver 13 for SQL Server] String data, right truncation (SQLExecute[0] at /build/buildd/php5-5.5.9+dfsg/ext/pdo_odbc/odbc_stmt.c:254)' in /var/www/scratch.php:46 Stack trace: #0 /var/www/scratch.php(46): PDOStatement->execute(Array) #1 {main} thrown in /var/www/scratch.php on line 46
我也试过设置:
$pdoDB->setAttribute( PDO::ATTR_EMULATE_PREPARES, true );
并使用命名参数:
$sql = "SELECT 'value' AS col where 'this' = :myVal";
$stmt = $pdoDB->prepare($sql);
$params = ['myVal' => 'this'];
$stmt->execute($params);
print_r($stmt->fetch());
即使有明确的冒号:
$params = [':myVal' => 'this'];
我也尝试使用bindParam,如this answer 所示:
$sql = "SELECT 'value' AS col where 'this' = ?";
$stmt = $pdoDB->prepare($sql);
$param = 'this';
$stmt->bindParam(1, $param);
$stmt->execute();
print_r($stmt->fetch());
以及命名参数:
$sql = "SELECT 'value' AS col where 'this' = :myVal";
$stmt = $pdoDB->prepare($sql);
$param = 'this';
$stmt->bindParam(':myVal', $param, PDO::PARAM_STR);
$stmt->execute();
print_r($stmt->fetch());
如果我尝试明确设置长度:
$stmt->bindParam(':myVal', $param, PDO::PARAM_STR, 4);
我收到一个额外错误:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 102 [Microsoft][ODBC Driver 13 for SQL Server][SQL Server] Incorrect syntax near 'OUTPUT'.
是的,所有这些都是一个没有表格的简单示例,因此您可以轻松地复制它,但可以肯定的是,我实际上已经用真实的表格进行了尝试。
CREATE TABLE myTable (
id INT IDENTITY PRIMARY KEY,
val NVARCHAR(255)
);
INSERT INTO myTable (val) VALUES ('hello world');
作品:
$sql = "SELECT * FROM myTable WHERE val = 'hello world'";
$stmt = $pdoDB->prepare($sql);
$params = [];
$stmt->execute($params);
print_r($stmt->fetch());
Array ( [id] => 1 [0] => 1 [val] => hello world [1] => hello world )
不起作用:
$sql = "SELECT * FROM myTable WHERE val = ?";
$stmt = $pdoDB->prepare($sql);
$params = ['hello world'];
$stmt->execute($params);
print_r($stmt->fetch());
所有路径都会导致相同的错误:
字符串数据,右截断
【问题讨论】:
-
您是否启用了 ATTR_EMULATE_PREPARES?如果你改变它会有什么不同吗?如果您使用像
SELECT :param as col这样的命名参数并绑定[':param' => 'test']会有所不同吗?我不希望改变...... -
@MichaelBerkowski 我只是尝试了这两个都无济于事-同样的错误。
-
“this”文件是什么类型的文件?
-
@zajonc 这是一个字符串文字,因此其他人无需数据集即可轻松复制。我的实际用例涉及 NVARCHAR(255),但我无法让它适用于任何数据类型。
-
我想这完全是 DBMS 问题,与 PDO 关系不大。出于好奇,您也可以使用全静态查询进行重现吗?我的意思是
'this' = 'this'?
标签: php sql-server pdo odbc prepared-statement