2010-01-22 61 views
4

我认为这不是确定性的,因为DB_NAME()不是确定性的吗?如果DB_NAME()不确定,为什么它不是确定性的?有什么办法可以使这个UDF具有确定性吗?

ALTER FUNCTION [TheSchema].[udf_IS_PRODUCTION]() 
RETURNS bit 
    WITH SCHEMABINDING 
AS 
    BEGIN 
     RETURN CASE WHEN DB_NAME() = 'PRODUCTION' THEN CONVERT(bit, 1) ELSE CONVERT(bit, 0) END 
    END 

更新:这个版本的作品,是确定性的,允许在任何数据库中使用相同的代码,并删除数据库名称的硬编码(这也让我删除有关数据库中的另一个自动系统健康异常命名编码)

ALTER FUNCTION [TheSchema].[udf_IS_PRODUCTION]() 
RETURNS bit 
    WITH SCHEMABINDING 
AS 
    BEGIN 
     RETURN (SELECT IS_PRODUCTION FROM TheSchema.IS_PRODUCTION) 
    END 

FYI这是在我的系统健康自报系统的代码片段,我用它来监视潜在的问题。

SELECT 'Non-deterministic Scalar UDF' AS Problem 
      ,QUOTENAME(ROUTINE_SCHEMA) + '.' + QUOTENAME(ROUTINE_NAME) AS ROUTINE_NAME 
    FROM INFORMATION_SCHEMA.ROUTINES WITH (NOLOCK) 
    WHERE IS_DETERMINISTIC = 'NO' 
      AND ROUTINE_TYPE = 'FUNCTION' 
      AND DATA_TYPE <> 'TABLE' 
    ORDER BY ROUTINE_SCHEMA 
      ,ROUTINE_NAME 
+0

因为更改数据库中不锁定所有的数据吗?基本上有人可以在长时间运行的查询期间重命名数据库。 – 2010-01-22 16:30:35

回答

4

当然,我可以想出一种方法来确定它。部署此功能对生产数据库:

ALTER FUNCTION [TheSchema].[udf_IS_PRODUCTION]() 
RETURNS bit 
    WITH SCHEMABINDING 
AS 
BEGIN 
    RETURN CONVERT(bit, 1) 
END 

和部署此一个测试数据库:

ALTER FUNCTION [TheSchema].[udf_IS_PRODUCTION]() 
RETURNS bit 
    WITH SCHEMABINDING 
AS 
BEGIN 
    RETURN CONVERT(bit, 0) 
END 

这可能看起来很可笑,但IMO数据库名称不应该“硬编码”任何更使比某些UDF的回报价值要高。

更好的是,把这些信息放在某个配置表中。

+0

由于显而易见的原因,我希望代码在数据库之间相同。此外,我宁愿封装调用,以使系统更易于维护,清晰和可读。使用配置表的版本变得确定。谢谢。 – 2010-01-22 16:53:50

+0

它也允许清除硬编码数据库名称的另一个健康异常。超。 – 2010-01-22 16:56:00

1

确定性函数,顾名思义,是一个函数,其返回值通过其agruments的值被唯一地识别。

现在,鉴于DB_NAME()(它们都没有)的参数,你能说出它会返回什么吗?

+0

这就是严格确定性的定义,并且所有内部函数都必须是严格确定性的,才能被标记为确定性函数,然后用于确定严格确定性函数或确定性用户定义函数。 – 2010-01-22 16:42:31

1

在严格的决定论意义上,结果不是基于输入参数,而是基于不在您控制范围内的外部对象的状态。

名称可以改变等,

Alter Database Modify Name = new_name 

2005年,SQL并不妨碍虽然当我试图使用默认模式正在创建的功能。 如果您遇到拒绝接受基于非确定性功能的情况,并且必须解决此问题(包括风险等),则绕过它的路径是创建一个使用该功能的视图,然后选择从功能的角度来看。

+0

该函数是有效的并且正常工作,它只是非确定性的。我有一个自动系统健康报告,标记所有非确定性标量函数供审查。显然,DB_NAME并不是严格的确定性的,并且对于所有内置函数,严格确定性和确定性都是相同的 - 只有严格确定性函数被标记为确定性函数。依赖于数据库状态的UDF仍然是确定性的,而不是严格确定性的。 – 2010-01-22 16:40:50

+0

你的报告看起来是非常精确和具体的严格确定性,从这个意义上说,这是正确的。 – Andrew 2010-01-22 16:55:56

+0

我会将我的健康报告代码添加到答案中 - UDF只有一个确定性标志。 – 2010-01-22 17:01:19

2

难道你不可能重写你的函数不是在内部确定DB_NAME(),而是将它作为参数发送?

ALTER FUNCTION [TheSchema].[udf_IS_PRODUCTION] (DatabaseName VARCHAR(255)) 
RETURNS bit 
WITH SCHEMABINDING 
AS 
    BEGIN 
     RETURN CASE WHEN DatabaseName = 'PRODUCTION' 
        THEN CONVERT(bit, 1) 
        ELSE CONVERT(bit, 0) 
       END 
    END 

不是应该是确定性的吧?

你打电话时,你可以使用DB_NAME()作为一个函数来确定数据库名称

+0

我不希望呼叫者这样做,它可能会鼓励他们简单地将逻辑内联,从而破坏封装的目的。我发布了最终解决方案。 – 2010-01-22 16:57:16

相关问题