“无效参数编号:未定义参数” 插入数据
Posted
技术标签:
【中文标题】“无效参数编号:未定义参数” 插入数据【英文标题】:"Invalid parameter number: parameter was not defined" Inserting data 【发布时间】:2011-08-17 23:29:21 【问题描述】:我使用 Yii 的主动记录模式已经有一段时间了。现在,我的项目需要为一笔小交易访问不同的数据库。我认为 Yii 的 DAO 会对此有好处。但是,我遇到了一个神秘的错误。
CDbCommand 执行 SQL 语句失败:SQLSTATE[HY093]: Invalid parameter number: parameter was not defined
这是我的代码:
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);
仅供参考$model->placeOfBirth
应该是城市和县的值。这不是错字(只是我必须做的一件愚蠢的事情)。
【问题讨论】:
【参考方案1】:只是为了提供一个答案 - 因为这个错误很常见 - 这里有几个原因:
1) :parameter
名称与错误绑定不匹配(错字?)。这就是这里发生的事情。他在 SQL 语句中有:alias
,但绑定了:username
。所以当尝试绑定参数时,Yii/PDO 在 sql 语句中找不到:username
,这意味着它是“一个参数短”并抛出错误。
2) 完全忘记为参数添加bindValue()
。这在 Yii 的其他结构中更容易做到,比如 $critera
,你有一个数组或参数 ($criteria->params = array(':bind1'=>'test', ':bind2'=>'test)
)。
3) 使用 together
和 joins
时与 CDataProvider 分页和/或排序发生奇怪的冲突。没有具体、简单的方法来描述这一点,但是在 CDataProviders 中使用复杂查询时,我遇到了一些奇怪的问题,即参数被丢弃并发生此错误。
在 Yii 中解决这些问题的一个非常有用的方法是在你的配置文件中 enable parameter logging。将此添加到配置文件中的 db
数组中:
'enableParamLogging'=>true,
并确保在您的log
部分中设置了CWebLogRoute
路由。这将打印出给出和错误的查询,以及它试图绑定的所有参数。超级有用!
【讨论】:
好帖子。我在我的实例中发现,在其中一个 col 名称之后有一个空格,这足以引发错误。 有效占位符列表***.com/questions/5809951/… 我的也是绑定调用中一个列名后面的空格,很难发现【参考方案2】:可能是您尝试将参数绑定在单引号内,而不是让它为您工作。
比较:
Model::model()->findAll("t.description ilike '%:filter%'", array(':filter' => $filter));
与:
Model::model()->findAll("t.description ilike :filter", array(':filter' => '%' . $filter . '%'));
【讨论】:
【参考方案3】:对我来说,上面没有提到的这个错误的原因是当你处理一个动态的参数数组时,如果你取消设置任何参数,你需要在传递它们之前重新索引。这其中残酷的部分是你的错误日志不显示索引,所以看起来一切都是正确的。例如:
SELECT id WHERE x = ?, y = ?, z = ?
可能会产生日志:参数编号无效:参数未使用参数定义 ("x","y","z")
这看起来不应该抛出错误,但如果索引是这样的:
0 => x, 1 => y, 4 => z
它认为最后一个参数未定义,因为它正在寻找键 2。
【讨论】:
在您的答案中添加一个简单的 print_r 将显示索引并且可以使用 array_values 修复,因为它将重新索引从 0 开始的数组【参考方案4】:尝试执行以下操作时出现此错误:
$stmt = $pdo->prepare("select name from mytable where id = :id");
$stmt->execute([
'id' => $id,
'unusedvar' => $foo, // This row causes the error.
]);
基本上,您不能将数组中未使用的参数传递给execute()
。传递给execute()
的数组中的每个值都必须在您准备好的语句中使用。
这也在docs中指定:
无法绑定比指定更多的值;如果 input_parameters 中存在的键多于 PDO::prepare() 中指定的 SQL 中的键,则语句将失败并发出错误。
【讨论】:
以上是关于“无效参数编号:未定义参数” 插入数据的主要内容,如果未能解决你的问题,请参考以下文章