2011-05-03 71 views
28

UPDATE“无效参数号:没有定义参数的”插入数据

我正在一个小错误列出值时,。我应该把“:用户名”,而不是“:别名”。我想这个问题的答案是对任何需要它的人来说是免费的吗?或者我删除这个问题?

ORIGINAL

我一直在使用Yii的活动记录图形一会儿。现在,我的项目需要为一个小事务访问不同的数据库。我认为Yii的DAO对此会有好处。但是,我收到了一个神秘的错误。

CDbCommand未能执行SQL语句:SQLSTATE [HY093]:无效的参数号:没有定义的参数

这里是我的代码:

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

此构造下面的查询(如在应用日志中所见):

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

FYI $model->placeOfBirth应该是城市和县的价值。这不是一个错字(只是我必须做的一件愚蠢的事情)。

回答

73

只是提供一个答案 - 因为这个错误是很常见的 - 这里有几个原因:

1):parameter名称不匹配错误(错字绑定)?这是发生在这里的事情。他在SQL语句中有:alias,但是绑定了:username。因此,当试图绑定param时,Yii/PDO在sql语句中找不到:username,这意味着它是“一个参数短”并引发错误。

2)完全忘记为参数添加bindValue()。在Yii其他构造如$critera中这样做更容易,其中您有一个数组或参数($criteria->params = array(':bind1'=>'test', ':bind2'=>'test))。

3)使用togetherjoins时与CDataProvider分页和/或排序有奇怪的冲突。没有特别的,简单的方法来描述这一点,但是当在CDataProviders中使用复杂的查询时,我遇到了一些奇怪的问题,因为参数被丢弃并且发生这个错误。

解决Yii中这些问题的一个非常有用的方法是在配置文件中输入enable parameter logging。在您的配置文件添加到您的db阵列:

'enableParamLogging'=>true, 

,并确保CWebLogRoute路线是建立在你的log部分。这将打印输出的查询和错误,以及它试图绑定的所有参数。超级有用!

+4

好帖子。我发现在我的实例中,我在col列名之后有一个空格,并且足以引发错误。 – salonMonsters 2011-12-19 23:52:46

+4

我的问题是':参数'名称中的变音符号... – testing 2012-08-31 13:37:12

+1

这里有效的占位符字符列表http://stackoverflow.com/questions/5809951/pdo-valid-characters-for-placeholders – maartenmachiels 2013-07-08 12:04:39

4

也许你正在尝试在单引号内绑定一个参数,而不是让它为你完成工作。

比较:

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

有了:

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

此错误的原因我上面没有覆盖的是当你与参数的动态数组处理,如果你取消设置任何参数,可以在传递它们之前,你需要重新索引。这个残酷的部分是你的错误日志不显示索引,所以它看起来像一切都是正确的。例如:

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

可能会产生的日志:无效参数数:参数没有被使用参数(“X”,“Y”,“Z”)

这看起来像它不应该被限定抛一个错误,但如果索引是这样的:

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

它认为最后的参数不确定,因为它在寻找关键2.

+1

向您的答案添加一个简单的print_r将显示索引,并且可以使用array_values修复它,因为它会重新索引从0开始的数组 – chifliiiii 2016-09-06 17:28:31

0

试图做这样的事情,当我得到这个错误:

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

基本上,您不能将数组中未使用的参数传递给​​。在准备好的声明中必须使用传递给​​的数组中的每个值。

这在docs还指定:小于指定

结合更多的值是不可能的;如果input_parameters中的键比PDO :: prepare()中指定的SQL更多,那么语句将失败并发出错误。

相关问题