跳到主要內容

視圖

警告

目前對視圖的支援仍處於非常早期的預覽功能階段。您可以使用 view 關鍵字將視圖新增至您的 Prisma schema,或使用 db pull 在您的資料庫 schema 中內省視圖。除非使用 --create-only 標記手動將變更新增至您的遷移檔案,否則您尚無法使用 Prisma Migrate 和 db push 將 schema 中的視圖套用至您的資料庫。

如需此功能進度的更新,請追蹤我們的 GitHub issue

資料庫視圖允許您命名和儲存查詢。在關聯式資料庫中,視圖是儲存的 SQL 查詢,可能包含多個表格中的欄位,或計算值,例如彙總。在 MongoDB 中,視圖是可查詢的物件,其內容由其他集合上的聚合管道定義。

views 預覽功能允許您使用 view 關鍵字在您的 Prisma schema 中表示視圖。若要在 Prisma ORM 中使用視圖,請依照下列步驟操作

啟用 views 預覽功能

目前對視圖的支援處於早期預覽階段。若要啟用 views 預覽功能,請將 views 功能標記新增至您 Prisma Schema 中 generator 區塊的 previewFeatures 欄位

schema.prisma
generator client {
provider = "prisma-client-js"
previewFeatures = ["views"]
}

請在我們專門的 views 預覽功能回饋 issue 中留下關於此預覽功能的意見回饋。

在底層資料庫中建立視圖

目前,您無法使用 Prisma Migrate 和 db push 將您在 Prisma schema 中定義的視圖套用至您的資料庫。相反地,您必須先在底層資料庫中建立視圖,可以手動建立,也可以作為遷移的一部分建立。

例如,以下列具有 User 模型和相關 Profile 模型的 Prisma schema 為例

model User {
id Int @id @default(autoincrement())
email String @unique
name String?
profile Profile?
}

model Profile {
id Int @id @default(autoincrement())
bio String
user User @relation(fields: [userId], references: [id])
userId Int @unique
}

接下來,以底層資料庫中的 UserInfo 視圖為例,該視圖結合了 User 模型中的 emailname 欄位,以及 Profile 模型中的 bio 欄位。

對於關聯式資料庫,建立此視圖的 SQL 陳述式為

CREATE VIEW "UserInfo" AS
SELECT u.id, email, name, bio
FROM "User" u
LEFT JOIN "Profile" p ON u.id = p."userId";

對於 MongoDB,您可以使用以下命令建立視圖

db.createView('UserInfo', 'User', [
{
$lookup: {
from: 'Profile',
localField: '_id',
foreignField: 'userId',
as: 'ProfileData',
},
},
{
$project: {
_id: 1,
email: 1,
name: 1,
bio: '$ProfileData.bio',
},
},
{ $unwind: '$bio' },
])

搭配 Prisma Migrate 和 db push 使用視圖

如果您使用 Prisma Migrate 或 db push 將變更套用至您的 Prisma schema,Prisma ORM 不會建立或執行任何與視圖相關的 SQL。

若要在遷移中加入視圖,請執行 migrate dev --create-only,然後手動將視圖的 SQL 新增至您的遷移檔案。或者,您可以手動在資料庫中建立視圖。

將視圖新增至您的 Prisma schema

若要將視圖新增至您的 Prisma schema,請使用 view 關鍵字。

您可以將上述範例中的 UserInfo 視圖表示為如下的 Prisma schema

view UserInfo {
id Int @unique
email String
name String
bio String
}

手動編寫

一個 view 區塊由兩個主要部分組成

  • view 區塊定義
  • 視圖的欄位定義

這兩個部分允許您定義產生的 Prisma Client 中視圖的名稱,以及視圖查詢結果中存在的欄位。

定義 view 區塊

若要定義上述範例中的 UserInfo 視圖,請先使用 view 關鍵字在您的 schema 中定義一個名為 UserInfoview 區塊

view UserInfo {
// Fields
}

定義欄位

視圖的屬性稱為欄位,由以下組成

  • 欄位名稱
  • 欄位類型

UserInfo 範例視圖的欄位可以定義如下

view UserInfo {
id Int @unique
email String
name String
bio String
}

view 區塊的每個欄位都代表底層資料庫中視圖查詢結果中的一個欄位。

使用內省

警告

目前僅適用於 PostgreSQL、MySQL、SQL Server 和 CockroachDB。

如果您在資料庫中定義了一個或多個現有的視圖,內省將自動在您的 Prisma schema 中產生代表這些視圖的 view 區塊。

假設範例 UserInfo 視圖存在於您的底層資料庫中,執行以下命令將在您的 Prisma schema 中產生一個代表該視圖的 view 區塊

npx prisma db pull

產生的 view 區塊將定義如下

/// The underlying view does not contain a valid unique identifier and can therefore currently not be handled by Prisma Client.
view UserInfo {
id Int?
email String?
name String?
bio String?

@@ignore
}

view 區塊最初會使用 @@ignore 屬性產生,因為未定義唯一識別符(目前是視圖預覽功能的一個限制)。

