2013-07-09 44 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);