在 laravel IDENTITY_INSERT 中插入数据设置为 OFF

Insert data in laravel IDENTITY_INSERT is set to OFF

所以我在数据库 sqlserver 上插入数据时遇到了问题。 id sqlserver 拒绝插入,因为数据库想要自己插入 id。

我必须尝试像这样设置 IDENTITY_INSERT ON :

DB::statement('SET IDENTITY_INSERT articles ON;');

并像这样将 IDENTITY_INSERT 设置为关闭 :

DB::statement('SET IDENTITY_INSERT articles OFF;');

但它不适用于我的代码。

   public function store(Request $request){
        //to sparate to methode
        $article = $request->isMethod('put') ? Article::findOrFail($request->article_id) : new Article;

        $article->id = $request->input('article_id');
        $article->title = $request->input('title');
        $article->body = $request->input('body');

        DB::statement('SET IDENTITY_INSERT articles ON;');
        if($article->save()){
            return new ArticleResources($article);
        }
        DB::statement('SET IDENTITY_INSERT articles OFF;');

    }

这个错误看起来像这样:

SQLSTATE[23000]: [Microsoft][ODBC Driver 11 for SQL Server][SQL Server]Cannot insert explicit value for identity column in table 'articles' when IDENTITY_INSERT is set to OFF.

您可以使用 DB::unprepared() 而不是 DB::statement()

区别在于statement()执行的是准备好的语句,而unprepared()使用的是PDO::exec()

每个准备好的语句都会启动一个新会话(在同一数据库连接内),并且因为 SET IDENTITY_INSERT 查询是 session-specific,它不会影响其他准备好的语句,如 INSERT 查询。

PDO::exec() 影响整个数据库连接。

喜欢:

DB::unprepared('SET IDENTITY_INSERT test_table ON');
DB::table('articles')->insert(['id' => $request->input('article_id'), 'title' => $request->input('title'), 'body'=> $request->input('body')]);
DB::unprepared('SET IDENTITY_INSERT test_table OFF');

如果您遇到断言错误,请尝试以下解决方法:

DB::unprepared('SELECT 1; SET IDENTITY_INSERT test_table ON');
DB::table('articles')->insert(['id' => $request->input('article_id'), 'title' => $request->input('title'), 'body'=> $request->input('body')]);
DB::unprepared('SELECT 1; SET IDENTITY_INSERT test_table OFF');

正如 Vikash Pathak 所提到的,DB::unprepared 会起作用,尽管在我的情况下,当我有 Doctrine DBAL(数据库抽象层)时,我在 macOS 上 运行 遇到了这个问题) 安装,这是 Laravel Nova 的依赖项。事实证明,DB::unprepared 将 return false 用于此语句,它工作正常,除了 DBAL 会导致断言错误。

 AssertionError 

  assert($result !== false)

  at vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:54

我尝试了多种方法来解决这个问题,但最终我发现通过在 SET IDENTITY_INSERT table_name ON 之前添加一个微不足道的 SELECT,它会 return true 并且 AssertionError 将不再是一个问题。

如果有更优雅的解决方案,请告诉我。我的特定问题可能是驱动程序怪癖或数据库设置,但我使用的 Docker SQL Server 2019 配置与其他没有此问题的环境相同。