如何使用不同的整数值正确重新执行预准备语句?
重用ODBC预处理语句时,显式和隐式绑定PDO::PARAM_INT
会出现严重错误。
CREATE TABLE mytab (
col INT,
something VARCHAR(20)
);
$pdoDB = new PDO('odbc:Driver=ODBC Driver 13 for SQL Server;
Server='.DATABASE_SERVER.';
Database='.DATABASE_NAME,
DATABASE_USERNAME,
DATABASE_PASSWORD
);
$pdoDB->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$values = ['here','are','some','values'];
$sql = "INSERT INTO mytab (something) VALUES (:something)";
$stmt = $pdoDB->prepare($sql);
foreach ($values as $value)
$stmt->execute(['something'=>$value]);
$values = [42];
$sql = "INSERT INTO mytab (col) VALUES (:col)";
$stmt = $pdoDB->prepare($sql);
foreach ($values as $value)
$stmt->execute(['col'=>$value]);
$values = [1,3,5,7,11];
$sql = "INSERT INTO mytab (col) VALUES (:col)";
$stmt = $pdoDB->prepare($sql);
foreach ($values as $value)
$stmt->execute(['col'=>$value]);
它实际上成功插入了第一条记录1
,但在尝试在下次执行时重用该语句时失败。
PHP致命错误:未捕获PDOException:SQLSTATE [22018]:强制转换规范的字符值无效:206 [Microsoft] [SQL Server的ODBC驱动程序13] [SQL Server]操作数类型冲突:text与int不兼容(SQLExecute [ 206] at /build/php7.0-lPMnpS/php7.0-7.0.8/ext/pdo_odbc/odbc_stmt.c:260)
我使用Microsoft® ODBC Driver 13 (Preview) for SQL Server®
从运行PHP 7.0.8的64位Ubuntu 16.04连接我尝试在PDO::beginTransaction
和PDO::commit
我也尝试使用PDOStatement::bindParam
,但它会抛出完全相同的错误。
$values = [1];
$sql = "INSERT INTO mytab (col) VALUES (:col)";
$stmt = $pdoDB->prepare($sql);
foreach ($values as $value){
$stmt->bindParam('col', $value, PDO::PARAM_INT);
$stmt->execute();
}
$values = [1,2];
$sql = "INSERT INTO mytab (col) VALUES (:col)";
$stmt = $pdoDB->prepare($sql);
foreach ($values as $value){
$stmt->bindParam('col', $value, PDO::PARAM_INT);
$stmt->execute();
}
我认为有趣的是,我使用PHP 5.6.9获得与此unanswered question完全相同的错误。但是,它们甚至无法执行一个语句,因此我想知道是否存在部分补丁,考虑到错误的确切行已从odbc_stmt.c:254
移至odbc_stmt.c:260
如果我在循环中准备语句,那么它可以正常工作。但我已经读到这是非常低效的,我应该能够重用声明。我特别担心使用大量数据集。这个可以吗?我能做些什么更好的事情吗?
$values = [1,3,5,7,9,11];
$sql = "INSERT INTO mytab (col) VALUES (:col)";
foreach ($values as $value){
$stmt = $pdoDB->prepare($sql);
$stmt->execute(['col'=>$value]);
}
答案 0 :(得分:0)
对于准备好的语句,通常必须在循环外使用bindParam
。
bindParam
仅一步之遥execute
我想,类似的方法会起作用:
$stmt = $pdoDB->prepare("INSERT INTO mytab (col, key) VALUES (:col, :key)");
// bind params (by reference)
$stmt->bindParams(":col", $col, PDO::PARAM_STR); //bind variable $col
$stmt->bindParams(":key", $key, PDO::PARAM_INT); //bind variable $key
$values = ['here','are','some','values'];
foreach ($values as $i => $value) {
$col = $value; //set col
$key = $i; //set key
$stmt->execute();
}