【问题标题】:Laravel+mysql: temporary table can be created/updated but not selected from:Laravel+mysql:可以创建/更新临时表,但不能从以下选项中选择:
【发布时间】:2018-08-13 18:30:03
【问题描述】:

我可以创建一个临时表,但是当我尝试从中选择时,它说该表不存在。我认为它是因为 DB::statement 和 DB::select 以某种方式与数据库进行了不同的会话,但我不确定如何修复它。

如何在同一个脚本中创建一个临时表、插入其中并从中选择?

以下是 tinker 的输出,它演示了该问题:

DB::select("select count(*) from users"); //12
DB::statement("create temporary table tempUsers like users"); //true
DB::statement("insert into tempUsers (id,email) VALUES (1, 'joe@example.com')"); //true

“选择”会话中似乎不存在

DB::select("select count(*) from tempUsers"); 

Illuminate\Database\QueryException 带有消息 'SQLSTATE[42S02]: Base 未找到表或视图:1146 表 'db.tempUsers' 不存在(SQL: 从 tempUsers 中选择 count(*)'

仍然存在于“声明”会话中

DB::statement("insert into tempUsers (id,email) VALUES (2, 'bob@example.com')"); //true
DB::statement("insert into tempUsers (id,email) VALUES (1, 'joe@example.com')"); 

Illuminate\Database\QueryException 带有消息“SQLSTATE[23000]: 完整性约束违规:1062 键的重复条目“1” 'PRIMARY' (SQL: INSERT INTO tempUsers (id,email) VALUES (1,'bob@example.com'))'

我使用$table->temporary()Blueprint 得到相同的行为,即

Schema::create('tempTable',function ($table) {$table->increments('id');
    $table->timestamps();
    $table->temporary();
}); 

使用 Laravel 5.4、MySQL 5.6

当我连接到 laravel 之外的数据库时,我可以很好地从临时表中进行操作和选择

【问题讨论】:

    标签: php mysql laravel temp-tables


    【解决方案1】:

    原来问题是由我们的reader-writer 设置引起的。我们使用一个数据库进行写入,另一个用于读取。写入器数据库被复制到读取数据库,但是temp table is not replicated,因为它是一个临时表并且它锁定到与写入器的当前会话。

    如果使用 Laravel 5.5+,解决方案是在数据库连接上设置'sticky' => true。这使得写入器在任何写入后都被视为读取器,以绕过复制延迟的问题。

    由于我现在坚持使用 Laravel 5.4,我的解决方案是创建一个标准表,但将其视为临时表并在方法结束时将其删除。

    DB::select("select count(*) from users"); //12
    
    //use uniqid to ensure a unique tablename since it is now in the global namespace
    $tableName=uniqid('tempUsers'); 
    
    DB::unprepared("create table $tableName like users"); //true
    DB::statement("insert into tempUsers (id,email) VALUES (1, 'joe@example.com')"); //true
    DB::select("select count(*) from $tableName"); //1
    //...do stuff with temp table
    //...
    Schema::drop($tableName);
    // return
    

    【讨论】:

      【解决方案2】:

      如果你在存储过程中创建临时表,一旦存储过程完成,它就会被销毁。

      临时表的范围很重要,只对特定用户可见。临时表以井号“#”或“@”开头,这非常重要,因为您似乎错过了那部分。

      因此,如果您将迁移调整为:

      Schema::create('#tmpTest', function (Blueprint $table) {
          $table->increments('id');
          $table->string('name');
      });
      

      然后运行:

      php artisan migrate:fresh
      

      在临时表上插入数据:

      \DB::statement("插入#tmpTest (id,name) VALUES (1, 'joe@example.com')");

      使用 select 获取这些数据:

      $a = DB::select('从#tmpTest中选择*'); dd($a);

      它给了我结果:

      【讨论】:

      • 您好,谢谢您的回复。我不是在存储过程中创建它,所以这不是一个因素。 mysql 不使用哈希 # 来指示临时表(也许 mssql 会?),所以在我的环境中,您的代码将执行,除了它将创建一个名称中带有文字哈希标记的普通表,而不是临时表,所以这没有回答问题
      猜你喜欢
      • 2012-03-23
      • 1970-01-01
      • 1970-01-01
      • 2021-11-09
      • 2023-04-09
      • 1970-01-01
      • 2016-05-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多