web-dev-qa-db-fra.com

"Numéro de paramètre non valide: le paramètre n'a pas été défini" Insertion de données

MISE À JOUR

Je faisais une petite erreur en listant les VALEURS. J'aurais dû mettre ": nom d'utilisateur" et non ": alias". Je suppose que le crédit de réponse à cette question est libre pour quiconque le veut? Ou dois-je supprimer la question?

ORIGINAL

J'utilise le modèle d'enregistrement actif de Yii depuis un certain temps. Maintenant, mon projet doit accéder à une base de données différente pour une petite transaction. Je pensais que le DAO du Yii serait bon pour cela. Cependant, je reçois une erreur cryptique.

CDbCommand n'a pas réussi à exécuter l'instruction SQL: SQLSTATE [HY093]: numéro de paramètre non valide: le paramètre n'a pas été défini

Voici mon code:

public function actionConfirmation
{
    $model_person = new TempPerson();

    $model = $model_person->find('alias=:alias',array(':alias'=>$_GET['alias']));
    $connection=Yii::app()->db2;
            $sql = "INSERT INTO users (username, password, ssn, surname
                    , firstname, email, city, country) 
                    VALUES(:alias, :password, :ssn, :surname
                    , :firstname, :email, :city, :country)";
            $command=$connection->createCommand($sql);
            $command->bindValue(":username", $model->alias);
            $command->bindValue(":password", substr($model->ssn, -4,4));
            $command->bindValue(":ssn", $model->ssn);
            $command->bindValue(":surname", $model->lastName);
            $command->bindValue(":firstname", $model->firstName);
            $command->bindValue(":email", $model->email);
            $command->bindValue(":city", $model->placeOfBirth);
            $command->bindValue(":country", $model->placeOfBirth);
            $command->execute();
            $this->render('confirmation',array('model'=>$model));
}

Cela construit la requête suivante (comme indiqué dans le journal des applications):

INSERT INTO users (username, password, ssn, surname, firstname, email
                   , city, country) 
VALUES(:alias, :password, :ssn, :surname, :firstname, :email, :city, :country);

FYI $model->placeOfBirth est censé correspondre aux valeurs de la ville et du comté. Ce n'est pas une faute de frappe (juste une chose idiote que je dois faire).

38
k to the z

Juste pour fournir une réponse - car cette erreur est assez courante - voici quelques causes:

1) Le nom :parameter Ne correspond pas à la liaison par erreur (faute de frappe?). C'est ce qui s'est passé ici. Il a :alias Dans l'instruction SQL, mais lié :username. Ainsi, lorsque la liaison param a été tentée, Yii/PDO n'a pas pu trouver :username Dans l'instruction sql, ce qui signifie qu'il s'agissait d'un "paramètre court" et a généré une erreur.

2) Oubliant complètement d'ajouter la bindValue() pour un paramètre. C'est plus facile à faire dans Yii d'autres constructions comme $critera, Où vous avez un tableau ou des paramètres ($criteria->params = array(':bind1'=>'test', ':bind2'=>'test)).

3) Conflits étranges avec la pagination et/ou le tri de CDataProvider lors de l'utilisation de together et joins. Il n'y a pas de moyen spécifique et facile de caractériser cela, mais lors de l'utilisation de requêtes complexes dans CDataProviders, j'ai eu des problèmes étranges avec la suppression des paramètres et cette erreur.

Un moyen très utile de résoudre ces problèmes dans Yii consiste à activer la journalisation des paramètres dans votre fichier de configuration. Ajoutez ceci à votre tableau db dans votre configuration fichier:

'enableParamLogging'=>true,

Et assurez-vous que la route CWebLogRoute est configurée dans votre section log. Cela affichera la requête qui a donné et l'erreur, et tous les paramètres qu'il tentait de lier. Super utile!

91
thaddeusmt

Une cause de cette erreur pour moi non couverte ci-dessus est lorsque vous avez affaire à un tableau dynamique de paramètres si vous ne définissez aucun paramètre, vous devez réindexer avant de les transmettre. La partie brutale de cela est que votre journal des erreurs ne afficher les index de sorte qu'il semble que tout va bien. Par exemple:

SELECT id WHERE x = ?, y = ?, z = ?

Pourrait produire le journal: Numéro de paramètre non valide: le paramètre n'a pas été défini avec des paramètres ("x", "y", "z")

Il semble que cela ne devrait pas générer d'erreur, mais si les index sont quelque chose comme:

0 => x, 1 => y, 4 => z

Il considère le dernier paramètre non défini car il recherche la clé 2.

4
jtubre

Vous essayez peut-être de lier un paramètre entre guillemets simples au lieu de le laisser faire le travail pour vous.

Comparer:

Model::model()->findAll("t.description ilike '%:filter%'", array(':filter' => $filter));

Avec:

Model::model()->findAll("t.description ilike :filter", array(':filter' => '%' . $filter . '%'));
4
Alan Willms

J'ai eu cette erreur en essayant de faire quelque chose comme:

$stmt = $pdo->prepare("select name from mytable where id = :id");
$stmt->execute([
  'id' => $id,
  'unusedvar' => $foo, // This row causes the error.
]);

Fondamentalement, vous ne pouvez pas avoir de paramètres inutilisés dans le tableau passés à execute(). Chaque valeur du tableau passée à execute() doit être utilisée dans votre instruction préparée.

Ceci est également spécifié dans le docs :

Il n'est pas possible de lier plus de valeurs que spécifié; s'il existe plus de clés dans les paramètres d'entrée que dans le SQL spécifié dans PDO :: prepare (), l'instruction échouera et une erreur sera émise.

2
Lars Nyström