在SQL中定义命名常量的最佳方法是什么?

6
如果在数据库中的多个存储过程和函数中需要使用“常量”值,是否有标准方法在一个地方定义它以便于随时使用?
例如,假设我在CATCH块中使用xp_logevent在事件日志中写入一些信息,当RAISERROR发生时,但是我希望根据 RAISERROR 严重性将其分组为信息、警告和错误。
我可以设置一个常数EventSeverity使得:
  • 如果 RAISERROR 严重性= 0,则 xp_logevent 为信息。
  • 如果 RAISERROR 严重性≤ EventSeverity ,则 xp_logevent 为警告。
  • 如果 RAISERROR 严重性> EventSeverity ,则 xp_logevent 为错误。
警告和错误严重性之间的截止点不太可能改变,但如果确实发生变化,我希望只更改一个位置。
我考虑了以下可能性:
  • Use a '@@variable' to store the value.

    • Advantages: Low access overhead. Easy to access in code.
    • Disadvantages: Imposes execution order, variable must be declared and set before other procedures and functions can access it. Changing value means changing code.

      DECLARE @@EventSeverity INT = 9
      ...
      BEGIN CATCH
          IF ERROR_SEVERITY() < @@EventSeverity
              ...
          ELSE
              ...
      END CATCH
      
  • Use a function to return the value.

    • Advantages: Fairly low access overhead. Easy to access in code.
    • Disadvantages: Changing value means changing code.

      CREATE FUNCTION dbo.EventSeverity()
      RETURNS INT
      AS
      BEGIN
          RETURN 9
      END
      ...
      BEGIN CATCH
          IF ERROR_SEVERITY() < dbo.EventSeverity()
              ...
          ELSE
              ...
      END CATCH
      
  • Use a "settings" table to store the value.

    • Advantages: Changing value means changing data.
    • Disadvantages: High access overhead. Difficult to access in code. Difficult to use as a parameter. User could change value.

      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
      
  • Use a "settings" table with a function to simplify access.

    • Advantages: Easy to change the value. Easy to access in code.
    • Disadvantages: High overhead. User could change value.

      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
请参见此处:https://dev59.com/KnA75IYBdhLWcg3wS3FA - StuartLC
1
如果这是一个应用程序特定的常量,我会选择使用 dbo.settings 方法,并确保表上的安全模型防止修改,从而满足常量的完整性。 - Roman
1个回答

3
所有其他条件相同的情况下,为了性能,我会选择硬编码的函数。为了安全起见,这个函数应该被放在一个独立的模式中,例如MyDatabase.CONF.SettingsFunc,而不是通常的DBO;并且将权限设置为此模式,以便只有管理员才能更改数据。
如果您需要集中各种配置设置以供多种不同用途使用,则最后一种方法(FUNCTION+TABLE)将具有更大的吸引力,可以为每种用例创建索引。同样,这个“settings”表应该在受限制的模式中,不像函数,它可以保留在默认模式中以方便编码。
但是,如果必须使用默认模式,那么在这个“settings”表中配置一个“INSTEAD OF UPDATE”触发器将变得有趣,这样用户就不能轻易更改数据;请不要忘记,后一种方法不能称为“安全”,因为用户仍然可以更改(或删除!)触发器。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接