2013-07-09 40 views
11

如何根据' - '字符分割下列字符串?SQL Server 2005使用CHARINDEX()分割字符串

所以,如果我有这个字符串:LD-23DSP-1430

我怎么可能把它分成单独的列是这样的:

LD  23DSP  1430 

此外,有没有一种方式,如果我每个字符分割成一个单独的领域需要(没有' - ')?我试图找到一种方法来用北约字母替换每个字母。

因此,这将是.....利马三角洲二十三三角洲谢拉帕帕十四十三......在一个领域。

我知道我能得到左边是这样的:

LEFT(@item, CHARINDEX('-', @item) - 1) 
+0

可以使用'substring'功能,并与第一,第二,第三命中CHARINDEX等增加开始索引。 – jpw

+0

@jpw他会如何找到第二个破折号的charindex? –

+0

@RaduGheorghiu通过搜索从第一个破折号+ 1的charindex开始的子字符串中的破折号。 – jpw

回答

9

我不完全说它是容易还是显而易见的,但只有两个连字符,你可以扭转字符串,这是不是太硬盘:

with t as (select 'LD-23DSP-1430' as val) 
select t.*, 
     LEFT(val, charindex('-', val) - 1), 
    SUBSTRING(val, charindex('-', val)+1, len(val) - CHARINDEX('-', reverse(val)) - charindex('-', val)), 
     REVERSE(LEFT(reverse(val), charindex('-', reverse(val)) - 1)) 
from t; 

除此之外,你可能想使用split()代替。

2

尝试以下查询:

DECLARE @item VARCHAR(MAX) = 'LD-23DSP-1430' 

SELECT 
SUBSTRING(@item, 0, CHARINDEX('-', @item)) , 
SUBSTRING(
       SUBSTRING(@item, CHARINDEX('-', @item)+1,LEN(@ITEM)) , 
       0 , 
       CHARINDEX('-', SUBSTRING(@item, CHARINDEX('-', @item)+1,LEN(@ITEM))) 
      ), 
REVERSE(SUBSTRING(REVERSE(@ITEM), 0, CHARINDEX('-', REVERSE(@ITEM)))) 
+0

感谢您的回答!另一个问题。如果某件物品有多个破折号,该怎么办?所以它可能是LD-23DSP-MF-1430有没有一种方法可以统计多少破折号并将每个部分分解为一个字段? – user2531854

4

这里有一个小功能,将做“北约编码”为您提供:

CREATE FUNCTION dbo.NATOEncode (
    @String varchar(max) 
) 
RETURNS TABLE 
WITH SCHEMABINDING 
AS 
RETURN (
    WITH L1 (N) AS (SELECT 1 UNION ALL SELECT 1), 
    L2 (N) AS (SELECT 1 FROM L1, L1 B), 
    L3 (N) AS (SELECT 1 FROM L2, L2 B), 
    L4 (N) AS (SELECT 1 FROM L3, L3 B), 
    L5 (N) AS (SELECT 1 FROM L4, L4 C), 
    L6 (N) AS (SELECT 1 FROM L5, L5 C), 
    Nums (Num) AS (SELECT Row_Number() OVER (ORDER BY (SELECT 1)) FROM L6) 
    SELECT 
     NATOString = Substring((
     SELECT 
      Convert(varchar(max), ' ' + D.Word) 
     FROM 
      Nums N 
      INNER JOIN (VALUES 
       ('A', 'Alpha'), 
       ('B', 'Beta'), 
       ('C', 'Charlie'), 
       ('D', 'Delta'), 
       ('E', 'Echo'), 
       ('F', 'Foxtrot'), 
       ('G', 'Golf'), 
       ('H', 'Hotel'), 
       ('I', 'India'), 
       ('J', 'Juliet'), 
       ('K', 'Kilo'), 
       ('L', 'Lima'), 
       ('M', 'Mike'), 
       ('N', 'November'), 
       ('O', 'Oscar'), 
       ('P', 'Papa'), 
       ('Q', 'Quebec'), 
       ('R', 'Romeo'), 
       ('S', 'Sierra'), 
       ('T', 'Tango'), 
       ('U', 'Uniform'), 
       ('V', 'Victor'), 
       ('W', 'Whiskey'), 
       ('X', 'X-Ray'), 
       ('Y', 'Yankee'), 
       ('Z', 'Zulu'), 
       ('0', 'Zero'), 
       ('1', 'One'), 
       ('2', 'Two'), 
       ('3', 'Three'), 
       ('4', 'Four'), 
       ('5', 'Five'), 
       ('6', 'Six'), 
       ('7', 'Seven'), 
       ('8', 'Eight'), 
       ('9', 'Niner') 
      ) D (Digit, Word) 
       ON Substring(@String, N.Num, 1) = D.Digit 
     WHERE 
      N.Num <= Len(@String) 
     FOR XML PATH(''), TYPE 
    ).value('.[1]', 'varchar(max)'), 2, 2147483647) 
); 

