Laravel 更新有时使用 'INSERT' SQL

Posted

技术标签:

【中文标题】Laravel 更新有时使用 \'INSERT\' SQL【英文标题】:Laravel update sometimes uses 'INSERT' SQLLaravel 更新有时使用 'INSERT' SQL 【发布时间】:2019-12-16 01:32:06 【问题描述】:

我在更新 Laravel 中的记录时遇到了一些奇怪的问题。我使用此代码更新记录:

$student = new Student();
$student->exists = true;
$student->reg_number = $request->post('reg_number');
$student->name = $request->post('name');
$student->level_id = $request->post('level_id');
$student->status = $request->post('status'); 
$student->save();

代码第一次执行良好。但是,当我再次尝试更新同一条记录时,我得到了错误

SQLSTATE[23000]:违反完整性约束:1062 重复条目 键“P​​RIMARY”的“F17/2019/2019”(SQL:插入studentsreg_numbernamelevel_idupdated_atcreated_at)值 (F17/2019/2019, 约翰·杜斯, 5, 2019-08-08 10:31:52, 2019-08-08 10:31:52))。

但是,过了一段时间,比如半小时左右,我可以再次更新记录而不会出现错误,但只能更新一次。第二次尝试会恢复错误。

我尝试了this question 中讨论的各种其他技术,但结果是相同的。该错误表明 Laravel 选择使用 INSERT 而不是 UPDATE SQL 语句,而记录存在并且我已明确指定它应该更新现有记录。

有人知道这里发生了什么吗?


我使用 mysql,我的学生表 PRIMARY KEY 是 VARCHAR 类型的 reg_number。学生控制器如下所示:

namespace App;
use Illuminate\Database\Eloquent\Model; 
class Student extends Model

    protected $fillable = [
        'reg_number', 
        'name', 
        'level_id', 
        'status' 
    ];
    protected $primaryKey = 'reg_number';
    public $incrementing = false;

【问题讨论】:

请不要使用 new Student();对于现有记录,使用 Student::find() 当您设置exists 时,代码会更新现有记录。请按照我的问题中的链接。此外,记录第一次更新的事实应该提示您错误不是由使用new Student()引起的。 该链接有超过 3 年前的答案,如果你挖掘源代码,我不会太相信存在的属性,还有像 $wasRecentlyCreated 这样的其他属性。获取现有模型的推荐方法是从数据库中对它们进行水合。 @dparoli exists 属性实际上在 Laravel 5.8 中有效。试试看。 在你的情况下它不起作用,你的问题就是这个。我不明白你为什么不想在数据库中找到模型,我错过了什么吗? 【参考方案1】:

我在未发布的代码的其他部分有错误。我有这个功能

public function addStudent(Request $request) 
    if($request->post('status') !== null)
        $this->updateStudent($request);
        return false;
    
...

这就是我在检查 $request->post('status') 时出现错误的地方,它在更新时有时为空。请投票关闭问题,因为错误不是由我发布的代码部分引起的。

我很头疼,因为 Laravel 有时会在错误报告方面模棱两可。如果它说明了导致错误的行号或函数,我会很容易地对其进行调试,并且最终不会发布不相关的问题。

【讨论】:

好吧,你自己找到了 :),我们一直是橡皮鸭。【参考方案2】:

尝试将值从 false 更改为 true

public $incrementing = true;

【讨论】:

我已经发现我做错了什么。但是,$incrementing 是必需的,因为主键是 VARCHAR 数据类型。【参考方案3】:

您必须找到要更新的学生。因为 New 总是会创建模型的新实例,当你保存时,它会创建新记录而不是更新。

$student = Student::find($id);
$student->exists = true;
$student->reg_number = $request->post('reg_number');
$student->name = $request->post('name');
$student->level_id = $request->post('level_id');
$student->status = $request->post('status'); 
$student->save();

另一种更新记录的方法是:

$data = [
   // Column values you want to update
   'exists' => 'value' 
    ... 
    'status' => 'value'
];

Student::where('id', $id)->update($data)

【讨论】:

这些都不起作用。请检查我的问题中的链接。它拥有所有这些解决方案。但是,我发现该错误是由我没有发布的代码的其他部分引起的。我将结束这个问题,因为问题实际上与我发布的代码无关。 PS:我的代码仍然会在不修改的情况下更新记录。这是因为当您将exists 设置为记录时,它会使用更新功能,并且不会创建新记录。 @TroubleZero 您可以使用 updateOrCreate 方法来实现。 实际上,我使用了某种updateOrCreate。我用来调用代码来更新记录的函数是这样的:public function addStudent(Request $request) if($request->post('status') !== null) $this->updateStudent($request); return false; ... 这就是我检查 $request->post('status') 时出现错误的地方,更新时它有时为空。

以上是关于Laravel 更新有时使用 'INSERT' SQL的主要内容,如果未能解决你的问题,请参考以下文章

如何对 laravel 表单请求提出条件

Laravel DB::insert() 和 DB::table()->insert() 的区别

如何使用 PHP 执行 sed -i '/^MAIL_DRIVER=/s/=.*/=log/' .env 之类的东西来更新 laravel dotenv 文件中的变量值

MybatisPlus的自动填充功能使用!

如何在 Laravel DB::insert 中返回我的 OUTPUT 子句

laravel数据库操作