Fehler beim Vorbereiten einer Multiple-Insert-Abfrage

Lesezeit: 8 Minuten

Benutzer-Avatar
Griff

// BUILD VALUES
$count = count($matches);
for($i = 0; $i < $count; ++$i) {
    $values[] = '(?)';
}
// INSERT INTO DATABASE
$q = $this->dbc->prepare("INSERT INTO hashes (hash) VALUES " . implode(', ', $values) . " ON DUPLICATE KEY UPDATE hash = hash");
$q->execute($matches);

Der obige Code schlägt mit dem folgenden Fehler fehl

SQLSTATE[HY093]: Ungültige Parameternummer: Parameter wurde nicht definiert

Obwohl wann count($matches) == count($values) kurz bevor execute aufgerufen wird?

Was geht hier vor sich?

  • Haben Sie versucht, stattdessen array_values($matches) zu übergeben?

    – Jack

    10. Juni 2012 um 4:40 Uhr

  • Wieso den ON DUPLICATE KEY UPDATE hash = hash? Darf es auch INSERT IGNORE .... Wollten Sie tun UPDATE hash = VALUES(hash)?

    – eigelb

    10. Juni 2012 um 5:12 Uhr

  • Habe das gemacht $values Array enthält bereits etwas vor der Schleife? Warum bereiten Sie auch nicht eine Single vor? INSERT INTO hashes (hash) VALUES (?) und mehrfach ausführen?

    – eigelb

    10. Juni 2012 um 5:18 Uhr

  • @eggyal Ich füge ungefähr 1000 Werte ein und eine mehrfache Einfügung ist ungefähr 10 Mal schneller 🙂

    – Griff

    10. Juni 2012 um 16:09 Uhr

  • @Griff: Gilt das auch für den Fall, dass eine vorbereitete Anweisung mehrmals ausgeführt wird? Ich habe es nie selbst bewertet, aber immer verstanden, dass die Auswirkungen auf die Leistung vernachlässigbar sind …

    – eigelb

    10. Juni 2012 um 21:45 Uhr

Benutzer-Avatar
Harun

Dieser Fehler, den Sie erhalten, liegt daran, dass die Anzahl der Elemente in $values & $matches stimmt nicht überein.

Ob $values & $matches nicht die gleiche Anzahl von Elementen enthalten, schlägt die Einfügung fehl, da die Abfrage X-Parameter erwartet, aber Y-Daten empfängt $matches. In Ihrem Fall, $values enthält wahrscheinlich bereits einige Werte, was der Grund für die Zählabweichung ist. Um dies zu vermeiden, müssen Sie immer ein Array vor der Schleife initialisieren.

Ich glaube, Sie müssen auch sicherstellen, dass der Spalten-Hash auch einen eindeutigen Index hat.

$matches = array('1');
$count = count($matches);
$values = [];
for($i = 0; $i < $count; ++$i) {
    $values[] = '(?)';
}

// INSERT INTO DATABASE
$sql = "INSERT INTO hashes (hash) VALUES " . implode(', ', $values) . " ON DUPLICATE KEY UPDATE hash=values(hash)";
$stmt = $dbh->prepare($sql);
$data = $stmt->execute($matches);

  • Tolle Antwort, ich bin gerade darauf gestoßen, weil ich zwei Spalten mit derselben Kennung definiert habe – :exampledas sollte auch ein Punkt sein, auf den man achten sollte!

    – Darren

    22. Juni 2015 um 3:12 Uhr

  • Nur zum Hinzufügen, es könnte daran liegen, dass der Parameter, den Sie zu binden versuchen, einfach nicht existiert …

    – Victor H

    3. Dezember 2015 um 3:41 Uhr

  • @Darren – Du bist mein Lebensretter. In meinem bindParam-Aufruf, der in einer Foreach-Schleife ausgeführt wurde, hatte ich vergessen, den Schlüssel aus dem Array-Index einzufügen, also erhielt ich bindParam(‘:id’, ‘someValue’), bindParam(‘:id’, ‘someValue2’), .. .anstelle von bindParam(‘:id0’, ‘someValue’), bindParam(‘:id1’, ‘someValue’),… Ich hoffe, das hilft jemandem, sein Rätsel zu lösen

    – Erik Čerpnjak

    31. Mai 2016 um 22:11 Uhr


  • Ich glaube, Sie haben die Absicht des OP missverstanden. Er implodierte $count mal (?) -und nicht nur ?– mit , weil sowas INSERT INTO hashes(hash) VALUES('What'),('Terrible'),('Failure'); würde in SQL funktionieren, um 3 Zeileneinfügungen in einer Anweisung vorzunehmen. Ihre Antwort deutet auf etwas hin INSERT INTO hashes(hash) VALUES('What', 'Terrible' , 'Failure'); – eine Spalte referenzieren und 3 Werte für eine Zeile angeben! Das würde werfen Column count doesn't match value count Error- Wie konnte dies +45 positive Stimmen und die Zustimmung von OP erhalten? (Natürlich: “Du wirst es ein wenig anpassen müssen.” hast du gesagt…)

    – SebasSBM

    17. September 2019 um 9:31 Uhr


  • @SebasSBM das war genau mein Gedanke. Ich habe es bearbeitet, um es zumindest vernünftig zu machen. Gehen Sie in meine Sammlung von Stack Overflow WTFs. SO Abstimmung ist solch ein Geheimnis.

    – Ihr gesunder Menschenverstand

    30. April um 6:24 Uhr

