2011-12-09 69 views
3

如果在數據庫中的多個存儲過程和函數中需要「常數」值,是否有一種標準方式將其定義在一個地方,以便在任何地方都可用?在SQL中定義一個命名常量的最佳方式是什麼?

例如,假設我用xp_logeventCATCH塊時發生RAISERROR寫的東西到事件日誌,但我想組基礎上,RAISERROR嚴重程度嚴重到信息,警告和錯誤。

我可以設定的常數EventSeverity使得:

  • 如果RAISERROR嚴重性= 0則xp_logevent用於提供信息。
  • 如果RAISERROR嚴重性< = EventSeverityxp_logevent是警告。
  • 如果RAISERROR嚴重性>EventSeverityxp_logevent是錯誤。

警告和錯誤嚴重程度之間的截斷不太可能改變,但如果它曾經做過,我只想在一個地方改變它。

我認爲這樣的可能性:

  • 使用 '@@variable' 來存儲值。

    • 優點:低訪問開銷。易於訪問的代碼。
    • 缺點:強制執行順序,變量必須在其他過程和函數可以訪問之前聲明和設置。更改值意味着更改代碼。

      DECLARE @@EventSeverity INT = 9 
      ... 
      BEGIN CATCH 
          IF ERROR_SEVERITY() < @@EventSeverity 
           ... 
          ELSE 
           ... 
      END CATCH 
      
  • 使用函數返回值。

    • 優點:相當低的訪問開銷。易於訪問的代碼。
    • 缺點:更改值意味着更改代碼。

      CREATE FUNCTION dbo.EventSeverity() 
      RETURNS INT 
      AS 
      BEGIN 
          RETURN 9 
      END 
      ... 
      BEGIN CATCH 
          IF ERROR_SEVERITY() < dbo.EventSeverity() 
           ... 
          ELSE 
           ... 
      END CATCH 
      
  • 使用 「設置」 表來存儲值。

    • 優點:改變值意味着改變數據。
    • 缺點:高訪問開銷。很難在代碼中訪問。很難用作參數。用戶可以更改值。

      CREATE TABLE dbo.Settings 
      (
          Name VARCHAR(...), 
          Value VARCHAR(...) 
      ) 
      ... 
      INSERT INTO dbo.Settings (Name, Value) 
      VALUES ('EventSeverity', CAST(9 AS VARCHAR)) 
      ... 
      BEGIN CATCH 
          IF ERROR_SEVERITY() < (SELECT CAST(Value AS INT) FROM dbo.Settings WHERE Name = 'EventSeverity') 
           ... 
          ELSE 
           ... 
      END CATCH 
      
  • 使用 「設置」 表的功能,簡化訪問。

    • 優點:易於改變價值。易於訪問的代碼。
    • 缺點:高開銷。用戶可以更改值。

      CREATE TABLE dbo.Settings 
      (
          Name VARCHAR(...), 
          Value VARCHAR(...) 
      ) 
      ... 
      INSERT INTO dbo.Settings (Name, Value) 
      VALUES ('EventSeverity', CAST(9 AS VARCHAR)) 
      ... 
      CREATE FUNCTION dbo.EventSeverity() 
      RETURNS INT 
      AS 
      BEGIN 
          DECLARE @result INT 
          SET @result = (SELECT CAST(Value AS INT) FROM dbo.Settings WHERE Name = 'EventSeverity') 
          IF @result IS NULL 
           SET @result = 9 
          RETURN @result 
      END 
      ... 
      BEGIN CATCH 
          IF ERROR_SEVERITY() < dbo.EventSeverity() 
           ... 
          ELSE 
           ... 
      END CATCH 
      

有沒有一種最佳實踐的方式來做到這一點?

+2

請參閱這裏:http://stackoverflow.com/questions/3370737/best-pattern-for-state-constants-in-sql-server-dbproj – StuartLC

+1

如果它是一個特定於應用程序的常量,我會選擇使用dbo.settings方法,並確保表上的安全模型可以防止修改,從而滿足常量的完整性。 – Roman

回答

2

其他所有的情況都是相同的,我會選擇硬編碼的FUNCTION來表現。爲了安全起見,這個函數應該放在一個獨特的SCHEMA中,比如MyDatabase.CONF.SettingsFunc,而不是通常的DBO;將權限設置爲此架構,以便只有管理員纔有權更改數據。

如果您需要集中許多不同用途的各種配置設置,那麼最後一種方法(FUNCTION + TABLE)將具有更大的吸引力,因爲您可以爲每個用例創建一個索引。同樣,這個「設置」表應該處於受限模式中,與函數不同,函數可以保留在默認模式中以便於編碼。但是,如果強制使用默認模式,則在此「設置」表中配置「INSTEAD OF UPDATE」觸發器變得很有趣,因此用戶不會輕易更改數據;不要忘記,後一種方法不能稱爲「安全」,因爲用戶仍然可以更改(或放棄)觸發器。

相關問題