我有文字,例如包含#(sharp)
字符。字符串包含参数。参数以#开头,以#结束。
declare @TEXT varchar(200) = 'Dear #NAMEOFGUEST# , we glad to see youSOMEHOTEL tomorrow.'
declare @scanChar char(1)='#'
select
SUBSTRING(@TEXT, CHARINDEX(@scanChar, @TEXT) + 1, (((LEN(@TEXT)) - CHARINDEX(@scanChar, REVERSE(@TEXT))) - CHARINDEX(@scanChar, @TEXT)))
返回:
NAMEOFGUEST
这是正确的结果。
当字符串仅包含一个参数#NAMEOFGUEST#
时,它将起作用。如果将 SOMEHOTEL 添加到#中,则#SOMEHOTEL#
的结果不是我们想要的。
declare @TEXT varchar(200) = 'Dear #NAMEOFGUEST# , we glad to see you #SOMEHOTEL# tomorrow.'
declare @scanChar char(1)='#'
返回:
NAMEOFGUEST# , we glad to see you #SOMEHOTEL
我想要与以前相同的结果,仅像 NAMEOFGUEST 。
答案 0 :(得分:3)
使用CHARINDEX(@FindString, @PrintData, CHARINDEX(@FindString, @PrintData) + 1)
,您可以找到#
的第二次出现,然后根据此结果可以完成剩余的计算。
以下查询将起作用。
DECLARE @PrintData AS VARCHAR (200) = 'Dear #NAMEOFGUEST# , we glad to see you #SOMEHOTEL# tomorrow.';
DECLARE @FindString AS CHAR (1) = '#';
DECLARE @LenFindString AS INT = LEN(@FindString);
SELECT SUBSTRING(@PrintData,
CHARINDEX(@FindString, @PrintData) + @LenFindString,
CHARINDEX(@FindString, @PrintData, CHARINDEX(@FindString, @PrintData) + 1) - (CHARINDEX(@FindString, @PrintData) + @LenFindString)
);
答案 1 :(得分:0)
您可以使用如下递归方法:
一个模型表,用于模拟面向集合的场景
declare @tbl TABLE(ID INT IDENTITY, SomeComment VARCHAR(100),SomeString varchar(200));
INSERT INTO @tbl VALUES('3 Terms','Dear #NAMEOFGUEST# , we glad to see you #SOMEHOTEL# tomorrow. And even #AThirdOne# is here.')
,('1 Term','Dear #NAMEOFGUEST# , we glad to see you soon.')
,('No Term','Dear Guest, nice to see you.')
,('invalid 1','Dear Guest, nice to #see you.')
,('invalid ?','Dear #Guest, nice# to see you.');
declare @scanChar char(1)='#';
-查询
WITH recCTE AS
(
SELECT t.ID
,t.SomeComment
,t.SomeString AS TextToWork
,1 AS TermIndex
,D.*
FROM @tbl t
OUTER APPLY(SELECT CHARINDEX(@scanChar,t.SomeString)) A(StartingAt)
OUTER APPLY(SELECT CHARINDEX(@scanChar,t.SomeString,A.StartingAt+1)) B(EndingAt)
OUTER APPLY(SELECT CASE WHEN A.StartingAt>0 AND B.EndingAt >0 THEN SUBSTRING(t.SomeString,A.StartingAt+1,B.EndingAt- A.StartingAt-1) END) C(TermCandidate)
OUTER APPLY(SELECT A.StartingAt,B.EndingAt,C.TermCandidate,SUBSTRING(t.SomeString,B.EndingAt+1,1000) AS RestString) D
UNION ALL
SELECT t.ID
,t.SomeComment
,t.RestString
,t.TermIndex+1
,D.*
FROM recCTE t
OUTER APPLY(SELECT CHARINDEX(@scanChar,t.RestString)) A(StartingAt)
OUTER APPLY(SELECT CHARINDEX(@scanChar,t.RestString,A.StartingAt+1)) B(EndingAt)
OUTER APPLY(SELECT CASE WHEN A.StartingAt>0 AND B.EndingAt >0 THEN SUBSTRING(t.RestString,A.StartingAt+1,B.EndingAt- A.StartingAt-1) END) C(TermCandidate)
OUTER APPLY(SELECT A.StartingAt,B.EndingAt,C.TermCandidate,SUBSTRING(t.RestString,B.EndingAt+1,1000) AS RestString) D
WHERE (LEN(t.RestString) - LEN(REPLACE(t.RestString,@scanChar,'')))%2=0 AND CHARINDEX(@scanChar,t.RestString)>0
)
SELECT ID
,SomeComment
,TermIndex
--this will exclude "Guest, nice" due to the blank
,CASE WHEN CHARINDEX(' ',TermCandidate)>0 THEN NULL ELSE TermCandidate END AS Term
FROM recCTE
ORDER BY ID,TermIndex;
结果
+----+-------------+-----------+-------------+
| ID | SomeComment | TermIndex | Term |
+----+-------------+-----------+-------------+
| 1 | 3 Terms | 1 | NAMEOFGUEST |
+----+-------------+-----------+-------------+
| 1 | 3 Terms | 2 | SOMEHOTEL |
+----+-------------+-----------+-------------+
| 1 | 3 Terms | 3 | AThirdOne |
+----+-------------+-----------+-------------+
| 2 | 1 Term | 1 | NAMEOFGUEST |
+----+-------------+-----------+-------------+
| 3 | No Term | 1 | NULL |
+----+-------------+-----------+-------------+
| 4 | invalid 1 | 1 | NULL |
+----+-------------+-----------+-------------+
| 5 | invalid ? | 1 | NULL |
+----+-------------+-----------+-------------+