我有这段代码,可以在第一时间插入数组,但在尝试替换和更新时,会返回错误
完整性约束违规:1062复合键重复输入['periodo_id','asociado_id']
型号:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Lectura extends Model
{
protected $primaryKey = array('periodo_id', 'asociado_id');
public $timestamps = false;
public $incrementing = false;
}
和控制器:
$rows = DB::table('lecturas_temp')->get();
$arr = array();
foreach ($rows as $row) {
$a = [
'asociado_id' => $row->asociado_id,
'periodo_id' => $request->periodo_id,
'nombre' => $row->nombre,
];
array_push($arr, $a);
}
DB::table('lecturas')->insert($arr);
行DB::table('lecturas')->insert($arr)
的其他替代方法?
我尝试了Eloquent Lectura::insert($arr)
和updateOrCreate
但结果相同;
答案 0 :(得分:1)
错误信息非常明确。您正在使用复合键['periodo_id', 'asociado_id']
,这意味着您无法插入相同的数据两次,因为您将其定义为主键。
如果您希望复制密钥重复,请将其从模型中删除为主键。但是,如果您希望数据是唯一的,则应使用updateOrCreate()
。
$rows = DB::table('lecturas_temp')->get();
$arr = array();
foreach ($rows as $row) {
Lectura::updateOrCreate(
[
'asociado_id' => $row->asociado_id,
'periodo_id' => $request->periodo_id
],
[
'nombre' => $row->nombre
]
);
}
如您所见,updateOrCreate()
将2个数组作为参数。第一个数组是用于验证它是否已存在的元素。此外,不幸的是,您将不得不逐一进行,而不是像往常一样。
如果您想坚持使用查询构建器,可以使用DB::updateOrInsert()
,使用相同的调用签名(传递2个数组)。
答案 1 :(得分:0)
使用此代码我解决了:https://github.com/yadakhov/insert-on-duplicate-key
class Lectura extends Model
{
protected $primaryKey = array('periodo_id', 'asociado_id');
public $timestamps = false;
public $incrementing = false;
public static function insertOnDuplicateKey(array $data, array $updateColumns = null)
{
if (empty($data)) {
return false;
}
// Case where $data is not an array of arrays.
if (!isset($data[0])) {
$data = [$data];
}
$sql = static::buildInsertOnDuplicateSql($data, $updateColumns);
$data = static::inLineArray($data);
return self::getModelConnectionName()->affectingStatement($sql, $data);
}
/**
* Insert using mysql INSERT IGNORE INTO.
*
* @param array $data
*
* @return int 0 if row is ignored, 1 if row is inserted
*/
public static function insertIgnore(array $data)
{
if (empty($data)) {
return false;
}
// Case where $data is not an array of arrays.
if (!isset($data[0])) {
$data = [$data];
}
$sql = static::buildInsertIgnoreSql($data);
$data = static::inLineArray($data);
return self::getModelConnectionName()->affectingStatement($sql, $data);
}
/**
* Insert using mysql REPLACE INTO.
*
* @param array $data
*
* @return int 1 if row is inserted without replacements, greater than 1 if rows were replaced
*/
public static function replace(array $data)
{
if (empty($data)) {
return false;
}
// Case where $data is not an array of arrays.
if (!isset($data[0])) {
$data = [$data];
}
$sql = static::buildReplaceSql($data);
$data = static::inLineArray($data);
return self::getModelConnectionName()->affectingStatement($sql, $data);
}
/**
* Static function for getting table name.
*
* @return string
*/
public static function getTableName()
{
$class = get_called_class();
return (new $class())->getTable();
}
/**
* Static function for getting connection name
*
* @return string
*/
public static function getModelConnectionName()
{
$class = get_called_class();
return (new $class())->getConnection();
}
/**
* Get the table prefix.
*
* @return string
*/
public static function getTablePrefix()
{
return self::getModelConnectionName()->getTablePrefix();
}
/**
* Static function for getting the primary key.
*
* @return string
*/
public static function getPrimaryKey()
{
$class = get_called_class();
return (new $class())->getKeyName();
}
/**
* Build the question mark placeholder. Helper function for insertOnDuplicateKeyUpdate().
* Helper function for insertOnDuplicateKeyUpdate().
*
* @param $data
*
* @return string
*/
protected static function buildQuestionMarks($data)
{
$lines = [];
foreach ($data as $row) {
$count = count($row);
$questions = [];
for ($i = 0; $i < $count; ++$i) {
$questions[] = '?';
}
$lines[] = '(' . implode(',', $questions) . ')';
}
return implode(', ', $lines);
}
/**
* Get the first row of the $data array.
*
* @param array $data
*
* @return mixed
*/
protected static function getFirstRow(array $data)
{
if (empty($data)) {
throw new \InvalidArgumentException('Empty data.');
}
list($first) = $data;
if (!is_array($first)) {
throw new \InvalidArgumentException('$data is not an array of array.');
}
return $first;
}
/**
* Build a value list.
*
* @param array $first
*
* @return string
*/
protected static function getColumnList(array $first)
{
if (empty($first)) {
throw new \InvalidArgumentException('Empty array.');
}
return '`' . implode('`,`', array_keys($first)) . '`';
}
/**
* Build a value list.
*
* @param array $first
*
* @return string
*/
protected static function buildValuesList(array $first)
{
$out = [];
foreach (array_keys($first) as $key) {
$out[] = sprintf('`%s` = VALUES(`%s`)', $key, $key);
}
return implode(', ', $out);
}
/**
* Inline a multiple dimensions array.
*
* @param $data
*
* @return array
*/
protected static function inLineArray(array $data)
{
return call_user_func_array('array_merge', array_map('array_values', $data));
}
/**
* Build the INSERT ON DUPLICATE KEY sql statement.
*
* @param array $data
* @param array $updateColumns
*
* @return string
*/
protected static function buildInsertOnDuplicateSql(array $data, array $updateColumns = null)
{
$first = static::getFirstRow($data);
$sql = 'INSERT INTO `' . static::getTablePrefix() . static::getTableName() . '`(' . static::getColumnList($first) . ') VALUES' . PHP_EOL;
$sql .= static::buildQuestionMarks($data) . PHP_EOL;
$sql .= 'ON DUPLICATE KEY UPDATE ';
if (empty($updateColumns)) {
$sql .= static::buildValuesList($first);
} else {
$sql .= static::buildValuesList(array_combine($updateColumns, $updateColumns));
}
return $sql;
}
/**
* Build the INSERT IGNORE sql statement.
*
* @param array $data
*
* @return string
*/
protected static function buildInsertIgnoreSql(array $data)
{
$first = static::getFirstRow($data);
$sql = 'INSERT IGNORE INTO `' . static::getTablePrefix() . static::getTableName() . '`(' . static::getColumnList($first) . ') VALUES' . PHP_EOL;
$sql .= static::buildQuestionMarks($data);
return $sql;
}
/**
* Build REPLACE sql statement.
*
* @param array $data
*
* @return string
*/
protected static function buildReplaceSql(array $data)
{
$first = static::getFirstRow($data);
$sql = 'REPLACE INTO `' . static::getTablePrefix() . static::getTableName() . '`(' . static::getColumnList($first) . ') VALUES' . PHP_EOL;
$sql .= static::buildQuestionMarks($data);
return $sql;
}
在控制器
中Lectura::replace($arr);