有沒有副作用的標準 SQL 函式?
SQL 標準是否定義了具有副作用的函式?
例如,當您執行類似操作時,它們是否具有寫入文件* 或更新表中某些列中的值的功能
SELECT myfunction(params...);
我有時會看到這些,但我只是好奇 SQL 標準是否也這樣做。
- 這不是專門針對 PostgreSQL 的問題。我只使用我在 PostgreSQL 中看到的副作用範例。
你在這裡有幾個不同的問題。
問:什麼是 ANSI 標準 SQL 函式?
ANSI 標準函式是諸如 AVG、COUNT、MIN、MAX 之類的東西。它們包含在1992 ANSI 標準中,但那是一種枯燥乏味的閱讀。
問:ANSI 標準 SQL 函式會更改數據庫中的數據嗎?
不,您可以使用它們來更改數據 - 例如,我可以說:
INSERT INTO dbo.MyReport SELECT MAX(SalespersonRevenue) FROM dbo.Sales
但就其本身而言,僅使用 AVG、COUNT、MIN、MAX 等不應永久更改數據庫內的數據。
問:ANSI 標準是否允許我編寫自己的函式?
是的,但具體實施因供應商而異。您編寫的函式可能符合 ANSI 語言標準,但您在函式中執行的操作可能非常糟糕,例如產生副作用。
- 在討論預期行為時,可以獲得跨平台的答案。
- 在討論副作用時,它不是。
問:我可以創建自己的函式來寫入數據嗎?
為什麼確定,如果你有創意。我是一名 Microsoft SQL Server 人員,因此我將專注於該平台。線上圖書的功能頁面說:
使用者定義的函式不能用於執行修改數據庫狀態的操作。
我說:
你不是我真正的父親。
所以這就是我打破規則的方式。警告:非常糟糕的想法隨之而來。
- 在您的函式中,查詢一個專門為此目的而創建的新表,然後創建一些東西來監視該表中的 select 語句,然後觸發一個操作(擴展事件、審計或 Profiler 跟踪)。您可以將 Rube Goldberg 類型的裝置連接在一起,以根據這些 select 語句執行工作。
- 在函式中,呼叫 CLR 程式碼 - 哎呀,您甚至可以呼叫 Web 服務。該網路服務可以很好地將數據推送回您自己的數據庫。
- 在函式中,呼叫 xp_cmdshell並通過命令提示符執行某些操作。(HT @AaronBertrand 在評論中。)
所有這些範例在性能和事務一致性方面都存在巨大缺陷。你只是問理論上是否可以做到,答案是肯定的。我永遠不會在我自己的程式碼中使用其中任何一個——我會退後一步問:“我在這裡想要實現的業務目標是什麼,有沒有辦法可以實現性能和事務一致性?” 如果您想對此提出具體建議,我會問一個單獨的 Stack 問題,其中包含具體細節。
關於 SQL Server,我只能肯定地說,而且似乎這在所有數據庫實現中並不一致。但在 SQL Server 中,函式可能不會產生副作用。這是一條硬性規定,我曾多次嘗試規避但均未成功。
如果您正在考慮一般意義上的函式,那麼有些 SQL 模組允許副作用(例如儲存過程),但使用者定義的函式不允許。
有句諺語“聰明的解決方案無法擴展”,這對於 Microsoft 產品來說尤其如此。我在 SQL Server 的早期版本中看到了許多巧妙的解決方法,這些解決方法在後來的版本中變得過時了,因為 MS 將它們添加為真正的功能。
老實說,那些從未成為功能的東西永遠不會成為功能,因為它們從根本上破壞了 T-SQL 開發的某些方面。函式的副作用就是其中之一。