php - 准备好的语句不能用整数值执行多次

标签 php sql-server pdo odbc prepared-statement

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

在重用 ODBC 准备语句时,显式和隐式绑定(bind) 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 Fatal error: Uncaught PDOException: SQLSTATE[22018]: Invalid character value for cast specification: 206 [Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Operand type clash: text is incompatible with 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();
}

我认为有趣的是,我遇到了与此 unanswered question 完全相同的错误使用 PHP 5.6.9。然而,他们甚至不能执行一条语句,所以我想知道是否有一个部分补丁,考虑到抛出错误的确切行已经从 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]);
}

最佳答案

如果是准备好的语句,通常必须在循环外使用 bindParam

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

关于php - 准备好的语句不能用整数值执行多次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39088156/

相关文章:

sql-server - SQL Server 性能 - Subselect 或 Inner Join?

java - 从 jTable 更新 SQL Server 表

sql-server - SQL Server 2014 备份到 2012

php - 在 php.ini 文件中添加扩展条目后,sqlsrv 驱动程序不会出现在 WAMP 服务器 phphinfo() 上

php - 如何在 mysql 和 php 中获取月明智的记录

PHP PDO : Charset=UTF8 : An invalid keyword charset was specified in the dsn string

php - 如何将数组传递给使用 func_get_args 检索参数的函数

mysql - 使用带日期的 pdo prepare 和 UNION 不返回任何结果(mysql)

php - 在 Ubuntu Linux 12 中启用 Excel PHP PDO 驱动程序

php - 按首选项覆盖 Magento_SalesRule ResourceModel 会引发错误 : Type Error occurred when creating object