查询中的所有参数都将内联,而不是被 $1
、$2
等替换。
视图
PostgreSQL
SQLite
MySQL
SingleStore
您可以通过多种方式在 Drizzle ORM 中声明视图。
您可以声明需要创建的视图,也可以声明数据库中已存在的视图。
您可以使用内联 query builder
语法、standalone query builder
以及原生 sql
操作符来声明视图语句。
当使用内联或独立查询构建器创建视图时,视图列的模式将自动推断,但当您使用 sql
时,您必须显式声明视图列的模式。
声明视图
import { pgTable, pgView, serial, text, timestamp } from "drizzle-orm/pg-core";
export const user = pgTable("user", {
id: serial(),
name: text(),
email: text(),
password: text(),
role: text().$type<"admin" | "customer">(),
createdAt: timestamp("created_at"),
updatedAt: timestamp("updated_at"),
});
export const userView = pgView("user_view").as((qb) => qb.select().from(user));
export const customersView = pgView("customers_view").as((qb) => qb.select().from(user).where(eq(user.role, "customer")));
CREATE VIEW "user_view" AS SELECT * FROM "user";
CREATE VIEW "customers_view" AS SELECT * FROM "user" WHERE "role" = 'customer';
如果您需要列的子集,可以在查询构建器中使用 .select({ ... })
方法,如下所示:
export const customersView = pgView("customers_view").as((qb) => {
return qb
.select({
id: user.id,
name: user.name,
email: user.email,
})
.from(user);
});
CREATE VIEW "customers_view" AS SELECT "id", "name", "email" FROM "user" WHERE "role" = 'customer';
您也可以使用 standalone query builder
声明视图,它的工作方式完全相同
import { pgTable, pgView, serial, text, timestamp, QueryBuilder} from "drizzle-orm/pg-core";
const qb = new QueryBuilder();
export const user = pgTable("user", {
id: serial(),
name: text(),
email: text(),
password: text(),
role: text().$type<"admin" | "customer">(),
createdAt: timestamp("created_at"),
updatedAt: timestamp("updated_at"),
});
export const userView = pgView("user_view").as(qb.select().from(user));
export const customersView = pgView("customers_view").as(qb.select().from(user).where(eq(user.role, "customer")));
CREATE VIEW "user_view" AS SELECT * FROM "user";
CREATE VIEW "customers_view" AS SELECT * FROM "user" WHERE "role" = 'customer';
使用原生 SQL 声明视图
当您需要使用查询构建器不支持的语法声明视图时,可以直接使用 sql
操作符并显式指定视图列的模式。
// regular view
const newYorkers = pgView('new_yorkers', {
id: serial('id').primaryKey(),
name: text('name').notNull(),
cityId: integer('city_id').notNull(),
}).as(sql`select * from ${users} where ${eq(users.cityId, 1)}`);
// materialized view
const newYorkers = pgMaterializedView('new_yorkers', {
id: serial('id').primaryKey(),
name: text('name').notNull(),
cityId: integer('city_id').notNull(),
}).as(sql`select * from ${users} where ${eq(users.cityId, 1)}`);
声明现有视图
当您被授予数据库中现有视图的只读访问权限时,应使用 .existing()
视图配置,drizzle-kit
将忽略该视图,并且不会在生成的迁移中生成 create view
语句。
export const user = pgTable("user", {
id: serial(),
name: text(),
email: text(),
password: text(),
role: text().$type<"admin" | "customer">(),
createdAt: timestamp("created_at"),
updatedAt: timestamp("updated_at"),
});
// regular view
export const trimmedUser = pgView("trimmed_user", {
id: serial("id"),
name: text("name"),
email: text("email"),
}).existing();
// materialized view won't make any difference, yet you can use it for consistency
export const trimmedUser = pgMaterializedView("trimmed_user", {
id: serial("id"),
name: text("name"),
email: text("email"),
}).existing();
物化视图
PostgreSQL
MySQL
SQLite
根据官方文档,PostgreSQL 拥有**常规视图
**和**物化视图
**。
PostgreSQL 中的物化视图与常规视图一样使用规则系统,但将结果以类表形式持久化。
Drizzle ORM 原生支持 PostgreSQL 物化视图
const newYorkers = pgMaterializedView('new_yorkers').as((qb) => qb.select().from(users).where(eq(users.cityId, 1)));
CREATE MATERIALIZED VIEW "new_yorkers" AS SELECT * FROM "users";
您可以在应用程序运行时刷新物化视图
await db.refreshMaterializedView(newYorkers);
await db.refreshMaterializedView(newYorkers).concurrently();
await db.refreshMaterializedView(newYorkers).withNoData();
扩展示例
// regular view
const newYorkers = pgView('new_yorkers')
.with({
checkOption: 'cascaded',
securityBarrier: true,
securityInvoker: true,
})
.as((qb) => {
const sq = qb
.$with('sq')
.as(
qb.select({ userId: users.id, cityId: cities.id })
.from(users)
.leftJoin(cities, eq(cities.id, users.homeCity))
.where(sql`${users.age1} > 18`),
);
return qb.with(sq).select().from(sq).where(sql`${users.homeCity} = 1`);
});
// materialized view
const newYorkers2 = pgMaterializedView('new_yorkers')
.using('btree')
.with({
fillfactor: 90,
toast_tuple_target: 0.5,
autovacuum_enabled: true,
...
})
.tablespace('custom_tablespace')
.withNoData()
.as((qb) => {
const sq = qb
.$with('sq')
.as(
qb.select({ userId: users.id, cityId: cities.id })
.from(users)
.leftJoin(cities, eq(cities.id, users.homeCity))
.where(sql`${users.age1} > 18`),
);
return qb.with(sq).select().from(sq).where(sql`${users.homeCity} = 1`);
});