MySQL的Replace操作

Posted by chunpat on April 19, 2021

缘由

想复现两条重复的数据,但是一直被替换,死死不出来。查看sql日志,发现出现了Replace操作,之前没见过,词义为替换。 第一时间想的是和索引有关,看了下还真是,去掉索引之后就复现了数据。

日志

tp5.1日志,出现了REPLACE

[ sql ] [ SQL ] REPLACE INTO `store_system_depot_goods_detail` 
(`goods_name` , `classify_type_id` , `skus_json` , `store_id` , 
`account_id` , `goods_sn` , `classify_id` , `goods_id` , `create_time` ,
 `update_time`) VALUES ('定义商品编码' , 1 , '{\"\\u5c0f\\u7c73\\u673a\\u578b\":\"HM-\\u7ea2\\u7c73NOTE5\"}' , 
 0 , 2269 , '6931755509057' , 1 , 426741 , '2021-04-19 10:23:45' , 
 '2021-04-19 10:23:45') [ RunTime:0.008989s ]

怎么实现

tp5.1,php代码,路径thinkphp/library/think/model/relation/HasMany.php,一对多关联的时候使用

    /**
     * 保存(新增)当前关联数据对象
     * @access public
     * @param  mixed    $data       数据 可以使用数组 关联模型对象 和 关联对象的主键
     * @param  boolean  $replace    是否自动识别更新和写入
     * @return Model|false
     */
    public function save($data, $replace = true)
    {
        if ($data instanceof Model) {
            $data = $data->getData();
        }

        // 保存关联表数据
        $data[$this->foreignKey] = $this->parent->{$this->localKey};

        $model = new $this->model;

        return $model->replace($replace)->save($data) ? $model : false;
    }

tp5.1 最终Sql转换code,thinkphp/library/think/db/Builder.php

     /**
      * 生成Insert SQL
      * @access public
      * @param  Query     $query   查询对象
      * @param  bool      $replace 是否replace
      * @return string
      */
     public function insert(Query $query, $replace = false)
     {
         $options = $query->getOptions();
 
         // 分析并处理数据
         $data = $this->parseData($query, $options['data']);
         if (empty($data)) {
             return '';
         }
 
         $fields = array_keys($data);
         $values = array_values($data);
 
         return str_replace(
             ['%INSERT%', '%TABLE%', '%FIELD%', '%DATA%', '%COMMENT%'],
             [
                 $replace ? 'REPLACE' : 'INSERT',
                 $this->parseTable($query, $options['table']),
                 implode(' , ', $fields),
                 implode(' , ', $values),
                 $this->parseComment($query, $options['comment']),
             ],
             $this->insertSql);
     }

结论:Replace是由Mysql自己做处理的

总结

慎用MySQL Replace语句,存在PRIMARY KEY或者UNIQUE索引,有利有弊。利:可以做去重处理。 弊:删除旧数据新增新数据。

迭代

  • 2021年04月19日 11:26:40 初稿

参考:


Creative Commons License
本作品采用CC BY-NC-ND 4.0进行许可。转载,请注明原作者 chunpat 及本文源链接。