警告

請注意,目前 db pull 僅在使用 PostgreSQL、MySQL、SQL Server 或 CockroachDB 時才會內省您 schema 中的視圖。此工作流程的支援將擴展到其他資料庫供應商。

將唯一識別符新增至內省的視圖

為了能夠在 Prisma Client 中使用內省的視圖,您需要選擇並定義一個或多個欄位作為唯一識別符。

在上述視圖的案例中,id 欄位指的是底層 User 表格中可唯一識別的欄位,因此該欄位也可以用作 view 區塊中可唯一識別的欄位。

為了使此 view 區塊有效,您需要

  • id 欄位中移除可選標記 ?
  • @unique 屬性新增至 id 欄位
  • 移除 @@ignore 屬性
  • 移除關於無效視圖的產生註解警告
/// The underlying view does not contain a valid unique identifier and can therefore currently not be handled by Prisma Client.
view UserInfo {
id Int?
id Int @unique
email String?
name String?
bio String?

@@ignore
}

當重新內省您的資料庫時,對您的視圖定義所做的任何自訂變更都將被保留。

views 目錄

內省具有一個或多個現有視圖的資料庫也會在您的 prisma 目錄中建立一個新的 views 目錄(從 Prisma 版本 4.12.0 開始)。此目錄將包含一個以您的資料庫 schema 命名的子目錄,其中包含每個在該 schema 中內省的視圖的 .sql 檔案。每個檔案將以個別視圖命名,並將包含相關視圖定義的查詢。

例如,在使用上述模型內省具有預設 public schema 的資料庫之後,您會發現已建立一個 prisma/views/public/UserInfo.sql 檔案,其內容如下

SELECT
u.id,
u.email,
u.name,
p.bio
FROM
(
"User" u
LEFT JOIN "Profile" p ON ((u.id = p."userId"))
);

限制

唯一識別符

目前,Prisma ORM 以與模型相同的方式處理視圖。這表示視圖需要至少有一個唯一識別符,可以使用以下任何一種方式表示

  • 使用 @unique 表示的唯一約束
  • 使用 @@unique 表示的複合唯一約束
  • 一個 @id 欄位
  • 使用 @@id 表示的複合識別符

在關聯式資料庫中,視圖的唯一識別符可以定義為一個欄位上的 @unique 屬性,或多個欄位上的 @@unique 屬性。如果可能,最好使用 @unique@@unique 約束,而不是 @id@@id 欄位。

然而,在 MongoDB 中,唯一識別符必須是一個 @id 屬性,該屬性使用 @map("_id") 映射到底層資料庫中的 _id 欄位。

在上述範例中,id 欄位具有 @unique 屬性。如果底層 User 表格中的另一個欄位被定義為可唯一識別,並且在視圖的查詢結果中可用,則可以使用該欄位作為唯一識別符。

內省

目前,視圖的內省僅適用於 PostgreSQL、MySQL、SQL Server 和 CockroachDB。如果您使用其他資料庫供應商,則必須手動新增您的視圖。

這是一個暫時的限制,內省的支援將擴展到其他支援的資料來源供應商。

在 Prisma Client 中查詢視圖

您可以使用與查詢模型相同的方式在 Prisma Client 中查詢視圖。例如,以下查詢在上述定義的 UserInfo 視圖中尋找所有 name'Alice' 的使用者。

const userinfo = await prisma.userInfo.findMany({
where: {
name: 'Alice',
},
})

目前,如果底層資料庫允許,Prisma Client 允許您更新視圖,而無需任何額外的驗證。

特殊類型的視圖

本節說明如何在您的資料庫中使用 Prisma ORM 和可更新及具體化視圖。

可更新視圖

某些資料庫支援可更新視圖(例如 PostgreSQLMySQLSQL Server)。可更新視圖允許您建立、更新或刪除條目。

目前 Prisma ORM 將所有 view 視為可更新視圖。如果底層資料庫支援視圖的此功能,則操作應會成功。如果視圖未標記為可更新,則資料庫將傳回錯誤,而 Prisma Client 隨後將拋出此錯誤。

未來,Prisma Client 可能會支援將個別視圖標記為可更新或不可更新。請在我們的 views 回饋 issue 中評論您的使用案例。

具體化視圖

某些資料庫支援具體化視圖,例如 PostgreSQLCockroachDBMongoDBSQL Server (在 SQL Server 中稱為「索引檢視表」)。

具體化視圖會持久儲存視圖查詢的結果以加快存取速度,並且僅在需要時更新。

目前,Prisma ORM 不支援具體化視圖。但是,當您手動建立視圖時,您也可以使用底層資料庫中的對應命令建立具體化視圖。然後,您可以使用 Prisma Client 的 TypedSQL 功能來執行命令並手動重新整理視圖。

未來,Prisma Client 可能會支援將個別視圖標記為具體化,並新增 Prisma Client 方法來重新整理具體化視圖。請在我們的 views 回饋 issue 中評論您的使用案例。