Drizzle ORM(Postgres)报错:未选择创建表的Schema及解决方法
问题场景
使用pg-core搭配^0.25.2版本的drizzle-orm,db.ts代码如下:
// db.ts import { drizzle } from "drizzle-orm/node-postgres"; import { migrate } from "drizzle-orm/node-postgres/migrator"; import { Pool } from "pg"; const pool = new Pool({ connectionString: process.env.POSTGRES_DB_URL, }); const db = drizzle(pool, { logger: true }); (async () => { await migrate(db, { migrationsFolder: "./drizzle" }); })();
执行迁移后,drizzle目录生成了.sql文件,但数据库未创建任何表,查询时出现以下错误日志:
Query: CREATE SCHEMA IF NOT EXISTS "drizzle" Query: CREATE TABLE IF NOT EXISTS "drizzle"."__drizzle_migrations" ( id SERIAL PRIMARY KEY, hash text NOT NULL, created_at bigint ) Query: select id, hash, created_at from "drizzle"."__drizzle_migrations" order by created_at desc limit 1 Query: begin Query: CREATE TABLE IF NOT EXISTS "accounts" ( "user_id" integer, "access_token" text, "expires_at" integer, "id_token" text, "provider" text NOT NULL, "provider_account_id" text NOT NULL, "refresh_token" text, "scope" text, "session_state" text, "token_type" text, "type" text NOT NULL ); Query: rollback error - unhandledRejection: error: no schema has been selected to create in
错误含义
这个错误是PostgreSQL的明确提示:执行创建表的SQL时,未指定表要存放的数据库模式(schema)。PostgreSQL要求必须明确表的归属schema,要么在SQL中给表名添加schema前缀(如public.accounts),要么当前数据库连接已设置默认的search_path(默认schema列表)。
从日志能看到,Drizzle创建迁移表时指定了drizzle.__drizzle_migrations,但创建accounts表时未加schema前缀,且当前连接未设置默认schema,导致PostgreSQL无法确定表的存放位置,最终触发回滚。
解决方法
1. 给数据库连接设置默认search_path
修改Pool配置,添加searchPath参数指定默认schema列表(通常public是公共默认schema,加上drizzle用于存放迁移表):
const pool = new Pool({ connectionString: process.env.POSTGRES_DB_URL, searchPath: ['public', 'drizzle'], // 指定默认schema优先级 });
这样PostgreSQL会优先在public下创建新表,同时能识别drizzle下的迁移表。
2. 在表定义中指定schema
在Drizzle的表结构定义里,给每个表明确指定目标schema,生成的迁移SQL会自动带上schema前缀:
import { pgTable, integer, text } from "drizzle-orm/pg-core"; // 定义表时指定schema const accounts = pgTable( "accounts", { user_id: integer(), access_token: text(), // 其他字段定义... }, { schema: "public" } // 明确指定schema );
重新生成迁移文件后,SQL会变为CREATE TABLE IF NOT EXISTS "public"."accounts" (...),即可正常执行。
3. 手动修改已生成的迁移SQL
如果已经生成了迁移文件,可直接编辑drizzle目录下的.sql文件,给无schema前缀的表添加public.(或你需要的schema):
-- 修改前 CREATE TABLE IF NOT EXISTS "accounts" (...); -- 修改后 CREATE TABLE IF NOT EXISTS "public"."accounts" (...);
修改完成后重新执行迁移即可。
内容的提问来源于stack exchange,提问作者wongx