此功能将运行于甚至很长的字符串,和漂亮的执行好吧(我用10万字符的字符串运行它,并在589毫秒内返回)。这里有一个如何使用它的一个例子:

SELECT NATOString FROM dbo.NATOEncode('LD-23DSP-1430'); 
-- Output: Lima Delta Two Three Delta Sierra Papa One Four Three Zero 

我特意做了它的表值函数,因此它可以,如果你运行它反对在一次许多行内联成一个查询,只需使用CROSS APPLY或包裹上面括号中的示例将其用作SELECT子句中的值(可以在函数参数位置放置一个列名)。

+0

酷功能。我似乎无法在SQL 2005上运行它。我得到Msg 156,级别15,状态1,过程NATOEncode,行21 关键字'VALUES'附近的语法不正确。 – user2531854

+0

在SQL 2005中将其更改为'INNER JOIN(SELECT'A','Alpha'UNION ALL SELECT'B','Beta'UNION ALL ...)'。 – ErikE

+0

九号不用于北约字母表,因为它可能与德语中的“否”(Nein)混淆,听起来像九。北约字母表中数字9的正确等值是“niner”。干杯! – levteck

0
USE [master] 
    GO 
    /****** this function returns Pakistan where as if you want to get ireland simply replace (SELECT SUBSTRING(@NEWSTRING,CHARINDEX('[email protected][email protected]$',@NEWSTRING)+5,LEN(@NEWSTRING))) with 
SELECT @NEWSTRING = (SELECT SUBSTRING(@NEWSTRING, 0,CHARINDEX('[email protected][email protected]$',@NEWSTRING)))******/ 
    SET ANSI_NULLS ON 
    GO 
    SET QUOTED_IDENTIFIER ON 
    GO 
    CREATE FUNCTION [dbo].[FN_RETURN_AFTER_SPLITER] 
    ( 
    @SPLITER varchar(max)) 
    RETURNS VARCHAR(max) 
    AS 
    BEGIN 

    --declare @testString varchar(100), 
    DECLARE @NEWSTRING VARCHAR(max) 
    -- set @teststring = '@ram?eez(ali)' 
    SET @NEWSTRING = @SPLITER ; 

    SELECT @NEWSTRING = (SELECT SUBSTRING(@NEWSTRING,CHARINDEX('[email protected][email protected]$',@NEWSTRING)+5,LEN(@NEWSTRING))) 
    return @NEWSTRING 
    END 
    --select [dbo].[FN_RETURN_AFTER_SPLITER] ('[email protected][email protected]$Pakistan') 
0
Create FUNCTION [dbo].[fnSplitString] 
( 
    @string NVARCHAR(200), 
    @delimiter CHAR(1) 
) 
RETURNS @output TABLE(splitdata NVARCHAR(10) 
) 
BEGIN 
    DECLARE @start INT, @end INT 
    SELECT @start = 1, @end = CHARINDEX(@delimiter, @string) 
    WHILE @start < LEN(@string) + 1 BEGIN 
     IF @end = 0 
      SET @end = LEN(@string) + 1 

     INSERT INTO @output (splitdata) 
     VALUES(SUBSTRING(@string, @start, @end - @start)) 
     SET @start = @end + 1 
     SET @end = CHARINDEX(@delimiter, @string, @start) 

    END 
    RETURN 

END**strong text** 
0
DECLARE @variable VARCHAR(100) = 'LD-23DSP-1430'; 
WITH Split 
     AS (SELECT @variable AS list , 
        charone = LEFT(@variable, 1) , 
        R = RIGHT(@variable, LEN(@variable) - 1) , 
        'A' AS MasterOne 
      UNION ALL 
      SELECT Split.list , 
        LEFT(Split.R, 1) , 
        R = RIGHT(split.R, LEN(Split.R) - 1) , 
        'B' AS MasterOne 
      FROM  Split 
      WHERE LEN(Split.R) > 0 
     ) 
SELECT * 
FROM Split 
OPTION (MAXRECURSION 10000);