SUPABASE CORE · 116
Data Queries:SDK 語法背後仍是資料操作 Contract
.from().select() 很方便,但 correctness 仍取決於 query filter、RLS、constraints、result cardinality 與 error handling。這一課不背 method 清單,而是追蹤一次 CRUD operation 的完整資料流。
Learning outcomes
- 能讀 select/insert/update/delete 的 input/output。
- 能區分 no rows、RLS、filter、network/error。
- 能避免無條件 update/delete。
- 能理解 pagination/order 的重要性。
1. Select
const {
data,
error
} = await supabase
.from("courses")
.select("id,title,score")
.gte("score", 60)
.order(
"score",
{ ascending: false }
);不要只看 data;error、auth context、RLS、filter 都會影響結果。
2. Insert
const {
data,
error
} = await supabase
.from("courses")
.insert({
title: "JavaScript",
score: 90
})
.select();能送 request 不代表能 insert;policy、NOT NULL、CHECK、FK 都可能拒絕。
3. Update / Delete:filter 是 operation scope
await supabase
.from("courses")
.update({ score: 95 })
.eq("id", 42);少 filter 可能影響多筆。RLS 是 authorization boundary,不替代 application intent。
4. Result cardinality
你預期一筆還是多筆要明確。若 id 必須唯一,應由 database constraint 表達,而不是只靠 UI 假設。
5. Pagination / ordering
.order(
"created_at",
{ ascending: false }
)
.range(0, 49)大量資料不能永遠一次抓完。Pagination 需要穩定 ordering,否則 page boundary 可能隨插入漂移。
Project checkpoint:Course Workspace v4
listMyCourses()
createCourse(input)
updateCourse(id, patch)
deleteCourse(id)
Each:
check error
know cardinality
RLS authorization
constraints validityDebug evidence:data=[]
- error 是什麼?
- filter 是否匹配?
- session/user context 是誰?
- RLS SELECT policy 是否允許?
- 資料是否存在?
6. Data API privilege 與 RLS 是兩道不同 gate
新 table 可能已存在於 public schema,但目前 project configuration 未自動把它暴露給 Data API。此時即使你已經 ENABLE RLS、也寫好了 policy,client 仍可能先遇到 table privilege error。
Table exists
↓
GRANT SELECT / INSERT / UPDATE / DELETE
↓
RLS policy
↓
visible / writable rows
典型 evidence:
42501
permission denied for table notes
這種錯誤優先查 role privilege / Data API exposure,不要把它和 data=[] 混在一起。後者更像 query/filter/RLS visibility 問題。
Knowledge check
- RLS 存在後 update 為何仍要 filter?
- 0 rows 和 network error 的 evidence 差異?
- 大量 courses 為何需 pagination?
- 設計 listMyCourses 的 order + range。