Yii2 插入忽略/插入重复项
Yii2 Insert Ignore / Insert duplicates
我对 Yii2 比较陌生,但到目前为止我非常喜欢它。
然而,我发现了一个与数据库插入相关的问题,更具体地说 MySQL.
问题很简单:我正在将值插入 table 中,我需要检查重复项,所以我的想法是使用 INSERT IGNORE 或关于重复密钥更新。
这是我用于插入的代码:
$db->createCommand()
->insert('sdg_fb_apps', [
'fb_id' => $app->id,
'page_id' => $page_id,
'name' => $app->name,
'app_id' => $app_id,
'app_name' => $app_name,
])
->execute();
我必须使用唯一键:id 和 app_id,如果我 运行 这段代码,我显然会从 Yii 中抛出异常。
有这个扩展,但据我所知只适用于 Yii 1.0:http://www.yiiframework.com/extension/rdbcommand
我还在 GitHub 上找到了如下代码片段:
class MyQueryBuilder extends yii\db\mysql\QueryBuilder
{
public function batchInsert($table, $columns, $rows)
{
$sql = parent::batchInsert($table, $columns, $rows);
$sql .= 'ON DUPLICATE KEY UPDATE';
return $sql;
}
}
我不明白如何扩展 Querybuilder,可以通过组件吗?
我通过查询查看 app_id 之前是否已经在数据库中,然后仅在它们不存在时才插入,但是这应该有扩展到巨大的数字,这种方法可能不是最好的。
任何指导将不胜感激,提前致谢。
有很多事情需要考虑,可能还有更好的方法来完成您的任务,但最直接的答案(根据您提供的信息)是扩展 QueryBuilder。
简单地创建一个具有适当命名空间的应用程序组件,并如上所示扩展 QueryBuilder。
如果您将 ActiveRecord 模型与 table 一起使用,而不是直接执行 sql 命令,则还有其他方法可以实现您想要的目标。
一年多过去了,我在这里找到了这个悬而未决的问题。我看到这有一些牵引力,所以最好添加一个正确的答案。
在 Yii2 中,思路是找到模型,检查是否存在,然后保存。该框架将自动更新或插入,这是我从 Viewlike.us - Yii2 Insert and Ignore duplicates:
获得的片段
$model = YourModel::findOne(ID); // findOne() searches for the table key, you can use find()->where('=', 'column', 'name')->one(); to identify the model.
if(!$model):
$model = new YourModel();
endif;
$model->column_1 = 'text';
$model->column_2 = 123; // integer
$model->save();
你的问题的关键是方法 $db->createCommand()。它在内部使用 $commandClass public 属性,默认情况下是 yii\db\Command。您可以在您的应用程序配置中更改它以覆盖 batchInsert() 等命令方法。以下是我的应用程序的示例:
'db' => [
'class' => 'yii\db\Connection',
'charset' => 'utf8',
'enableSchemaCache' => YII_ENV_PROD,
'commandClass' => 'app\db\MyCommand'
],
您的命令 class 可能如下所示:
class MyCommand extends yii\db\Command
{
public function batchInsert($table, $columns, $rows)
{
parent::batchInsert($table, $columns, $rows);
$sql = $this->getRawSql();
$sql .= ' ON DUPLICATE KEY UPDATE';
$this->setRawSql($sql);
return $this;
}
}
但我宁愿介绍单独的方法,例如batchInsertUpdate() 之类的。
从 Yii 2.0.14 开始,有一个 upsert()
方法可以用于此。
$db->createCommand()
->upsert(
'sdg_fb_apps',
[
'fb_id' => $app->id,
'page_id' => $page_id,
'name' => $app->name,
'app_id' => $app_id,
'app_name' => $app_name,
],
false
)
->execute();
对于Yii 1(Yii 2应该类似)我继承了CActiveRecord然后我把插入函数复制到insertIgnoreDuplicates,
我在 createInsertCommand 调用后做了以下更改:
/**
* Inserts ignore duplicates a row into the table based on this active record attributes.
* If the table's primary key is auto-incremental and is null before insertion,
* it will be populated with the actual value after insertion.
* Note, validation is not performed in this method. You may call {@link validate} to perform the validation.
* After the record is inserted to DB successfully, its {@link isNewRecord} property will be set false,
* and its {@link scenario} property will be set to be 'update'.
* @param array $attributes list of attributes that need to be saved. Defaults to null,
* meaning all attributes that are loaded from DB will be saved.
* @return boolean whether the attributes are valid and the record is inserted successfully.
* @throws CDbException if the record is not new
*/
public function insertIgnoreDuplicates($attributes = null)
{
try {
return $this->insert($attributes);
} catch (CDbException $ex) {
if ($ex->code == 23000) // ignore duplicated key
{
} else {
throw $ex;
}
}
}
用法:
$x = new record();
$x->attr1 = 'val';
$x->insertIgnoreDuplicates();
我对 Yii2 比较陌生,但到目前为止我非常喜欢它。 然而,我发现了一个与数据库插入相关的问题,更具体地说 MySQL.
问题很简单:我正在将值插入 table 中,我需要检查重复项,所以我的想法是使用 INSERT IGNORE 或关于重复密钥更新。
这是我用于插入的代码:
$db->createCommand()
->insert('sdg_fb_apps', [
'fb_id' => $app->id,
'page_id' => $page_id,
'name' => $app->name,
'app_id' => $app_id,
'app_name' => $app_name,
])
->execute();
我必须使用唯一键:id 和 app_id,如果我 运行 这段代码,我显然会从 Yii 中抛出异常。
有这个扩展,但据我所知只适用于 Yii 1.0:http://www.yiiframework.com/extension/rdbcommand
我还在 GitHub 上找到了如下代码片段:
class MyQueryBuilder extends yii\db\mysql\QueryBuilder
{
public function batchInsert($table, $columns, $rows)
{
$sql = parent::batchInsert($table, $columns, $rows);
$sql .= 'ON DUPLICATE KEY UPDATE';
return $sql;
}
}
我不明白如何扩展 Querybuilder,可以通过组件吗?
我通过查询查看 app_id 之前是否已经在数据库中,然后仅在它们不存在时才插入,但是这应该有扩展到巨大的数字,这种方法可能不是最好的。
任何指导将不胜感激,提前致谢。
有很多事情需要考虑,可能还有更好的方法来完成您的任务,但最直接的答案(根据您提供的信息)是扩展 QueryBuilder。
简单地创建一个具有适当命名空间的应用程序组件,并如上所示扩展 QueryBuilder。
如果您将 ActiveRecord 模型与 table 一起使用,而不是直接执行 sql 命令,则还有其他方法可以实现您想要的目标。
一年多过去了,我在这里找到了这个悬而未决的问题。我看到这有一些牵引力,所以最好添加一个正确的答案。
在 Yii2 中,思路是找到模型,检查是否存在,然后保存。该框架将自动更新或插入,这是我从 Viewlike.us - Yii2 Insert and Ignore duplicates:
获得的片段$model = YourModel::findOne(ID); // findOne() searches for the table key, you can use find()->where('=', 'column', 'name')->one(); to identify the model. if(!$model): $model = new YourModel(); endif; $model->column_1 = 'text'; $model->column_2 = 123; // integer $model->save();
你的问题的关键是方法 $db->createCommand()。它在内部使用 $commandClass public 属性,默认情况下是 yii\db\Command。您可以在您的应用程序配置中更改它以覆盖 batchInsert() 等命令方法。以下是我的应用程序的示例:
'db' => [
'class' => 'yii\db\Connection',
'charset' => 'utf8',
'enableSchemaCache' => YII_ENV_PROD,
'commandClass' => 'app\db\MyCommand'
],
您的命令 class 可能如下所示:
class MyCommand extends yii\db\Command
{
public function batchInsert($table, $columns, $rows)
{
parent::batchInsert($table, $columns, $rows);
$sql = $this->getRawSql();
$sql .= ' ON DUPLICATE KEY UPDATE';
$this->setRawSql($sql);
return $this;
}
}
但我宁愿介绍单独的方法,例如batchInsertUpdate() 之类的。
从 Yii 2.0.14 开始,有一个 upsert()
方法可以用于此。
$db->createCommand()
->upsert(
'sdg_fb_apps',
[
'fb_id' => $app->id,
'page_id' => $page_id,
'name' => $app->name,
'app_id' => $app_id,
'app_name' => $app_name,
],
false
)
->execute();
对于Yii 1(Yii 2应该类似)我继承了CActiveRecord然后我把插入函数复制到insertIgnoreDuplicates, 我在 createInsertCommand 调用后做了以下更改:
/**
* Inserts ignore duplicates a row into the table based on this active record attributes.
* If the table's primary key is auto-incremental and is null before insertion,
* it will be populated with the actual value after insertion.
* Note, validation is not performed in this method. You may call {@link validate} to perform the validation.
* After the record is inserted to DB successfully, its {@link isNewRecord} property will be set false,
* and its {@link scenario} property will be set to be 'update'.
* @param array $attributes list of attributes that need to be saved. Defaults to null,
* meaning all attributes that are loaded from DB will be saved.
* @return boolean whether the attributes are valid and the record is inserted successfully.
* @throws CDbException if the record is not new
*/
public function insertIgnoreDuplicates($attributes = null)
{
try {
return $this->insert($attributes);
} catch (CDbException $ex) {
if ($ex->code == 23000) // ignore duplicated key
{
} else {
throw $ex;
}
}
}
用法:
$x = new record();
$x->attr1 = 'val';
$x->insertIgnoreDuplicates();