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

时间:2011-12-09 07:52:36

标签: sql sql-server-2008

如果数据库中的多个存储过程和函数需要“常量”值,是否有一种标准方法可以在一个地方定义它,以便它可以在任何地方使用?

例如,假设我在xp_logevent块中使用CATCHRAISERROR发生时向事件日志写入内容,但我想将严重性分组为信息,警告和错误基于RAISERROR严重性。

我可以设置一个常量EventSeverity

  • 如果RAISERROR严重性= 0,则xp_logevent是信息性的。
  • 如果RAISERROR严重性< = EventSeverity而非xp_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
      

有最好的做法吗?

1 个答案:

答案 0 :(得分:2)

在其他条件相同的情况下,我会选择硬编码的FUNCTION来获得性能。为了安全起见,这个函数应该放在一个不同的SCHEMA中,比如MyDatabase.CONF.SettingsFunc而不是通常的DBO;权限设置为此架构,因此只有管理员才有权更改数据。

如果您需要集中各种配置设置以用于许多不同的用途,那么最后一种方法(FUNCTION + TABLE)将具有更大的吸引力,您可以为每个用例创建索引。同样,这个“设置”表应该在受限制的模式中,与函数不同,函数可以保留在默认模式中以便于编码。

但是,如果必须使用默认模式,则在此“设置”表中配置“INSTEAD OF UPDATE”触发器会很有趣,因此用户不会轻易更改数据;不要忘记后一种方法不能称为“安全性”,因为用户仍然可以更改(或删除!)触发器。

相关问题