cod*_*ori 11 sql-server-2005 sql-server string-searching
如何patindex
在表格或变量中找到所有位置?
declare @name nvarchar(max)
set @name ='ali reza dar yek shabe barani ba yek '
+ 'dokhtare khoshkel be disco raft va ali baraye'
+ ' 1 saat anja bud va sepas... ali...'
select patindex('%ali%',@name) as pos
Run Code Online (Sandbox Code Playgroud)
这会返回1
但我想要所有结果,例如:
pos
===
1
74
113
Run Code Online (Sandbox Code Playgroud)
Aar*_*and 15
我认为这将比您选择的循环方法(这里有一些证据)更有效,并且绝对比递归 CTE 更有效:
CREATE FUNCTION dbo.FindPatternLocation
(
@string NVARCHAR(MAX),
@term NVARCHAR(255)
)
RETURNS TABLE
AS
RETURN
(
SELECT pos = Number - LEN(@term)
FROM (SELECT Number, Item = LTRIM(RTRIM(SUBSTRING(@string, Number,
CHARINDEX(@term, @string + @term, Number) - Number)))
FROM (SELECT ROW_NUMBER() OVER (ORDER BY [object_id])
FROM sys.all_objects) AS n(Number)
WHERE Number > 1 AND Number <= CONVERT(INT, LEN(@string)+1)
AND SUBSTRING(@term + @string, Number, LEN(@term)) = @term
) AS y);
Run Code Online (Sandbox Code Playgroud)
示例用法:
DECLARE @name NVARCHAR(MAX);
SET @name = N'ali reza dar yek shabe barani ba yek'
+ ' dokhtare khoshkel be disco raft va ali baraye '
+ '1 saat anja bud va sepas... ali...';
SELECT pos FROM dbo.FindPatternLocation(@name, 'ali');
Run Code Online (Sandbox Code Playgroud)
结果:
pos
---
1
74
113
Run Code Online (Sandbox Code Playgroud)
如果您的字符串将超过 2K,则使用 sys.all_columns 而不是 sys.all_objects。如果长于 8K,则添加交叉连接。
declare @name nvarchar(max)
set @name ='ali reza dar yek shabe barani ba yek dokhtare khoshkel be disco raft va ali baraye 1 saat anja bud va sepas... ali...'
Declare @a table (pos int)
Declare @pos int
Declare @oldpos int
Select @oldpos=0
select @pos=patindex('%ali%',@name)
while @pos > 0 and @oldpos<>@pos
begin
insert into @a Values (@pos)
Select @oldpos=@pos
select @pos=patindex('%ali%',Substring(@name,@pos + 1,len(@name))) + @pos
end
Select * from @a
Run Code Online (Sandbox Code Playgroud)
为了使其可重用,您可以在表函数中使用它来调用它:
Select * from dbo.F_CountPats ('ali reza dar yek shabe barani ba yek dokhtare khoshkel be disco raft va ali baraye 1 saat anja bud va sepas... ali...','%ali%')
Run Code Online (Sandbox Code Playgroud)
该功能可能如下所示
Create FUNCTION [dbo].[F_CountPats]
(
@txt varchar(max),
@Pat varchar(max)
)
RETURNS
@tab TABLE
(
ID int
)
AS
BEGIN
Declare @pos int
Declare @oldpos int
Select @oldpos=0
select @pos=patindex(@pat,@txt)
while @pos > 0 and @oldpos<>@pos
begin
insert into @tab Values (@pos)
Select @oldpos=@pos
select @pos=patindex(@pat,Substring(@txt,@pos + 1,len(@txt))) + @pos
end
RETURN
END
GO
Run Code Online (Sandbox Code Playgroud)