我正在寻找一种简洁的方法来在SQL Server 2008上获取可选标记之前的列的前导文本(所以没有IIF
)。我有一个nvarchar
列,在文本中的某个点可能有也可能没有标记,我需要返回完整的列值(如果没有标记)或者标记之前的位(如果有的话)是)。 (这不是我的架构,我无法改变它。)
我看到了这些选择:
使用CHARINDEX
和SUBSTRING
执行此操作,这是详细而丑陋的(见下文),或
创建一个集中和隐藏丑陋的功能,并使用它(见下文)。
是否有更好的内置选项?如果是这样,它是什么? (这个问题的答案很可能是“不”。)
(我认为this answer谈论PARSENAME
可能是一个选项,但因为标记是可选的,所以它并没有真正帮助,而这样做而不是创建一个函数似乎是对我来说有点讨厌......)
选项#1的示例:
SELECT
CASE
WHEN CHARINDEX('{}', data, 1) = 0 THEN
data
ELSE
SUBSTRING(data, 1, CHARINDEX('{}', data, 1) - 1)
END AS trimmedData
FROM ...
咳嗽。破解。
选项#2的示例
SELECT dbo.StrUntil(data, '{}') as trimmedData
FROM ...
...其中dbo.StrUntil
类似于:
IF NOT EXISTS (SELECT * FROM sys.objects WHERE type = 'FN' AND name = 'StrUntil')
exec('CREATE FUNCTION [dbo].[StrUntil]() RETURNS INT AS BEGIN RETURN 0 END')
GO
ALTER FUNCTION [dbo].[StrUntil](
@str nvarchar(max),
@substr nvarchar(max)
)
RETURNS nvarchar(max)
AS
BEGIN
RETURN CASE
WHEN CHARINDEX(@substr, @str, 1) = 0 THEN
@str
ELSE
SUBSTRING(@str, 1, CHARINDEX(@substr, @str, 1) - 1)
END
END
答案 0 :(得分:2)
另一种方法是将标记附加到列的末尾,并在连接值上使用charindex
。
left(data, charindex(N'{}', data+N'{}')-1)
答案 1 :(得分:1)
我更喜欢将定义放在代码中而不是将其隐藏在函数中。一个原因是用户定义函数的性能 - 尽管自SQL Server早期以来性能有了很大提高。另一个原因是用户定义的功能今天可能对你有意义,但对未来的其他人可能没有意义。要了解查询,则需要查找函数的定义。 (如果您在编写的代码中定义了一组常用函数,则可以减轻这种情况。)
如果你需要经常这样做,那么我会建议两件事之一。首先,使用您希望定义它的任何方法创建一个包含TrimmedData
列的视图。
另一种是用计算列定义表:
TrimmedData as (CASE when data like '%{}%' then left(data, charindex('{}', data)-1)
else data
end)
在任何一种情况下,"表"的用户都可以使用它。 (或观点)。这可确保TrimmedData
的定义始终相同且随时可用。
作为一个注释,使用like
和left()
代替charindex()
和substr()
是一个(不重要的)偏好问题:
SELECT (CASE when data like '%{}%' then left(data, charindex('{}', data) - 1)
else data
end) as TrimmedData
FROM ...
我强迫自己在此上下文中使用like
来不断提醒自己,它在许多数据库上都经过高度优化,而且往往是查找子字符串的最佳表现方法。