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

标签 sql sql-server-2008

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

例如,假设我使用 xp_logeventCATCHRAISERROR 时阻止向事件日志写入内容发生,但我想根据 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
    
  • 使用“设置”表来存储值。
  • 优点:改变值(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
    
  • 使用带有功能的“设置”表来简化访问。
  • 优点:易于更改值。易于在代码中访问。
  • 缺点:开销大。用户可以更改值。
    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
    

  • 有没有最佳实践方法来做到这一点?

    最佳答案

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

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

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

    关于sql - 在 SQL 中定义命名常量的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8442565/

    相关文章:

    sql-server - SQL Server执行计划: what are rebinds,中的物理运算符回滚和执行次数?

    sql-server - 值必须存在于两个表中

    sql-server-2008 - 如何在SQL2k8中使用另一个数据库中定义的数据类型(表)?

    sql-server-2008 - 计算最长不间断语音时长

    php - 使用 laravel 高级 where 子句运行查询

    mysql - 更新语句不按条件过滤,使用MySQL默认为 "else"

    mysql - 如何在没有嵌套查询的情况下在 MySQL 中执行组聚合?

    sql - 减少自连接

    java - 处理海量数据表时应该如何使用Hibernate Mapping

    sql - 如果不同表中的列匹配则更新值