Laravel 5.2 Builder插入替换多行

时间:2017-04-04 02:27:12

标签: php mysql laravel

我有这段代码,可以在第一时间插入数组,但在尝试替换和更新时,会返回错误

  

完整性约束违规: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但结果相同;

2 个答案:

答案 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);