1

我正在寻找一种简洁的方法来获取可选标记之前列的前导文本,在 SQL Server 2008 上(所以没有IIF)。我有一nvarchar列在文本中的某个点可能有也可能没有标记,我需要返回完整的列值(如果没有标记)或标记之前的位(如果有)。(这不是我的架构,我无法更改它。)

我看到了这些选择:

  1. CHARINDEXandSUBSTRING来做,它既冗长又丑陋(见下文),或者

  2. 创建一个函数来集中和隐藏丑陋,并使用它(见下文)。

有没有更好的内置选项?如果是这样,那是什么?(这个问题的答案很可能是“不”。)

(我认为谈论的这个答案PARSENAME可能是一个选项,但是因为标记是可选的,所以它并没有真正的帮助,而且这样做而不是创建一个函数对我来说似乎有点 hacky...)


选项 #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
4

2 回答 2

2

另一种方法是将标记附加到列的末尾并用于charindex连接值。

left(data, charindex(N'{}', data+N'{}')-1)
于 2013-07-14T19:14:41.783 回答
1

我更喜欢将定义放在代码中,而不是将其隐藏在函数中。原因之一是用户定义函数的性能——尽管自 SQL Server 早期以来性能已经大大提高。另一个原因是用户定义的函数今天可能对您有意义,但将来对其他人可能没有意义。要理解查询,则需要查找函数的定义。(如果您在正在编写的代码中定义一组通用函数,则可以缓解这种情况。)

如果你需要经常这样做,那么我会建议两件事之一。TrimmedData首先,使用您喜欢定义的任何方法创建一个包含列的视图。

另一种是使用计算列定义表:

TrimmedData as (CASE when data like '%{}%' then left(data, charindex('{}', data)-1)
                     else data
                end)

在任何一种情况下,“表”(或视图)的用户都可以使用它。这确保了 的定义TrimmedData始终相同并且易于获得。

like请注意,使用andleft()代替charindex()and是一个(不重要的)偏好问题substr()

SELECT (CASE when data like '%{}%' then left(data, charindex('{}', data) - 1)
             else data
        end) as TrimmedData
FROM ...

我强迫自己like在这种情况下不断地提醒自己,它在许多数据库上都经过了高度优化,并且通常是查找子字符串的最佳性能方法。

于 2013-07-14T16:09:37.110 回答