2016-11-04 33 views
0

你好,我是堆栈溢出新手,虽然我一直在使用本网站搜索多年的答案。所以我有这个问题从一个非常长的字符串中提取各种具体的细节。问题是,字符串不是静态的,没有固定的索引,所以我不能使用子字符串函数。字符串输出的例子是这样的。从动态字符串源提取特定字

Sample 1: 
1 AJ 552 O 9/28/2016 0:0:0 6 PSI KTL 0 GK 2 9/28/2016 7:20:0 9/28/2016 8:35:0 O20YEARS 32.2400 

Sample 2: 
1 AJ 2552 O 10/8/2016 0:0:0 6 PSI KTL 0 GK 2 10/28/2016 7:0:0 9/28/2016 8:5:0 O20YEARS 32.2400 

正如你所看到的,字符串的索引相应的调整。因此我不能依赖于固定子功能。

我是相当新的SQL,并希望你的意见,我应该如何处理这个。

到目前为止,我试过的方法只有子串。

UPDATE:

对不起,我忘了提,我没有任何字符或字符串中提取数据的基础上。我从这个字符串中提取了一个确切的部分。例如,

Sample 1: 
1 AJ 552 O 9/28/2016 0:0:0 6 PSI KTL 0 GK 2 9/28/2016 7:20:0 9/28/2016 8:35:0 O20YEARS 32.2400 

我需要因此从技术提取的第一个日期是“2016年9月28日”和“PSI KTL”

,我需要从字符串中提取一定的第n个字。

现在,我试图使用空格作为分隔符,并将每个单词分配到临时表中,但它似乎不是现在的工作。

谢谢!

+0

'提取不同或特定details' ...你试图提取? –

+0

什么是目标标记字符串? –

+0

已更新。对困惑感到抱歉。 :) – Calvs

回答

0

试试这个:

CREATE FUNCTION GetWordBasedOnIndex(@text varchar(max),@index int) 
RETURNS varchar(50) 
AS 
BEGIN 
    DECLARE @RET VARCHAR(50),@counter int 
    SET @text = LTRIM(RTRIM(@text)) 
    SET @counter = 1 
    IF @counter < @index 
    BEGIN 
      SET @text = LTRIM(RTRIM(SUBSTRING(@text, CHARINDEX(' ',@text,1), LEN(@text) - CHARINDEX(' ',@text,1)+1))) 
      SET @text = dbo.GetWordBasedOnIndex(@text,@index-1) 
    END 
    IF CHARINDEX(' ',@text,1)=0 SET @RET = @text 
    ELSE SET @RET = SUBSTRING(@text,@counter,CHARINDEX(' ',@text,1)) 
    RETURN @RET 
END 

declare @string nvarchar(max) 
set @string = '1 AJ 552 O 9/28/2016 0:0:0 6 PSI KTL 0 GK 2 9/28/2016 7:20:0 9/28/2016 8:35:0 O20YEARS 32.2400'; 
SELECT DBO.GetWordBasedOnIndex(@string, 5) 

如果从表中传递,并采取字基于索引:

declare @string nvarchar(max) 
set @string = '1 AJ 552 O 9/28/2016 0:0:0 6 PSI KTL 0 GK 2 9/28/2016 7:20:0 9/28/2016 8:35:0 O20YEARS 32.2400'; 
SELECT [dbo].[GetWordBasedOnIndex](@string, 5) 


CREATE table #temp (msg nvarchar(max)) 
INSERT INTO #temp VALUES(@string) 
SELECT [dbo].[GetWordBasedOnIndex](msg, 5) as test from #temp 

drop table #temp 
+0

谢谢詹姆斯,这解决了我的问题。 :) – Calvs

+0

嗨@詹姆斯。你的回答是非常有用的,但是像这样使用它。 SELECT \t bh.Detail, \t(SELECT [REZ5JWB01] [DBO]。[GetWordBasedOnIndex](bh.Details,13))作为试验 给我一个不同的输出。而不是,给字符串参数一个值,我直接从表中提供它。对此有何想法? – Calvs

+0

你的意思是这样的: SELECT a.test from (SELECT [dbo]。[GetWordBasedOnIndex](永久地址,2)作为来自yourtable的测试)a – James

0

请试试这个:

DECLARE @s varchar(8000) 
DECLARE @s2 varchar(8000) 


set @s = '1 AJ 552 O 9/28/2016 0:0:0 6 PSI KTL 0 GK 2 9/28/2016 7:20:0 9/28/2016 8:35:0 O20YEARS 32.2400'; 

SET @s2 =SUBSTRING(@s, CHARINDEX('PSI KTL', @s), 8000) 

select SUBSTRing(@s2, PATINDEX('%__/__/____%', @s2), 10) 

UPDATE:

如果你正在寻找解析使用空间分隔字符串,可以使用SQL 2016或类似的UDF功能的其他版本的String_Split:如果您在使用的SQL Server 2016

DECLARE @s varchar(max) 

set @s = '1 AJ 2552 O 10/8/2016 0:0:0 6 PSI KTL 0 GK 2 10/28/2016 7:0:0 9/28/2016 8:5:0 O20YEARS 32.2400'; 
SET @s = replace(@s, ' ', ' '); -- Here, you can replace other white spaces by single space. 

WITH cte 
AS (
     SELECT *, 
       ROW_NUMBER() Over(ORDER BY (SELECT null)) as RN 
     from string_split(@s, ' ') 
    ) 
     SELECT * FROM cte 
     WHERE RN = 15 
+1

不错的尝试,只是更新长度为8000而不是9999,以防止下一个错误:给'varchar'类型的大小(9999)超过了任何数据类型(8000)所允许的最大值。 –

+0

@ahmedab​​delqader,谢谢艾哈迈德,代码已更新。 –

0

另一种简单的解决方案,

1)使用STRING_SPLIT函数使用指定的分隔符分割字符表达式。

3)经由使用ISDATE功能

2)最后使用Top 1为retriving第一行检测的日期值。

如下所示: -

SELECT TOP 1 * 
FROM STRING_SPLIT ('1 AJ 552 O 9/28/2016 0:0:0 6 PSI KTL 0 GK 2 9/28/2016 7:20:0 9/28/2016 8:35:0 O20YEARS 32.2400 
', ' ') 
WHERE ISDATE(value) = 1 

结果:

value 
9/28/2016