laravel 在插入之前检查记录是不是存在,这是一种有效的方法

Posted

技术标签:

【中文标题】laravel 在插入之前检查记录是不是存在,这是一种有效的方法【英文标题】:laravel check for record existence before inserting, the efficient waylaravel 在插入之前检查记录是否存在,这是一种有效的方法 【发布时间】:2014-10-08 00:41:34 【问题描述】:

假设我有一个包含这些数据的名为组的表:

+----+---------+------+--------+ |编号 |用户 ID |姓名 |颜色 | +----+---------+------+--------+ | 1 | 1 |富 |绿色 | | 2 | 1 |酒吧 |红色 | | 3 | 1 |巴兹 | | | 4 | 2 |巴兹 |灰色 | | 5 | 3 |富 |蓝色 | | 6 | 3 |巴兹 | | | 7 | 4 |巴兹 |棕色 | | 8 | 4 |富 | | | 9 | 4 |曲奇 |黑色 | +----+---------+------+--------+

我将读取一个 csv 文件并将其转换为如下数据数组:

[
    [
        'user_id'   => 2,
        'name'      => 'foo'
    ],
    [
        'user_id'   => 2,
        'name'      => 'bar'
    ],
    [
        'user_id'   => 2,
        'name'      => 'baz'
    ],
    [
        'user_id'   => 2,
        'name'      => 'qux'
    ],
    [
        'user_id'   => 2,
        'name'      => 'tux'
    ],
]

只将新数据插入数据库,并跳过数据库中已经存在的数据,在本例中,为用户 2 分组 baz

在 Eloquent 中有一些有用的方法,例如 firstOrCreate()findOrNew(),这似乎是我需要的,但这些方法仅用于一条记录,如果我使用它们,我应该在每个文件行运行它们。

while($line = $this->decoder->decode($this->file) 
    $row = Group::firstOrCreate($line);

有没有更好的解决方案来减少查询?

【问题讨论】:

【参考方案1】:

您可以直接将文件加载到表中并忽略重复条目。您所需要的只是列上不应有重复的唯一索引。那你就做

LOAD DATA INFILE 'file_name.csv'
IGNORE
INTO TABLE tbl_name
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
(user_id, @var)
SET name = do_some_voodoo(@var);

就是这样。阅读有关此命令的更多信息here。

测试:

/*sample data*/
shell> cat test.csv
Name|Value
Anna|hello
Ben |Test
East|whatever
Anna|This line should be ignored
Bob |

/*creating destination table in database*/
mysql> create table phpload(a varchar(50) primary key, b varchar(50));
Query OK, 0 rows affected (0.03 sec)

/*Test script*/
<?php
// Create connection
$con=mysqli_connect("localhost","root","r00t","playground");

// Check connection
if (mysqli_connect_errno()) 
  echo "Failed to connect to MySQL: " . mysqli_connect_error();


$sql = "LOAD DATA LOCAL INFILE '/home/developer/test.csv' IGNORE INTO TABLE phpload FIELDS TERMINATED BY '|' (a, @b) SET b = UPPER(@b);";

$result = mysqli_query($con, $sql) or die(mysqli_error());

mysqli_close($con);
?>

/*executing*/
shell> php test.php

mysql> select * from phpload;
+------+----------+
| a    | b        |
+------+----------+
| Name | VALUE    |
| Anna | HELLO    |
| Ben  | TEST     |
| East | WHATEVER |
| Bob  |          |
+------+----------+
5 rows in set (0.00 sec)

工作得很好。

【讨论】:

很酷,但问题是我必须对每一行进行一些处理和验证等 不是真的,我无权访问 SQL 级别 @Behzadsh 更新了我的答案以证明它工作得非常好,您可以在没有“SQL 级别”的情况下使用它。【参考方案2】:

在重复密钥更新时使用 INSERT ...

INSERT INTO table (user_id,name) VALUES(1, "test") ON DUPLICATE KEY UPDATE name=VALUES(name)

对于 Laravel 检查this question

【讨论】:

正如我在问题中提到的,firstOrNew()firstOrCreate() 如果我有单条记录很有用,但我正在寻找一种方法来处理多条记录。

以上是关于laravel 在插入之前检查记录是不是存在,这是一种有效的方法的主要内容,如果未能解决你的问题,请参考以下文章

检查 Laravel 中是不是存在记录不起作用

实体框架:在插入新记录之前检查记录是不是存在

检查 Laravel 5.5 中是不是存在记录 [关闭]

如何在将大量数据插入数据库之前检查记录是不是存在?

Laravel:检查记录ID是不是存在

在使用php插入sql之前检查记录