我试图在T-SQL中模拟PL / SQL DECODE()
函数:
CREATE FUNCTION [dbo].[fnDecode]
(
@condition AS BIT,
@trueVal AS VARCHAR(2000),
@falseVal AS VARCHAR(2000)
)
RETURNS VARCHAR(2000)
WITH EXEC AS CALLER AS
BEGIN
RETURN CASE @condition
WHEN 1 THEN @trueVal
ELSE @falseVal
END
END
GO
尝试移植到T-SQL的PL / SQL片段是:
CASE pcr.person_type
WHEN 'N'
THEN
npcr.first_name
|| DECODE (npcr.middle_name,
NULL, '',
' ' || npcr.middle_name)
|| ' '
|| npcr.last_name
WHEN 'L'
THEN
lpcr.name
END
我想在CASE
语句中调用上面定义的标量函数,如下所示:
CASE pcr.person_type
WHEN 'N' THEN npcr.first_name
+ dbo.fnDecode(npcr.middle_name IS NULL, '', ' ' + npcr.middle_name)
+ ' '
+ npcr.last_name
WHEN 'L' THEN lpcr.name
END
我无法将fnDecode()
函数的结果存储到变量中,因为行来自某些连接表(并且在我移植的查询中有多个fnDecode()
调用)
我们正在使用SQL Server 2012和2014。
答案 0 :(得分:2)
移植程序方法"因为它是" 根本不是一个好习惯。这不是PHP,C#甚至是PL / SQL。此外,在描述的情况下,您甚至不需要任何函数调用。 NULL
和上面提到的场景中的空字符串处理非常简单,不需要任何程序方法。
有函数NULLIF
,ISNULL
,COALESCE
,CASE
语句。您需要的一切就是检查某些内容是true
还是false
,null
。
每行的标量UDF调用可能(并且会)导致严重性能问题。
检查出来:
CASE pcr.person_type
WHEN 'N' THEN npcr.first_name
+ IsNull(' ' + npcr.middle_name, '')
+ ' '
+ npcr.last_name
WHEN 'L' THEN lpcr.name
END
即使你已经禁用了ANSI_NULLS和CONCAT_NULL_YIELD_NULL选项而且没有'希望给服务器任何错误的机会,你可以使用case
,这种方法比调用函数要好得多:
CASE pcr.person_type
WHEN 'N' THEN npcr.first_name
+ case when npcr.middle_name is NULL then '' else ' ' + npcr.middle_name end
+ ' '
+ npcr.last_name
WHEN 'L' THEN lpcr.name
END
如果允许空标记,则此代码可以正常工作(设置常规空选项):
CASE pcr.person_type
WHEN 'N' THEN npcr.first_name
+ IsNull(' ' + NullIf(npcr.middle_name, ''), '')
+ IsNull(' ' + NullIf(npcr.last_name, ''), '')
WHEN 'L' THEN lpcr.name
END
答案 1 :(得分:1)
是的,从CASE
表达式(以及许多其他地方)调用标量函数当然是可能的。
您遇到的问题与第一个参数有关。 BIT
是一种数字数据类型。不是boolean
,事实上,SQL Server在T-SQL中没有公开的boolean
数据类型。因此,您不能将fDecode
函数的第一个参数设置为布尔值,也不能在预期接受npcr.middle_name = NULL
的位置传递评估谓词的结果,例如bit
。
this 之类的东西应该执行:
CASE pcr.person_type
WHEN 'N' THEN npcr.first_name
+ dbo.fnDecode(CASE WHEN npcr.middle_name = NULL THEN 1 ELSE 0 END, '', ' ' + npcr.middle_name)
+ ' '
+ npcr.last_name
WHEN 'L' THEN lpcr.name
END
(虽然你可能还需要插入一个显式的演员表)
但这使得治疗看起来比诅咒更糟糕。
在任何情况下,您都可以使用内置的IIF
函数而不是fDecode
。因为它是内置的,所以它不会遵循您必须遵循的相同规则,事实上它的第一个参数是一个布尔表达式。