【问题标题】:How to get SQL substring?如何获取 SQL 子字符串?
【发布时间】:2014-05-25 16:51:05
【问题描述】:

我有一列包含如下值:

“AAAA\BBBBBBBB\CCC”(A、B、C部分长度不固定)

如果存在 \CCC 部分,我需要删除它,如果不存在,则不要理会它。

例如:

AAA\BBBBBB\CCC -> AAA\BBBBBB

AA\BBBB -> AA\BBBB

AA -> AA

对不起,我不够清楚,A、B、C 部分并不是字面上的 ABC,它们可以是任何内容。

还应该删除 \DDD\EEEE(etc.)

【问题讨论】:

  • 你应该找到第三个斜线并截断之后的文本
  • 所以你能澄清一下:这是必须替换的第二个'\'之后的部分吗?还是和'\'的个数无关?
  • 是否有可能存在 \DDD 段?如果是这样,你想用它做什么?
  • @Crono 是的,它可能是。我想要的只是删除前 2 个部分之后的部分。

标签: sql sql-server tsql substring


【解决方案1】:

虽然在纯 T-SQL 中肯定有一种方法可以做到这一点,但它可能还不够清晰。

您可能需要考虑改用基于 SQLCLR 的用户定义函数 (UDF)。这样,您将能够受益于 Sql Server 中(或)的强大功能和清晰度。

只要做到这一点,您的函数将接收您的字符串作为参数,并将您想要的输出作为标量值返回。从那时起,您将能够像使用您可能已经拥有的任何其他 UDF 一样使用该功能。这样,您的代码将更容易编写(以及之后的阅读/维护)。

您的 函数可以像这样容易编写(伪代码):

public static string SpecialSubstring(string input)
{
    if (input == null) return null;

    var builder = new StringBuilder();
    var occurences = 0;

    for (i = 0; i < input.Length; i++;)
    {
        var current = input[i];

        if (current == '\') occurences += 1;
        if (occurences >= 2) break;

        builder.Append(current)
    }

    return builder.ToString();
}

然后,从 T-SQL:

SELECT
    [owningschema].SpecialSubstring('AAA\BBBBBB\CCC'), -- returns 'AAA\BBBBBB'
    [owningschema].SpecialSubstring('AA\BBBB'),, -- returns 'AA\BBBB'
    [owningschema].SpecialSubstring('AA') -- returns 'AA'

此页面将为您提供入门所需的几乎所有内容:

SQL Server Common Language Runtime Integration

【讨论】:

  • +1 我过去创建了 SQL CLR 函数来公开 .Net 框架 RegEx 引擎的全部功能,因为 SQL 本身非常缺乏这些东西。
  • @StevePettifer 我做了同样的事情。当正确使用并用于正确的任务时,SQLCLR 使执行某些操作变得更加容易。有时它甚至胜过 T-SQL。
  • 这个。特别是如果它不止一次查询。 (虽然如果它不止一次查询,请考虑更改底层数据结构。)一个 TSql 版本的所有字符串函数都会非常昂贵。
【解决方案2】:

如果有两个或多个部分(用\分隔),这是删除最后一部分的解决方案

DECLARE @var VARCHAR(32) = 'AAAA\BBBBBBBB\CCC'

SELECT
    LEN(@var) - LEN(REPLACE(@var, '\', '')) -- Number of occurences of the character \

    , CHARINDEX('\', @var) -- Position of the first occurence
    , LEN(@var) - CHARINDEX('\', REVERSE(@var)) -- Position of the last occurence

    , CASE WHEN LEN(@var) - LEN(REPLACE(@var, '\', '')) > 1 AND CHARINDEX('\', @var) !=  LEN(@var) - CHARINDEX('\', REVERSE(@var))
        THEN SUBSTRING(@var, 1, LEN(@var) - CHARINDEX('\', REVERSE(@var)))
        ELSE @var
    END

【讨论】:

    【解决方案3】:

    您可以使用PATINDEX 找出该字段是否有 3 个(或更多)部分,然后进行一些字符串操作以删除最后一部分:

    select case 
           when PATINDEX(field, '%\%\%') > 0 then 
               /* Chop off last part */
               LEFT(field, len(field) - charindex('\', reverse(field)))
           else
               field
           end case as choppedfield
      from my_table
    

    【讨论】:

      【解决方案4】:

      这就是我完成这项任务的方式:

      declare @temp varchar(50), @temp2 varchar(15), @temp3 varchar(15)
      set @temp = 'aaaa\bbbb\cccc\dddd'
      
      IF (SELECT LEFT(@temp,CHARINDEX('\',@temp, CHARINDEX('\',@temp,0)+1))) != ''
          BEGIN
            SELECT LEFT(LEFT(@temp,CHARINDEX('\',@temp, CHARINDEX('\',@temp,0)+1)),LEN(LEFT(@temp,CHARINDEX('\',@temp, CHARINDEX('\',@temp,0)+1)))-1)
          END
      ELSE
          BEGIN
            select @temp
          END
      

      将其粘贴到查询窗口中,并使用不同的@temp 值对其进行尝试。它会快速检查是否存在两个'\',并将其修剪到第二个'\' 之前的字符位置。如果存在少于两个'\'s,它只会返回值本身。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-04-07
        • 2017-04-18
        • 2013-03-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-30
        相关资源
        最近更新 更多