如果数据库中的多个存储过程和函数需要“常量”值,是否有一种标准方法可以在一个地方定义它,以便它可以在任何地方使用?
例如,假设我在xp_logevent
块中使用CATCH
在RAISERROR
发生时向事件日志写入内容,但我想将严重性分组为信息,警告和错误基于RAISERROR
严重性。
我可以设置一个常量EventSeverity
:
RAISERROR
严重性= 0,则xp_logevent
是信息性的。RAISERROR
严重性< = EventSeverity
而非xp_logevent
发出警告。RAISERROR
严重程度> EventSeverity
比xp_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
有最好的做法吗?
答案 0 :(得分:2)
在其他条件相同的情况下,我会选择硬编码的FUNCTION来获得性能。为了安全起见,这个函数应该放在一个不同的SCHEMA中,比如MyDatabase.CONF.SettingsFunc而不是通常的DBO;权限设置为此架构,因此只有管理员才有权更改数据。
如果您需要集中各种配置设置以用于许多不同的用途,那么最后一种方法(FUNCTION + TABLE)将具有更大的吸引力,您可以为每个用例创建索引。同样,这个“设置”表应该在受限制的模式中,与函数不同,函数可以保留在默认模式中以便于编码。
但是,如果必须使用默认模式,则在此“设置”表中配置“INSTEAD OF UPDATE”触发器会很有趣,因此用户不会轻易更改数据;不要忘记后一种方法不能称为“安全性”,因为用户仍然可以更改(或删除!)触发器。