2017-03-06 49 views
0

想象一下,我有以下字符串: “SELECT * FROM TABLE_1 INNER JOIN TABLE_2 ON table_1.A = table_2.B”T-SQL - 斯普利特的下一个单词后两个特定词

我想提取两张表的声明为了得到: table_1; TABLE_2。

基本上我需要在字符串From和Join之后得到下一个单词。我用下面的查询尝试:

DECLARE @StaffName nvarchar(4000) 
SET @StaffName = 'Select * From table_1 INNER JOIN table_2 ON table_1.A = table_2.B' 

SELECT SUBSTRING 
    (
    @StaffName, 
     CHARINDEX('From', @StaffName), 
    CHARINDEX(' ', SUBSTRING(@StaffName, CHARINDEX(' ', @StaffName), 255)) 
) , 
    SUBSTRING(@StaffName, CHARINDEX('From ', @StaffName) + 5, LEN(@StaffName)) 
    , 
    SUBSTRING(@StaffName, CHARINDEX('From ', @StaffName) + 5, LEN(@StaffName)) 
    , 
    RIGHT(@StaffName,LEN(@StaffName)-CHARINDEX('From ',@StaffName)) 

但我没有得到我想要的东西:(

任何人都可以帮助我

非常感谢

+0

当第一表是'[用户加入俱乐部]',第二个是'[女童玛]“你期望什么? – HABO

+0

@HABO我需要收集字符串所有的表...在这种情况下,我想提取俱乐部和Ipanema –

回答

2

看着SQLZim的回答是完全有效的(+1),让我意识到,我已经厌倦了提取字符串的部分。因此,我修改了我的解析函数以接受两个多字符分隔符。所以,IF你是开放的UDF,考虑以下因素:

在一个侧面说明:作为一个表值,功能,很容易将其纳入一个跨应用或作为一个单一的查询

对于您的具体要求,我们正在和寻找的FROM关键词ON

Declare @String varchar(max) = 'Select * From table_1 INNER JOIN table_2 ON table_1.A = table_2.B' 
Select Table1 = left(RetVal,charindex(' ',RetVal+' ')-1) 
     ,Table2 = right(RetVal,charindex(' ',reverse(RetVal)+' ')-1) 
From [dbo].[udf-Str-Extract] (@String,' from ',' on ') 

返回

Table1 Table2 
table_1 table_2 

一般示例:

比方说,我们正在寻找之间{}的价值观

Declare @String varchar(max) = 'co-101{12345},co-513{22578}' 
Select * From [dbo].[udf-Str-Extract] (@String,'{','}') 

返回

RetSeq RetPos RetLen RetVal 
1  8  5  12345 
2  22  5  22578 

另一个通用示例

Declare @String varchar(max) = '<root><firstmame>John</firstname><lastname>Cappelletti</lastname><phone>(401) 555-1212</phone></root>' 
Select * From [dbo].[udf-Str-Extract] (@String,'>','<') 

返回

RetSeq RetPos RetLen RetVal 
1  18  4  John 
2  44  11  Cappelletti 
3  73  14  (401) 555-1212 

的UDF如果有意

CREATE FUNCTION [dbo].[udf-Str-Extract] (@String varchar(max),@Delimiter1 varchar(100),@Delimiter2 varchar(100)) 
Returns Table 
As 
Return ( 

with cte1(N) As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)), 
     cte2(N) As (Select Top (IsNull(DataLength(@String),0)) Row_Number() over (Order By (Select NULL)) From (Select N=1 From cte1 N1,cte1 N2,cte1 N3,cte1 N4,cte1 N5,cte1 N6) A), 
     cte3(N) As (Select 1 Union All Select t.N+DataLength(@Delimiter1) From cte2 t Where Substring(@String,t.N,DataLength(@Delimiter1)) = @Delimiter1), 
     cte4(N,L) As (Select S.N,IsNull(NullIf(CharIndex(@Delimiter1,@String,s.N),0)-S.N,8000) From cte3 S) 

Select RetSeq = Row_Number() over (Order By N) 
     ,RetPos = N 
     ,RetLen = charindex(@Delimiter2,RetVal)-1 
     ,RetVal = left(RetVal,charindex(@Delimiter2,RetVal)-1) 
From (Select A.N,RetVal = ltrim(rtrim(Substring(@String, A.N, A.L))) From cte4 A) A 
Where charindex(@Delimiter2,RetVal)>1 
) 
/* 
Max Length of String 1MM characters 

Declare @String varchar(max) = 'Dear [[FirstName]] [[LastName]], ...' 
Select * From [dbo].[udf-Str-Extract] (@String,'[[',']]') 
*/ 
+0

这很漂亮,漂亮的工作+1 – SqlZim

1

使用组合?!中left()right(),charindex()

declare @str varchar(256) = 'Select * From table_1 INNER JOIN table_2 ON table_1.A = table_2.B'; 

select 
    tbl1 = left(right(@str,len(@str)-charindex(' From ',@str)-5) 
     ,charindex(' ',right(@str,len(@str)-charindex(' From ',@str)-5))-1 
     ) 
    , tbl2 = left(right(@str,len(@str)-charindex(' Join ',@str)-5) 
     ,charindex(' ',right(@str,len(@str)-charindex(' Join ',@str)-5))-1 
     ) 

rextester演示:http://rextester.com/WOO86939

回报:

+---------+---------+ 
| tbl1 | tbl2 | 
+---------+---------+ 
| table_1 | table_2 | 
+---------+---------+ 
+0

您的启发我修改了一个解析函数,通过两个分隔符提取字符串+1 –

+0

@SqlZim但想象一下我有10桌(或者我不知道我有多少桌)在这种情况下,我不能使用左或右声明 –

+0

@PedroAlves是真的,如果是这样的话,那应该是在你的问题下次。为什么问一个不能准确反映问题的问题? – SqlZim