Functions

有沒有副作用的標準 SQL 函式?

  • March 11, 2017

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 開發的某些方面。函式的副作用就是其中之一。

引用自:https://dba.stackexchange.com/questions/164938