今天我們繼續 TypedSQL
經過昨天的 $queryRaw
的介紹,大家應該都知道 raw SQL
根本沒有 type
的概念,所以很容易在寫 SQL
的時候都要對照表去查看對應的欄位,那有什麼方法解決呢,我們就廢話不多說開始今天的內容 TypedSQL
走起~
在使用 TypedSQL
之前大家記得安裝最新的 prisma
版本,要記得你的 prisma
必須要是 5.19.0
以上才有 TypedSQL
的功能喔
>npm install @prisma/client@latest
>npm install -D prisma@latest
接著到你的 schema.prisma
加上 typedSql
這個 previewFeatures
//schema.prisma
generator client {
provider = "prisma-client-js"
previewFeatures = ["typedSql"]
}
然後新增 prisma/sql
這個 folder
,在這邊的 folder
你可以加上任何你想執行的 SQL
指令,這邊以 getPostAndAuthor.sql
為例子
然後這邊是 getPostAndAuthor.sql
的內容,這邊想看所有的 post
對應的 user
是誰,然後用 join
關聯 User
跟 Post
的 table
//getPostAndAuthor.sql
Select
p.id as "postId",
p.title as "postTitle",
p.content as "postContent",
p.published
FROM "Post" as p
JOIN "User" as u on p."authorId" = u.id
ORDER By p."createAt" DESC
這邊使用 prisma client
的 generate
要注意加上 --sql
因為我們要轉換的是 SQL
>npx prisma generate --sql
同樣 prisma generate
也有支援 watch
功能,如果需要可以加上
>prisma generate --sql --watch
之後 prisma client
就會把 SQL
的內容加到 node_modules
中
>npx prisma generate --sql
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
✔ Generated Prisma Client (v5.20.0) to ./node_modules/@prisma/client in 76ms
Start by importing your Prisma Client (See: http://pris.ly/d/importing-client)
Tip: Easily identify and fix slow SQL queries in your app. Optimize helps you enhance your visibility: https://pris.ly/--optimize
使用時候就可以自動從 @prisma
import
進來,那 function name
就是對應 SQL
的 file name
,然後用 prisma
的 $queryRawTyped
這個 methods
去執行你的 SQL function
import { getPostAndAuthor } from "@prisma/client/sql";
const result = await prisma.$queryRawTyped(getPostAndAuthor())
執行 index.ts
後就成功拿到資料拉~是不時很神奇呢~以後只需要 call function
就好不用自己寫 raw SQL
了
[
//..
{
postId: 2641,
postTitle: 'atqui',
postContent: 'tamquam',
published: false
},
... 120 more items
]
甚至 result
還有 type
~
另外你也可加上參數到你的 SQL file
中,這邊加上 getPostAndAuthorByPostId.sql
然後 $1
當作你要查詢 post.id
的變數
// getPostAndAuthorByPostId.sql
Select
p.id as "postId",
p.title as "postTitle",
p.content as "postContent",
p.published
FROM "Post" as p
JOIN "User" as u on p."authorId" = u.id
WHERE p.id = $1
ORDER By p."createAt" DESC
再次跑完 generate
後你就可以使用了
>npx prisma generate --sql
import {
getPostAndAuthor,
getPostAndAuthorByPostId,
} from "@prisma/client/sql";
const result = await prisma.$queryRawTyped(getPostAndAuthorByPostId(2231))
一樣執行 index.ts
資料也如預期返回~
[
{
postId: 2231,
postTitle: 'rerum',
postContent: 'copiose',
published: false
}
]
那因為 post.id
我們是定 number
如果參數 type
不對也會跳 type error
~
如果你要使用兩個以上變數只需要加上 $2
就好
//getUsersByAge.sql
Select
u.id as "userId",
u.email as "userEmail",
u.name as "userName",
u.age as "userAge"
FROM "User" as u
WHERE u.age > $1 AND u.age < $2
const userByAge = await prisma.$queryRawTyped(getUsersByAge(10, 20))
這邊一樣也如預期返回我們要的資料~
[
{
userId: 1400,
userEmail: 'Eulalia20@hotmail.com',
userName: 'Greg Kassulke',
userAge: 16
}
]
另外 prisma
支援你可以在 SQL file
中去定你的 Argument
的 type
或是 Argument
的 name
使用方式如下:
@param
這個變數-- @param {Type} $N:alias optional description
這邊以 getUsersByAge.sql
為例子,我們取名 minAge
跟 maxAge
然後 type
都是 number
-- @params {Int} $1:minAge get user by min Age range
-- @params {Int} $2:maxAge get user by max Age range
Select
u.id as "userId",
u.email as "userEmail",
u.name as "userName",
u.age as "userAge"
FROM "User" as u
WHERE u.age > $1 AND u.age < $2
然後你會看到 prisma client
就自動根據我們定義的 @params
產出 argument
的 name
跟 type
,寫法是不是很像在寫 jsDoc
~
最後補充一個就是 TypedSQL
有一個限制是,如果你需要在 runtime
的時候才會知道你要拿到的 Select column
是什麼的話,你無法用 argument
的方式搭配 TypedSQL
幫你 generate
,反之你只能透過 queryRawUnsafe
的方式
但這可能會衍生一個隱患是 SQL injection
所以使用時要謹慎考慮一下
const columns = 'name, email, age'; // Columns determined at runtime
const result = await prisma.$queryRawUnsafe(
`SELECT ${columns} FROM Users WHERE active = true`
);
✅ 前端社群 :
https://lihi3.cc/kBe0Y