Benutzer-Avatar
Danny F

SQLSTATE[HY093]: Ungültige Parameternummer: Parameter wurde nicht definiert

Leider ist dieser Fehler nicht beschreibend für eine Reihe verschiedener Probleme im Zusammenhang mit demselben Problem – ein Bindungsfehler. Es wird auch nicht angegeben, wo der Fehler liegt, und daher liegt Ihr Problem nicht unbedingt in der Ausführung, sondern in der bereits “vorbereiteten” SQL-Anweisung.

Dies sind die möglichen Fehler und ihre Lösungen:

  1. Es liegt ein Parameterkonflikt vor – die Anzahl der Felder stimmt nicht mit den gebundenen Parametern überein. Achten Sie auf Arrays in Arrays. Um es noch einmal zu überprüfen – verwenden var_dump($var). “print_r” zeigt Ihnen nicht unbedingt, ob der Index in einem Array ein anderes Array ist (wenn das Array einen Wert enthält), wohingegen var_dump Wille.

  2. Sie haben versucht, mit demselben Bindungswert zu binden, zum Beispiel: „:hash“ und „:hash“. Jeder Index muss eindeutig sein, auch wenn es logisch sinnvoll ist, denselben für zwei verschiedene Teile zu verwenden, selbst wenn es sich um denselben Wert handelt. (es ist ähnlich wie eine Konstante, aber eher wie ein Platzhalter)

  3. Wenn Sie mehr als einen Wert in einer Anweisung binden (wie es häufig bei einem “INSERT” der Fall ist), müssen Sie “bindParam” und dann “bindValue” an die Parameter binden. Der Prozess hier besteht darin, die Parameter an die Felder zu binden und dann die Werte an die Parameter zu binden.

     // Code snippet
     $column_names = array();
     $stmt->bindParam(':'.$i, $column_names[$i], $param_type);
     $stmt->bindValue(':'.$i, $values[$i], $param_type);
     $i++;
     //.....
    
  4. Wenn Sie den Backtick nicht konsequent verwenden, um Literale zu begrenzen, die Bezeichner (keine Zeichenfolgen) darstellen. (Verwenden von “), aber sobald Sie sie verwenden, müssen Sie für diese Abfrage konsistent sein, dh Sie können keine Backticks für einen Bezeichner und nicht für einen anderen verwenden, alle müssen Backticks haben, wenn Sie sie verwenden. (zB WÄHLEN id AUS my_table) Verwenden Sie keine Backticks für Platzhalter

  5. Jeder Wert in einfachen Anführungszeichen wird immer als Zeichenfolgenliteral behandelt und nicht als Spalten-/Tabellenname oder Platzhalter zum Binden gelesen.

  • Danke, dass Sie Grund Nr. 2 haben, ich war verblüfft, bis ich das hier gefunden habe.

    Benutzer3277192

    10. März 2018 um 1:24 Uhr

  • Und Ihre ursprüngliche Version war auch falsch. Du kann nicht Werte an Spaltennamen binden

    – Ihr gesunder Menschenverstand

    1. Mai um 14:36 ​​Uhr

  • Falls Sie glauben, dass Sie so etwas tun können, WHERE ` :column ` =1 , es wird nicht funktionieren. Beachten Sie das doppelte ” in der Fehlermeldung um die ID herum. PDO fügt Werten Anführungszeichen hinzu, wodurch der Dateiname buchstäblich wird 'id'. Das bedeutet, dass Sie keine Platzhalter für Spaltennamen verwenden können. Backticks haben absolut nichts mit Platzhaltern zu tun und können in keiner Weise mit Platzhaltern verwendet werden, weder als Teil des Namens noch als Umgebung. Bitte verbreiten Sie keine irreführenden Informationen.

    – Ihr gesunder Menschenverstand

    2. Mai um 4:25


  • Keine Ahnung wo du es her hast aber Sie können Backticks inkonsistent verwenden, wo immer Sie wollen sogar für einen einzelnen Spaltennamen. Außerdem hat dieses ganze Backtick-Geschäft absolut nichts damit zu tun Frage, die Sie zu beantworten versuchen. Die Frage bezieht sich auf Platzhalter, nicht auf Backticks.

    – Ihr gesunder Menschenverstand

    2. Mai um 16:29 Uhr


  • Und mir ist gerade aufgefallen, #3 macht auch keinen Sinn. Wie wir bereits gelernt haben, kann kein Spaltenname gebunden werden, daher ist es schwer zu sagen, wovon Sie sprechen. Ganz zu schweigen davon, dass es kein solches Problem gibt, das durch Verschachtelung von bindParam und bindValue gelöst werden kann. Sie können eine oder beide verwenden. Und beides würde den Fehler „Ungültige Parameternummer“ nicht verursachen. Die gesamte Anweisung “die Parameter an die Felder zu binden und dann die Werte an die Parameter zu binden” ist ein glasklarer Unsinn.

    – Ihr gesunder Menschenverstand

    2. Mai um 16:38 Uhr


