web-dev-qa-db-fra.com

SQLSTATE [HY093]: Numéro de paramètre non valide: le paramètre n'a pas été défini

// 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);

Le code ci-dessus échoue avec l'erreur suivante

SQLSTATE [HY093]: Numéro de paramètre non valide: le paramètre n'a pas été défini

Bien que lorsque count($matches) == count($values) juste avant l'exécution soit appelée?

Qu'est-ce qui se passe ici?

29
Griff

Cette erreur que vous recevez:

SQLSTATE [HY093]: Numéro de paramètre non valide: le paramètre n'a pas été défini

est parce que le nombre d'éléments dans $values & $matches n'est pas le même ou $matches contient plus d'un élément.

Si $matches contient plus de 1 élément, l'insertion échouera, car il n'y a qu'un seul nom de colonne référencé dans la requête (hash)

Si $values & $matches ne contient pas le même nombre d'éléments, l'insertion échouera également, car la requête attend x params mais reçoit des données y $matches.

Je pense que vous devrez également vous assurer que le hachage de la colonne possède également un index unique.

Essayez le code ici :

<?php

/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'root';

/*** mysql password ***/
$password = '';

try {
    $dbh = new PDO("mysql:Host=$hostname;dbname=test", $username, $password);
    /*** echo a message saying we have connected ***/
    echo 'Connected to database';
    }
catch(PDOException $e)
    {
    echo $e->getMessage();
    }


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

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

//Error reporting if something went wrong...
var_dump($dbh->errorInfo());

?>

Vous devrez l'adapter un peu.

La structure de table que j'ai utilisée est ici :

CREATE TABLE IF NOT EXISTS `hashes` (
  `hashid` int(11) NOT NULL AUTO_INCREMENT,
  `hash` varchar(250) NOT NULL,
  PRIMARY KEY (`hashid`),
  UNIQUE KEY `hash1` (`hash`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

Le code a été exécuté sur mon serveur XAMPP qui utilise PHP 5.3.8 avec MySQL 5.5.16.

J'espère que ça aide.

45
Haroon

SQLSTATE [HY093]: Numéro de paramètre non valide: le paramètre n'a pas été défini

Malheureusement, cette erreur n'est pas descriptive pour une gamme de problèmes différents liés au même problème - une erreur de liaison. Il ne spécifie pas non plus où se trouve l'erreur, et donc votre problème n'est pas nécessairement dans l'exécution, mais dans l'instruction sql qui était déjà "préparée".

Ce sont les erreurs possibles et leurs solutions:

  1. Il existe une incompatibilité de paramètres - le nombre de champs ne correspond pas aux paramètres qui ont été liés. Méfiez-vous des tableaux dans les tableaux. Pour revérifier - utilisez var_dump ($ var) . " print_r " ne vous montre pas nécessairement si l'index dans un tableau est un autre tableau (si le tableau contient une valeur), tandis que var_dump le fera.

  2. Vous avez essayé de lier en utilisant la même valeur de liaison, par exemple: ": hachage" et ": hachage". Chaque index doit être unique, même si, logiquement, il est logique de l'utiliser pour deux parties différentes, même s'il s'agit de la même valeur. (il est similaire à une constante mais ressemble plus à un espace réservé)

  3. Si vous liez plusieurs valeurs dans une instruction (comme c'est souvent le cas avec un "INSERT"), vous devez lierParam puis lierValeur aux paramètres. Le processus ici consiste à lier les paramètres aux champs, puis à lier les valeurs aux paramètres.

    // Code snippet
    $column_names = array();
    $stmt->bindParam(':'.$i, $column_names[$i], $param_type);
    $stmt->bindValue(':'.$i, $values[$i], $param_type);
    $i++;
    //.....
    
  4. Lorsque vous liez des valeurs à column_names ou table_names, vous pouvez utiliser `` mais ce n'est pas nécessaire, mais assurez-vous d'être cohérent.

  5. Toute valeur entre guillemets simples est toujours traitée comme une chaîne et ne sera pas lue comme un nom de colonne/table ou un espace réservé auquel se lier.

5
Danny F