簡體   English   中英

反對將數據插入其他表的 SQL 觸發器的原因?

[英]Reasons for objection to SQL triggers that insert data into other tables?

我們公司的一個有一定權威的人告訴我,在數據庫中創建觸發器來更改另一個表中的行是一個“數據庫禁忌”。

我已經使用這種技術來創建默認初始配置、自動維護審計日志以及在連接到該數據庫的異構應用程序中始終如一地維護的各種其他事情。 十多年來,我一直認為這是一種集中關系約束維護並讓與數據交互的應用程序承擔責任的適當方式。

因此,我的 BS 儀表與此掛鈎。 我是否遺漏了該技術的一些根本錯誤,使其成為一種不好的做法?

如果你對你的觸發代碼很小心,它本質上沒有什么不好的。 有些人被錯誤的觸發代碼所困擾,然后認為觸發器是錯誤的(盡管問題是錯誤的觸發代碼)。 然后他們將其概括為“從不使用觸發器”。

另一個問題是......

以審計表為例,假設您有一個更新表並將數據放入審計表的存儲過程。 現在假設您編寫觸發器代碼將數據放入審計表。 您最終可能會得到重復的審計數據。

這是個人喜好。 不過,在我看來,這是不好的做法。 管理一個在表上具有更新其他表的觸發器的數據庫可能有點不守規矩,這會引發另一個觸發器來更新另一個表,等等。

對我來說,將所有功能包裝到存儲過程中更有意義,這樣所有邏輯都在一個地方。

不過,各有各的。

這可能是公司的政策,但不是絕對的禁忌。 除非您知道並控制數據庫,否則這樣做的問題是其他表的修改可能效率低下(這通常很難識別為問題),並且存在級聯的危險 - 即修改此表觸發另一個觸發器,該觸發器可能會更新另一個表....

因此,我不會將其稱為“禁忌”,而是要謹慎行事。

我認為這類似於在結構化編程中避免goto語句的警告。 與將一堆 DML 放入觸發器相比,你應該很難找到一個“更好”的答案,因為錯誤處理觸發器很容易讓你措手不及,但有時這是解決手頭問題的最佳答案。

我的經驗主要是在 SQL 服務器上。 舊版本沒有更改跟蹤或級聯參照完整性,因此在過去糟糕的日子里,您可能不得不自己編寫觸發器來處理日志記錄和參照完整性管理。 現在,平台中內置了用於這兩種功能的高級工具。 它們比加載 DML 的觸發器“更干凈”,但仍然允許您保持這些功能集中。

即便如此,仍然存在在觸發器中編寫代碼可以最好地完成工作的情況。 如果您通過分析得出結論認為觸發器是您需要的工具,請不要讓教條阻止您完成工作。

正如您所說,並非所有將行插入另一個表的觸發器都是壞的,例如一個觸發器而不是在 AUDIT 表中保留該行的先前版本。 但是在不知道細節的情況下,我確實懷疑您通過觸發器創建的“默認初始配置”在存儲過程中可能會更好,因為 SP 更具自我記錄性。

應避免特殊的副作用——我所說的“特殊”是指一個人對繞過久經考驗的標准做事方式的捷徑的想法。 它們使持續的維護變得困難,並且對於后來發生的粗心的程序員來說可能是陷阱。

我仍在尋找定義“最佳實踐”的那本書——我想我會在“數據庫禁忌的大書”旁邊找到它。

就個人而言,我鼓勵團隊盡可能避免觸發因素。 我和他們有過不好的經歷——我同意用錘子擊打自己並不會使所有的錘子都變壞,但觸發器更像是釘槍而不是錘子——傷害的機會肯定存在。

觸發器是“副作用”——您的明確意圖是在表中插入一條記錄; 作為這種意圖的副作用,發生了一大堆其他事情。 與我合作的大多數團隊都沒有“數據庫專家”——開發人員跨多個層次工作,將所有副作用留在他們的大腦中是很費力的。 這為錯誤和性能問題創造了機會——不是因為某人愚蠢或懶惰,而是因為技術變得更加復雜。

有些問題最好(甚至只能)通過觸發器解決——強制引用完整性是一個經典。 有些問題經常通過觸發器來解決,這讓我很緊張——尤其是當它們反映業務規則或使用審計表時。 有些問題 - 在我看來 - 太接近釘槍觸發器而無法通過觸發器來解決,例如商業領域的計算(例如計算銷售稅額)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM