【问题标题】:Can the Select list in a SQL Statement use Regular ExpressionsSQL 语句中的 Select 列表可以使用正则表达式吗
【发布时间】:2010-06-25 04:55:07
【问题描述】:

我有一条 SQL 语句,

select ColumnName from Table

我得到了这个结果,

Error 192.168.1.67 UserName 0bce6c62-1efb-416d-bce5-71c3c8247b75 An existing ....

所以无论如何,该字段中有很多东西,我只想取出“用户名”。

我可以为此使用正则表达式吗?

我的意思是有点像这样,

select SUBSTRING(ColumnName, 0, 5) from Table

除了 SUBSTRING 将被替换为某种正则表达式。我对正则表达式很满意,但我不确定在这种情况下如何应用它,或者即使你可以。

如果我能完成这项工作,那就太好了,因为我计划将数据提取到一个临时表中,并做一些与其他表匹配的相当复杂的事情。如果我能让这一切正常工作,那将节省我的写作时间一个 C# 应用程序。

谢谢。

【问题讨论】:

标签: sql sql-server


【解决方案1】:

不,开箱即用,SQL Server 不支持正则表达式。

您可以通过部署到 SQL Server 中的 SQL-CLR 程序集来改造它们。

【讨论】:

    【解决方案2】:

    我认为无论如何你都应该使用 SUBSTRING。使用正则表达式更灵活,但也会导致较大的处理开销。如果您必须处理大型记录集,情况会变得更糟。

    您必须首先证明是否需要灵活性。

    如果是这样,您应该在这里阅读:

    http://msdn.microsoft.com/en-us/magazine/cc163473.aspx

    仅使用 T-SQL 可以是这样的:

    SELECT 'Error 192.168.1.67 XUserNameX 0bce6c62-1efb-416d-bce5-71c3c8247b75 An existing' expr
        INTO log_table
    GO
    WITH
        split1 (expr, cstart, cend) 
    AS (
            SELECT
                expr, 1, 0
            FROM
                log_table a
    ), split2 (expr, cstart, cend, div)
    AS (
        SELECT
            a.expr, a.cend + 1, CHARINDEX(' ', a.expr, a.cend + 1), 1 
        FROM
            split1 a
        UNION ALL
        SELECT
            a.expr, a.cend + 1, CHARINDEX(' ', a.expr, a.cend + 1), div+1
        FROM
            split2 a
        WHERE
            a.cend > 1
    ), substrings(expr, div)
    AS (
        SELECT 
            SUBSTRING(expr, cstart, cend - cstart), div
        FROM
            split2
    )
    SELECT expr from
        substrings a
    where
        a.div = 3
    

    【讨论】:

    • 我曾经的回答也差不多。但是,现在,我可以非常肯定地说 - 正则表达式。我不会试图为自己辩解太多。我只想说 T-SQL 中的字符串操作工具还有很多不足之处,C# 及其正则表达式的实现非常棒,而对于 T-SQL,使用 substring / charindex 等,需要为每个工具编写单独的提取您想要从字符串中获取的数据。使用正则表达式,一个模式就完成了。维护起来要简单得多。正确、可维护和“慢”节拍 错误、混乱和“快”任何一天。
    【解决方案3】:

    更新

    我们不知道从哪里开始 用户名是。除非我们可以说'找到 我之后的开始字符 第二个空格'

    这很简单:

    • 过滤掉少于 两个空格(或者,有三个 或更多字词);
    • 找到第一个之后的位置 空间(或者,开始 第二个词);
    • 找到第一个之后的位置 第一个空格后的空格 (或者,在 第三个词);
    • 确定第三个的长度 使用下一个位置的单词 空格(或字符串的结尾是 只有三个字);
    • 将上述值与 SUBSTRING() 函数返回 第三个字。

    例子:

    WITH MyTable (ColumnName)
    AS
    (
     SELECT NULL
     UNION ALL 
     SELECT ''
     UNION ALL 
     SELECT 'One.'
     UNION ALL 
     SELECT 'Two words.'
     UNION ALL 
     SELECT 'Three word sentence.'
     UNION ALL 
     SELECT 'Sentence containing four words.'
     UNION ALL 
     SELECT 'Five words in this sentence.'
     UNION ALL 
     SELECT 'Sentence containing more than five words.'
    ), 
    AtLeastThreeWords (ColumnName, pos_word_2_start)
    AS
    (
     SELECT M1.ColumnName, CHARINDEX(' ', M1.ColumnName) + LEN(' ') + 1
       FROM MyTable AS M1
      WHERE LEN(M1.ColumnName) - LEN(REPLACE(M1.ColumnName, ' ', '')) >= 2
    ), 
    MyTable2 (ColumnName, pos_word_3_start)
    AS
    (
     SELECT M1.ColumnName, 
            CHARINDEX(' ', M1.ColumnName, pos_word_2_start) + LEN(' ') + 1
       FROM AtLeastThreeWords AS M1
    ), 
    MyTable3 (ColumnName, pos_word_3_start, pos_word_3_end)
    AS
    (
     SELECT M1.ColumnName, M1.pos_word_3_start, 
            CHARINDEX(' ', M1.ColumnName, pos_word_3_start) + LEN(' ')
       FROM MyTable2 AS M1        
    ), 
    MyTable4 (ColumnName, pos_word_3_start, word_3_length)
    AS
    (
     SELECT M1.ColumnName, M1.pos_word_3_start, 
            CASE 
               WHEN pos_word_3_start < pos_word_3_end 
                  THEN pos_word_3_end - pos_word_3_start
               ELSE LEN(M1.ColumnName) - pos_word_3_start + 1
            END         
       FROM MyTable3 AS M1        
    )
    SELECT M1.ColumnName, 
           SUBSTRING(M1.ColumnName, pos_word_3_start, word_3_length) 
              AS word_3
      FROM MyTable4 AS M1;
    

    原始答案:

    用户名值的位置和/或长度在数据中可能不是恒定的,而是始终跟随字符串“用户名”的问题?如果是这样,您可以将CHARINDEXSUBSTRING 一起使用,例如

    WITH MyTable (ColumnName)
    AS
    (
     SELECT 'Error 192.168.1.67 UserName 0bce6c62-1efb-416d-bce5-71c3c8247b75 An existing ....'
     UNION ALL 
     SELECT 'Username onedaywhen is invalid'
    
    ), 
    MyTable1 (ColumnName, pos1)
    AS
    (
     SELECT M1.ColumnName, CHARINDEX('UserName ', M1.ColumnName) + LEN('UserName ') + 1
       FROM MyTable AS M1
    ), 
    MyTable2 (ColumnName, pos1, pos2)
    AS
    (
     SELECT M1.ColumnName, M1.pos1, 
            CHARINDEX(' ', M1.ColumnName, pos1) - M1.pos1
       FROM MyTable1 AS M1
    )
    SELECT SUBSTRING(M1.ColumnName, M1.pos1, M1.pos2)
      FROM MyTable2 AS M1;
    

    ...尽管您需要使其更健壮,例如当用户名值等后面没有尾随空格时。

    【讨论】:

    • IP 地址可以是任意值。 IE。上面的IP地址192.168.1.89是12个字符,10.5.4.3只有8个字符。字符串“用户名”也不会出现在该字段中。它只是一个实际的用户名'jerryb'或'georget'等。我得到的是我们无法确定用户名的开头在哪里。除非我们可以说“在第二个空格之后找到我的起始字符”。这有意义吗?
    猜你喜欢
    • 2016-10-10
    • 2015-12-26
    • 2012-01-08
    • 2019-09-18
    • 2011-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-18
    相关资源
    最近更新 更多