Préparé déclaration ne peut pas être exécutée plusieurs fois avec des valeurs entières
Comment puis-je correctement ré-exécuter une instruction préparée en utilisant des valeurs entières différentes?
Il y a quelque chose reliques de mal avec explicites et implicites de liaison PDO::PARAM_INT
lors de la réutilisation d'un ODBC déclaration préparée.
CREATE TABLE mytab (
col INT,
something VARCHAR(20)
);
Fonctionne : plusieurs chaînes de caractères
$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]);
Fonctionne : un simple entier
$values = [42];
$sql = "INSERT INTO mytab (col) VALUES (:col)";
$stmt = $pdoDB->prepare($sql);
foreach ($values as $value)
$stmt->execute(['col'=>$value]);
ne fonctionne pas: nombres entiers multiples
$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]);
il insère effectivement avec succès le premier enregistrement 1
mais échoue quand il tente de réutiliser l'instruction sur l'exécution suivante.
PHP Fatal error: Uncaught PDOException: SQLSTATE[22018]: invalides 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)
je me connecte à partir de 64 bits Ubuntu 16.04 lancer PHP 7.0.8 en utilisant le pilote Microsoft® ODBC 13 (Preview) pour SQL Server®
j'ai essayé d'envelopper le tout dans PDO::beginTransaction
et PDO::commit
j'ai aussi essayé d'utiliser PDOStatement::bindParam
mais il jette l'exacte même erreur.
Œuvres
$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();
}
Ne Fonctionne Pas
$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();
}
je pense qu'il est intéressant de noter que j'obtiens exactement la même erreur que cette question sans réponse en utilisant PHP 5.6.9. Cependant, ils ne sont pas capables d'exécuter même une déclaration, donc je me demande s'il y a eu un patch partiel considérant la ligne exacte jetant l'erreur a déménagé de odbc_stmt.c:254
à odbc_stmt.c:260
solution de contournement
si je prépare la déclaration à l'intérieur de la boucle, puis il fonctionne très bien. mais j'ai lu que c'est très inefficace et je devrais pouvoir réutiliser la déclaration. Je suis particulièrement inquiet de l'utiliser avec des ensembles de données massives. Est-ce OK? Est-il quelque chose de mieux que je peux faire?
$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]);
}
1 réponses
dans le cas de déclarations préparées vous devez utiliser bindParam
en dehors de la boucle, habituellement.
-
bindParam
est un pas simple - jeu de lier des variables est un reproductibles à l'étape (boucle)
- vous devez exécuter
execute
pour chaque répétition
je suppose, quelque chose comme ça marcherait:
$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();
}