准备语句不能使用整数值多次执行

Jef*_*ett 5 php sql-server odbc pdo prepared-statement

如何使用不同的整数值正确地重新执行预准备语句?

PDO::PARAM_INT重用ODBC预处理语句时,显式和隐式绑定存在严重错误.

CREATE TABLE mytab (
    col INT,
    something VARCHAR(20)
);
Run Code Online (Sandbox Code Playgroud)

Works:多个字符串

$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]);
Run Code Online (Sandbox Code Playgroud)

Works:单个整数

$values = [42];
$sql = "INSERT INTO mytab (col) VALUES (:col)";
$stmt = $pdoDB->prepare($sql);
foreach ($values as $value)
  $stmt->execute(['col'=>$value]);
Run Code Online (Sandbox Code Playgroud)

不起作用:多个整数

$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]);
Run Code Online (Sandbox Code Playgroud)

它实际上成功插入了第一条记录,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)

我正在使用用于SQLServer®Microsoft®ODBCDriver 13(预览版)从运行PHP 7.0.8的64位Ubuntu 16.04进行连接


我曾尝试在包裹了整个事情PDO::beginTransactionPDO::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();
}
Run Code Online (Sandbox Code Playgroud)

不起作用

$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();
}
Run Code Online (Sandbox Code Playgroud)

我认为有趣的是,我使用PHP 5.6.9 得到了与这个未回答的问题完全相同的错误.然而,它们不能执行甚至一个语句,所以如果有考虑过确切的抛绳该错误的部分区块已经从移动我不知道odbc_stmt.c:254odbc_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]);
}
Run Code Online (Sandbox Code Playgroud)

seb*_*ttg -1

对于准备好的语句,bindParam通常必须在循环之外使用。

  1. bindParam是一步
  2. 设置绑定变量是一个可重复的步骤(循环)
  3. 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();
}
Run Code Online (Sandbox Code Playgroud)