生成列
MSSQL 支持计算列。计算列是根据一个表达式计算出来的,该表达式可以引用同一张表中的其他列。
-
虚拟计算列在查询时计算,不占用存储空间。
-
持久化计算列将计算结果存储在磁盘上,并且当表达式是确定性的时可以建立索引。
更多信息请参阅 Microsoft 文档中的 计算列。
Drizzle 端
在 Drizzle 中,你可以在列上指定 .generatedAlwaysAs() 并传入一个 SQL 表达式。
虚拟计算列
import { SQL, sql } from "drizzle-orm";
import { mssqlTable, varchar } from "drizzle-orm/mssql-core";
export const users = mssqlTable("users", {
firstName: varchar("first_name", { length: 256 }),
lastName: varchar("last_name", { length: 256 }),
fullName: varchar("full_name", { length: 512 }).generatedAlwaysAs(
(): SQL => sql`concat(${users.firstName}, ' ', ${users.lastName})`,
),
});CREATE TABLE [users] (
[first_name] varchar(256),
[last_name] varchar(256),
[full_name] AS (concat([users].[first_name], ' ', [users].[last_name]))
);持久化计算列
当你希望 SQL Server 持久化计算值时,请使用 { mode: "persisted" }。
schema.ts
SQL
import { SQL, sql } from "drizzle-orm";
import { int, mssqlTable, varchar } from "drizzle-orm/mssql-core";
export const orders = mssqlTable("orders", {
quantity: int("quantity"),
unitPrice: int("unit_price"),
total: int("total").generatedAlwaysAs(
(): SQL => sql`${orders.quantity} * ${orders.unitPrice}`,
{ mode: "persisted" },
),
});限制
Drizzle Kit 对 push 命令也有一些限制:
- 你不能使用
push来更改生成约束表达式。Drizzle-kit 会忽略这个变更。要使其生效,你需要drop the column、push,然后再add a column with a new expression。之所以这样做,是因为数据库端的映射很复杂:模式表达式会在数据库端被修改,而在 introspection 时我们会得到一个不同的字符串。我们无法确定你是修改了这个表达式,还是它只是被数据库修改并格式化了。只要这些是生成列,而且push主要用于本地数据库上的原型验证,那么快速drop和create生成列应该是可行的。由于这些列是generated的,所有数据都会被恢复 generate不应有任何限制