Benutzer-Avatar
Hannah

Ich hatte den gleichen Fehler, nachdem ich beim Binden den falschen Parameternamen verwendet hatte.

Notiz :tokenHash in dem VALUES Klausel der Abfrage, aber :token_hash beim Binden.

Das Beheben des einen oder anderen hat den Fehler behoben.

// Prepare DB connection
$sql="INSERT INTO rememberedlogins (token_hash,user_id,expires_at)
        VALUES (:tokenHash,:user_id,:expires_at)";
$db = static::getDB();
$stmt = $db->prepare($sql);

// Bind values
$stmt->bindValue(':token_hash',$hashed_token,PDO::PARAM_STR);

Derselbe Fehler, den ich gefunden habe, wird angezeigt, wenn der Spaltenname in PHP und der Datenbankspaltenname nicht übereinstimmen. Überprüfen Sie das auch. Das ist, was ich falsch gemacht habe.

Ich verstehe, dass die Antwort nützlich war, aber aus irgendeinem Grund funktioniert sie bei mir nicht, aber ich habe die Situation mit dem folgenden Code verschoben und sie ist perfekt

    <?php

$codigoarticulo = $_POST['codigoarticulo'];
$nombrearticulo = $_POST['nombrearticulo'];
$seccion        = $_POST['seccion'];
$precio         = $_POST['precio'];
$fecha          = $_POST['fecha'];
$importado      = $_POST['importado'];
$paisdeorigen   = $_POST['paisdeorigen'];
try {

  $server="mysql: host=localhost; dbname=usuarios";
  $user="root";
  $pass="";
  $base   = new PDO($server, $user, $pass);

  $base->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

  $base->query("SET character_set_results="utf8",
                     character_set_client="utf8",
                     character_set_connection = 'utf8',
                     character_set_database="utf8",
                     character_set_server="utf8"");

  $base->exec("SET character_set_results="utf8",
                     character_set_client="utf8",
                     character_set_connection = 'utf8',
                     character_set_database="utf8",
                     character_set_server="utf8"");

  $sql = "
  INSERT INTO productos
  (CÓDIGOARTÍCULO, NOMBREARTÍCULO, SECCIÓN, PRECIO, FECHA, IMPORTADO, PAÍSDEORIGEN)
  VALUES
  (:c_art, :n_art, :sec, :pre, :fecha_art, :import, :p_orig)";
// SE ejecuta la consulta ben prepare
  $result = $base->prepare($sql);
//  se pasan por parametros aqui
  $result->bindParam(':c_art', $codigoarticulo);
  $result->bindParam(':n_art', $nombrearticulo);
  $result->bindParam(':sec', $seccion);
  $result->bindParam(':pre', $precio);
  $result->bindParam(':fecha_art', $fecha);
  $result->bindParam(':import', $importado);
  $result->bindParam(':p_orig', $paisdeorigen);
  $result->execute();
  echo 'Articulo agregado';
} catch (Exception $e) {

  echo 'Error';
  echo $e->getMessage();
} finally {

}

?>

1012150cookie-checkFehler beim Vorbereiten einer Multiple-Insert-Abfrage

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy