用 AI 編寫並檢查 SQL:參數化、唯讀沙箱與結果核對流程

用 AI 編寫並檢查 SQL:參數化、唯讀沙箱與結果核對流程

Olivia Park
2026年8月24日· 9 分鐘讀完

要安全地用 AI 編寫並檢查 SQL,就給模型一份獲批的 schema 和精確的業務問題,要求以參數而非字串拼接傳值,並把執行限制在最小權限的唯讀沙箱或可棄置副本內。信任結果之前,先審查執行計劃,再以獨立設計的 fixture 核對資料列、join、空值、重複和聚合。

不要把 AI 工具直接連到生產資料庫當作學習捷徑。在受控邊界內使用 AI的流程同樣適用,但資料庫存取需要更嚴格的身份、資料和副作用控制。

關鍵要點

  • 生成 SQL 前,先界定業務問題、列粒度、schema 和假設。
  • 透過資料庫驅動程式的參數介面,把程式碼與數值分開。
  • 按讀寫行為和可能的副作用,為每條語句分類。
  • 使用可棄置資料庫或最小權限的唯讀身份,而非生產憑證。
  • 先審查執行計劃,再以合成 fixture 和獨立總數核對結果。

如何用 AI 編寫並檢查 SQL 而不交出資料庫控制權?

把起草與執行分開。模型可以根據 schema 上下文提出查詢,但是否執行、在哪裏執行,由經審核的操作人員或受控應用程式決定。這樣,一次解釋上的錯誤就不會變成資料庫操作。

OWASP 建議以使用參數化查詢的預備語句作為防禦 SQL 注入的主要方法,因為它把 SQL 程式碼與傳入的數值分開定義。[1] 參數化不能證明查詢回答了正確的問題,但能擋住一大類程式碼與資料混淆。

設定五道閘門:

閘門必需證據
問題已界定的指標、人口、時間窗口和列粒度
草稿附 schema 限定的 SQL 及明確假設
安全參數、讀寫分類、最小權限的執行身份
計劃已審查的運算子、估算、篩選、join 和資源風險
結果已核對的 fixture 資料列、總數、重複、空值和邊界情況

每道閘門的輸出都是下一道的輸入。不要讓聊天介面把它們藏進一個「執行此查詢」按鈕。

步驟 1:凍結業務問題與預期列粒度

分享 schema 之前,先以業務語言寫下問題。「為每名活躍客戶傳回一列,包含上一個完整曆月的已付發票總額」比「顯示每月收入」清楚。

界定:

  • 一列代表哪個實體或時段;
  • 包括和排除哪些狀態;
  • 時區,以及邊界是否包含在內;
  • 退款、取消、重複和缺失值如何處理;
  • 結果是計數、總和、快照、事件歷史還是最新狀態;
  • 一個可獨立計算的小例子。

最昂貴的 SQL 錯誤大多源於含糊的粒度。把發票列 join 到多項狀態事件上,即使每個子句都是有效 SQL,金額也可能成倍放大。把預期的唯一鍵寫明。

把假設寫成可 Review 清單

在給出查詢文字前,先請模型陳述假設。例如:「invoices.id 唯一」「一名客戶可有多張發票」「時間戳記以 UTC 儲存」。對照 schema、約束、遷移和持續維護的文件逐項核實。

如果不熟悉程式庫,先以唯讀證據釐清相關程式碼和資料路徑。不要只憑應用程式的變數名稱推斷資料庫契約。

步驟 2:只分享最小獲准 schema

提供表名、欄名、類型、鍵、關係、相關約束和幾列合成資料。寫明資料庫方言和你的環境支援的版本功能,但略去真實記錄、憑證、主機名稱、連接字串和敏感註解。

優先提供經整理的 schema 摘錄,而非完整的生產匯出。刪除個人資料和看似秘密的預設數值。如果欄名本身已透露敏感商業資訊,就改用關係相同、獲批准的本地 fixture。

告訴模型不要虛構欠缺的欄、索引、關係或列舉值。它的回應應分兩部分:「查詢草稿」和「未解決的 schema 問題」。依賴未解決關係的查詢不可執行。

步驟 3:參數化值並限制動態識別符

來自用戶、請求、檔案或上游系統的數值,必須使用驅動程式的綁定參數介面。不要請模型手動轉義字串,或把它們拼進 SQL。OWASP 的查詢參數化指引展示了這個做法在常見語言和資料庫介面中的寫法。[2]

概念上,應優先採用:

SELECT customer_id, SUM(amount) AS paid_total
FROM invoices
WHERE status = :status
  AND paid_at >= :period_start
  AND paid_at < :period_end
GROUP BY customer_id;

佔位符語法因驅動程式而異,請在你實際使用的程式庫官方文件中核實。

參數通常不能取代表名、欄名、排序方向或 SQL 關鍵字。如果識別符必須可變,就在應用程式碼中把一小組獲批輸入對應到寫死的識別符。不要把模型產生的任意識別符直接傳給資料庫。

參數化與授權解決不同問題

參數化查詢仍可能把每列客戶資料暴露給未獲授權的調用者。租戶範圍、列級規則、資料庫角色和應用程式授權要分別核實。AI 私隱風險指南可協助判斷哪些資料根本不應進入提示詞或 fixture。

步驟 4:執行前分類語句與副作用

不要只憑第一個可見關鍵字分類。通用資料表運算式、函數、觸發器、預存程序、擴充功能、臨時物件、鎖和 EXPLAIN ANALYZE 的行為,都可能有別於一般讀取。

採用三個實用類別:

類別例子預設處理方式
讀取候選普通 SELECT、不執行的計劃檢查Review 後在唯讀沙箱執行
狀態或資源影響鎖定讀取、臨時物件、大型掃描、會執行的計劃分析使用專用環境和明確限制
寫入或管理INSERT、UPDATE、DELETE、DDL、權限授予、帶副作用的程序進入獨立變更流程並由人手批准

PostgreSQL 交易把多個步驟組合成全有或全無的單位,並在完成前對其他交易隱藏中間變更。[3] 交易有助管理原子性,但不會令錯誤的更新變得可以接受,也不保證外部副作用可以還原。

絕不能把「稍後還原」當作未經審查寫入的主要安全界線。錯誤的查詢可能在你打算還原之前,已鎖住資源、觸發工作、調用易變函數或暴露資料。

步驟 5:使用一次性或最小權限唯讀環境

最安全的學習環境,是載有合成資料的本地或可棄置資料庫。預備環境副本仍可能含有敏感記錄,也可能觸發整合,因此要核實其資料和副作用界線。

必須查詢真實資料庫時,使用專用身份,只授予所需的 schema、資料表、欄和操作。在模型控制範圍以外設定語句逾時、適當的列數上限、資源控制和記錄。

PostgreSQL 支援唯讀交易模式,並在該模式下禁止許多資料變更指令,但其文件指出,這只是高層次的唯讀概念,並不能阻止所有磁碟寫入。[4] 把它視為其中一層,而非普遍保證。其他資料庫的語義亦各有不同。

此圖描述的是操作流程,不能證明某個具體資料庫、身份、函數或連接器是唯讀的。

步驟 6:看結果前先審查 SQL 與計劃

審查所選欄位、join 鍵、篩選、空值行為、分組、排序、限制和子查詢。留意意外的交叉 join、放在會放大列數的 join 之後的篩選條件、被 WHERE 謂詞變成內部連接的左連接,或使用了錯誤時區的日期邊界。

如果資料庫支援,先用不會執行的計劃指令。檢查:

  • 每個節點的估算列數;
  • 掃描方式,以及篩選是否足夠早套用;
  • join 類型和 join 條件;
  • 排序、聚合、實體化和重複的子計劃;
  • 分割區修剪和索引假設;
  • 預期基數與估算基數之間可疑的差距。

在 PostgreSQL 中,EXPLAIN ANALYZE 會真正執行查詢,同時報告實際列數和耗時。[5] 不要把它當作無害的預覽。只有在為底層語句和資源風險分類後,才在獲批環境中使用。

計劃不是正確性的證明。快速的計劃可能傳回錯誤的資料列;正確的查詢亦可能對生產資料分佈而言成本過高。

步驟 7:以專用 fixture 獨立核對結果

建立一個可人手計出答案的小型合成數據集。每項重要規則至少對應一列:

  • 應包括和應排除的狀態;
  • 恰好落在起訖時間點的時間戳記;
  • 空值和空白值;
  • 重複事件或一對多關係;
  • 沒有對應子列的客戶;
  • 相關時的退款或沖銷;
  • 如獲允許,異常大或負數的數值。

執行生成的查詢之前,先寫下預期的資料列和總數。然後比較:

  1. 輸出列數;
  2. 預期粒度鍵的唯一性;
  3. 分組小計和總計;
  4. 被包括和被排除的記錄;
  5. 空值處理和預設數值;
  6. 對重複的敏感度;
  7. 下游依賴排序時,排序是否確定。

可以請 AI 協助列出遺漏的情況,但不要讓它在無人核對下既計算預期結果又撰寫查詢。使用 AI 測試設計流程建立回歸 fixture,令判定依據獨立於 SQL 實作。

步驟 8:審查應用整合,不只看裸 SQL

一條安全的語句,也可能因應用程式碼拼接字串、以錯誤類型綁定數值、使用高權限連接池、重試寫入、在記錄中寫下敏感參數,或傳回無上限的結果而變得不安全。

