Вопрос:

Подготовленный оператор не может быть выполнен несколько раз с целочисленными значениями

php sql-server pdo odbc prepared-statement

796 просмотра

1 ответ

18033 Репутация автора

Как правильно повторно выполнить подготовленный оператор, используя разные целочисленные значения?

Что-то смертельно неправильно с явным и неявным связыванием PDO::PARAM_INTпри повторном использовании подготовленного ODBC оператора.

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: Uncaught PDOException: SQLSTATE [22018]: недопустимое символьное значение для спецификации приведения: 206 [Microsoft] [ODBC-драйвер 13 для SQL Server] [SQL Server] Тип операнда clash: текст несовместим с int (SQLExecute [206] в /build/php7.0-lPMnpS/php7.0-7.0.8/ext/pdo_odbc/odbc_stmt.c:260)

Я подключаюсь из 64-битной Ubuntu 16.04 под управлением PHP 7.0.8, используя Microsoft® ODBC Driver 13 (Preview) для SQL Server®


Я попытался обернуть все это в 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. Тем не менее, они не могут выполнить даже один оператор, поэтому мне интересно, был ли частичный патч, учитывая, что точная строка, выдававшая ошибку, переместилась 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]);
}
Автор: Jeff Puckett Источник Размещён: 22.08.2016 08:26

Ответы (1)


0 плюса

141 Репутация автора

В случае подготовленных заявлений вы должны использовать 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();
}
Автор: seboettg Размещён: 09.08.2018 01:22
Вопросы из категории :
32x32