Laravel迁移中如何设置PostgreSQL的GENERATED BY DEFAULT AS IDENTITY标识列
在Laravel迁移中配置PostgreSQL标识列(GENERATED BY DEFAULT AS IDENTITY)
刚好之前处理过类似的需求,Laravel默认的$table->id()确实是用PostgreSQL序列来实现自增,但如果想要用原生的IDENTITY列,有两种实用的方法可以实现:
方法一:直接使用原生SQL语句(快速实现)
如果只是单张表需要这种结构,直接用DB::statement()执行原生PostgreSQL语句是最直接的方式,完全贴合你想要的表结构:
use Illuminate\Database\Migrations\Migration; use Illuminate\Support\Facades\DB; return new class extends Migration { public function up() { DB::statement("CREATE TABLE color ( color_id INT GENERATED BY DEFAULT AS IDENTITY, color_name VARCHAR NOT NULL )"); } public function down() { DB::statement("DROP TABLE IF EXISTS color"); } };
运行迁移后,你可以用PostgreSQL的\d color命令查看表结构,会看到color_id列的定义正是你需要的GENERATED BY DEFAULT AS IDENTITY。
方法二:自定义Schema宏(复用性更高)
如果你的项目中有多张表需要使用IDENTITY列,自定义一个Schema宏会更符合Laravel的开发风格,不用每次都写原生SQL。
步骤1:注册Schema宏
在App\Providers\AppServiceProvider的boot()方法中添加以下代码:
use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; public function boot() { Schema::macro('identity', function ($columnName = 'id', $type = 'int') { /** @var Blueprint $this */ return $this->addColumn('identity', $columnName, compact('type')); }); }
步骤2:创建自定义列类型
在项目中创建App\Database\Schema\Columns\IdentityColumn.php文件(路径可以根据你的习惯调整),内容如下:
use Illuminate\Database\Schema\Grammars\PostgresGrammar; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\ColumnDefinition; class IdentityColumn extends ColumnDefinition { public function build(Blueprint $blueprint, PostgresGrammar $grammar) { $column = $this->name; $type = $this->attributes['type']; // 这里可以根据需求改成GENERATED ALWAYS AS IDENTITY return "$column $type GENERATED BY DEFAULT AS IDENTITY"; } }
步骤3:在迁移中使用自定义方法
现在你就可以像使用$table->id()一样,用$table->identity()来创建标识列了:
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { public function up() { Schema::create('color', function (Blueprint $table) { $table->identity('color_id', 'int'); $table->string('color_name')->nullable(false); }); } public function down() { Schema::dropIfExists('color'); } };
小提示:区分两种IDENTITY模式
别忘了GENERATED BY DEFAULT和GENERATED ALWAYS的区别:
GENERATED BY DEFAULT:允许你手动给标识列插入值,如果不提供值则自动生成GENERATED ALWAYS:强制自动生成值,手动插入会报错(除非使用INSERT ... OVERRIDING SYSTEM VALUE语句)
根据你的业务需求调整对应的SQL语句即可。
内容的提问来源于stack exchange,提问作者Dhairya Lakhera
相关产品推荐
相关产品推荐