檢查最終的調用位置:

  • 連接選用了哪個身份和資料庫?
  • 參數是透過驅動程式綁定,還是被格式化進文字?
  • 交易、逾時、取消和重試規則是否明確?
  • 結果欄位對應是否沒有截斷或類型混淆?
  • 錯誤會否把 schema 或個人資料洩漏到記錄或客戶端?
  • 分頁是否使用穩定的排序?

對整合修補套用 AI 生成程式碼執行前 Review清單。只審查裸 SQL,涵蓋不到周邊的權限和控制流程。

步驟 9:寫查詢必須進入獨立變更流程

如果任務需要更新資料,在執行前就停止起草流程。要求經審查的遷移或運作手冊、受影響資料列預覽、備份或復原計劃、交易設計、並行分析、授權、監察和一名具名批准人。

使用不可變的輸入,並把批准綁定到確切的查詢、參數、目標身份、資料庫和時間窗口。其後對查詢的任何修改都會令批准失效。不要讓模型在預覽後擴大影響範圍。

查詢產生意外的資料列或效能時,保存證據,並使用 AI 除錯流程。沒有穩定的判定依據,反覆要求「更好的查詢」,往往只是以一個隱藏假設換掉另一個。

總結

  • 先界定業務問題、列粒度、schema 和邊界行為。
  • 數值用綁定參數,可變識別符用白名單對應。
  • 把起草與執行分開,並為所有可能的影響分類。
  • 優先使用合成的可棄置資料;否則使用最小權限的唯讀身份並設定限制。
  • 審查計劃,再獨立核對資料列、總數、join、空值和重複。
  • 把每次寫入都當作另行批准的變更,而非聊天的延伸。

常見問題

可以把資料庫 schema 傳給 AI 嗎?

只有在機構容許,並刪除秘密和敏感商業細節之後才可以。優先提供最小的獲批摘錄,或對等的合成 schema。

參數化能保證 SQL 安全嗎?

不能。它有力地解決了數值層面的程式碼與資料分離,但你仍需核實授權、資料暴露、識別符、查詢邏輯、權限、資源使用和應用整合。

唯讀資料庫用戶足夠嗎?

它是重要的一層,但並非完整保證。要核實資料庫特定的語義、函數行為、臨時物件、資源影響、可存取的資料,以及連接實際使用的身份。

EXPLAIN 與 EXPLAIN ANALYZE 一樣嗎?

不一樣。在 PostgreSQL 中,普通 EXPLAIN 只顯示計劃而不執行查詢,EXPLAIN ANALYZE 則會執行查詢並報告實際量度。使用前請查閱你所用資料庫的文件。

如何發現 join 導致的重複資料列?

界定預期的列粒度和唯一鍵,比較每次 join 前後的列數,並以一對多的 fixture 測試。把分組小計與獨立計算的總數核對。

應讓 AI Agent 直接連接生產資料庫嗎?

學習或起草時不應預設如此。使用可棄置資料庫或受控查詢介面,並配合最小權限、明確批准、記錄和獨立的結果核對。

Transaction 能撤銷所有資料庫相關效果嗎?

不能。交易語義因資料庫而異,外部調用、序列、鎖、通知或運作影響未必能完全撤銷。請審查具體系統的行為。

生成的查詢與預期總數不一致怎麼辦?

暫停執行,保存 fixture 和結果,先核實判定依據,再逐項檢查粒度、join、篩選、空值、時間邊界和重複。不要為了讓查詢通過而修改預期值。


延伸閱讀:

免責聲明:本文提供一般技術與保安資訊,不構成資料庫管理、法律、合規或財務建議。有後果的資料系統,請使用合資格覆核人和機構的變更控制。

來源:

  1. OWASP Cheat Sheet Series — SQL Injection Prevention — https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html
  2. OWASP Cheat Sheet Series — Query Parameterization — https://cheatsheetseries.owasp.org/cheatsheets/Query_Parameterization_Cheat_Sheet.html
  3. PostgreSQL Documentation — Transactions — https://www.postgresql.org/docs/current/tutorial-transactions.html
  4. PostgreSQL Documentation — SET TRANSACTION — https://www.postgresql.org/docs/current/sql-set-transaction.html
  5. PostgreSQL Documentation — Using EXPLAIN — https://www.postgresql.org/docs/current/using-explain.html

Sources checked 2026 年 8 月 24 日。

開啟 3 天免費試用

註冊即可免費體驗全部高級功能。

*只限新用戶;每位用戶只可獲得一次試用。

用 AI 編寫並檢查 SQL:參數化、唯讀沙箱與結果核對流程 | AethoVPN