2012-04-18 64 views
2

我试过使用patindex和charindex,但似乎他们都不会轻易做我想做的事。 Charindex只需要一次搜索一个符号,并且patindex不允许“搜索”索引,不允许我循环查找符号的所有索引。我有什么选择?如何查找varchar中所有特殊符号的位置?

+2

什么是特殊符号?他们有什么特别的? – 2012-04-18 06:09:13

+0

对不起,我应该澄清,任何符号如/,。 & - 或空间。我想保留任何我发现的符号,它们不能被删除 – 2012-04-19 04:54:43

回答

2

没有关于什么是“特殊符号”的具体细节,如何存储以及您期望的输出是一些猜测工作,但我认为我的答案的基本原则可以适用。获取所有事件的关键是使用递归CTE以及OUTER APPLY。每次CTE循环时,它都会用一个空格替换一个特殊字符,直到没有特殊字符为止,随着字符的存在而存储字符的位置。

样本数据:

DECLARE @SpecialSymbols TABLE (Symbol CHAR(1) NOT NULL PRIMARY KEY) 
INSERT @SpecialSymbols VALUES ('@'), ('.'), ('['), (']') 

DECLARE @TestData TABLE (StringToTest VARCHAR(100)) 
INSERT @TestData VALUES 
    ('test 1 [Using Square Brackets]'), 
    ('[[email protected]]'), 
    ('No Special Symbols') 

实际查询

;WITH CTE AS 
( SELECT *, STUFF(StringToTest, Position, 1, ' ') [ReworkedString] 
    FROM @TestData 
      OUTER APPLY 
      ( SELECT CHARINDEX(Symbol, StringToTest) [Position], Symbol 
       FROM @SpecialSymbols 
      ) Symbols 
    WHERE Position > 0 
    UNION ALL 
    SELECT StringToTest, Symbols.Position, Symbols.Symbol, STUFF(ReworkedString, Symbols.Position, 1, ' ') [ReworkedString] 
    FROM CTE 
      OUTER APPLY 
      ( SELECT CHARINDEX(Symbol, ReworkedString) [Position], Symbol 
       FROM @SpecialSymbols 
       WHERE Symbol = CTE.Symbol 
      ) Symbols 
    WHERE Symbols.Position > 0 
) 

-- CTE NOW LOOKS LIKE: 
-- | test 1 [[Using Square Brackets] | 8 | [ | test 1 [Using Square Brackets] 
-- | test 1 [[Using Square Brackets] | 30 | ] | test 1 [[Using Square Brackets 
-- | [[email protected]]   | 20 | . | [[email protected] com] 
-- | [[email protected]]   | 7 | @ | [Test2 EmailAddress.com] 
-- | [[email protected]]   | 1 | [ | [email protected]] 
-- | [[email protected]]   | 24 | ] | [[email protected] 
-- | test 1 [[Using Square Brackets] | 9 | [ | test 1 Using Square Brackets] 

SELECT a.StringToTest, COALESCE(Location, '') [SpecialSymbolLocations] 
FROM @TestData a 
     LEFT JOIN 
     ( SELECT DISTINCT 
        StringToTest, 
        -- THIS MERELY CONCATENATES ROWS INTO COLUMNS TO GET COMMA SEPARATED LIST 
        STUFF((SELECT ', ' + CONVERT(VARCHAR, Position) 
          FROM CTE b 
          WHERE a.StringToTest = b.StringToTest 
          ORDER BY Position 
          FOR XML PATH('') 
        ), 1, 2, '') [Location] 
      FROM CTE a 
     ) b 
      ON a.StringToTest = b.StringToTest 

的CTE可以请你真是的,但是为了完整起见,我已添加使用最终查询被操纵SQL server XML Extension to concatenate将特殊符号的位置放入逗号分隔列表中,并将它们放在每个原始字符串的旁边。所以最终的输出如下:

| StringToTest      | SpecialSymbolLocations | 
|-----------------------------------|---------------------------| 
| test 1 [[Using Square Brackets] | 8, 9, 31     | 
| [[email protected]]   | 1, 7, 20, 24    | 
| No Special Symbols    |       | 
相关问题