这是在SQL Server 2008 R2中。
我正用这个拉我的头发。请密切关注。当我运行它时,我返回了27行:
select *
from dbo.[12STD_NO_VISIT]
where (
(dbo.fPhoneExists(PhoneNumber1) = 1
AND (NextCall1 BETWEEN GETDATE() AND DATEADD(hh, 1, GETDATE())))
)
当我运行这个时,我得到21行返回(注意对PhoneNumber2和NextCall2的更改):
select *
from dbo.[12STD_NO_VISIT]
where (
(dbo.fPhoneExists(PhoneNumber2) = 1
AND (NextCall2 BETWEEN GETDATE() AND DATEADD(hh, 1, GETDATE())))
)
但是,当我运行这个时,'ORing'这两个条件,我得到一个错误:
将varchar值'N'转换为数据类型int
时转换失败
select *
from dbo.[12STD_NO_VISIT]
where (
(dbo.fPhoneExists(PhoneNumber1) = 1
AND (NextCall1 BETWEEN GETDATE() AND DATEADD(hh, 1, GETDATE())))
OR
(dbo.fPhoneExists(PhoneNumber2) = 1
AND (NextCall2 BETWEEN GETDATE() AND DATEADD(hh, 1, GETDATE())))
)
但它不只是给我错误。它首先检索42行,显示一行(结果选项卡),然后显示错误(消息选项卡)。
我无法想出这个。非常感谢任何帮助。
谢谢!
FUNCTION [dbo].[fPhoneExists](@PhoneNumber varchar)
RETURNS BIT
WITH EXECUTE AS CALLER
AS
BEGIN
DECLARE @GoodNumber bit
IF (@PhoneNumber is NULL or @PhoneNumber = 0 or @PhoneNumber = '')
SET @GoodNumber = 0;
ELSE
SET @GoodNumber = 1;
Return(@GoodNumber);
END
答案 0 :(得分:4)
PhoneNumber1
和PhoneNumber2
有哪些数据类型? dbo.fPhoneExists
的定义是什么?我怀疑这个问题存在于某个地方 - 或者正如Lynn所暗示的那样,查询可能比你向我们展示的更多(查询会成功或失败作为一个整体;它不会产生42行然后是错误)。
现在我们看到了这个函数,这里是重写:
ALTER FUNCTION [dbo].[fPhoneExists]
(
@PhoneNumber VARCHAR -- varchar(what)? This should match definition of column
)
RETURNS BIT
WITH EXECUTE AS CALLER
AS
BEGIN
RETURN (SELECT CASE WHEN COALESCE(@PhoneNumber, '') IN ('0', '') THEN 0 ELSE 1 END);
END
GO
没有理由将临时逻辑存储在变量中,还要注意您在ELSE条件下返回仅变量。
答案 1 :(得分:3)
您的dbo.fPhoneExists
函数在PhoneNumber = 0
表达式中包含一个隐式转换,根据Data Type Peecendence的规则将PhoneNumber
VARCHAR值转换为int。如果字符串中的值不是数字,则此强制转换将失败。你也陷入了假设在SQL中保证布尔运算符短路的谬论,这根本不是真的。 SQL是一种声明性语言和order of evaluation of boolean operators is not guaranteed。
答案 2 :(得分:1)
通过将fnPhoneExists
替换为CASE
来替换select *
from dbo.[12STD_NO_VISIT]
where (
(case when ISNULL(PhoneNumber1,'') not in ('0','') then 1 else 0 end=1
AND (NextCall1 BETWEEN GETDATE() AND DATEADD(hh, 1, GETDATE())))
OR
(case when ISNULL(PhoneNumber2,'') not in ('0','') then 1 else 0 end=1
AND (NextCall2 BETWEEN GETDATE() AND DATEADD(hh, 1, GETDATE())))
)
,您将获得更好的效果:
{{1}}
这是因为优化器不会优化fnPhoneExists的内容。