我想知道在SQL Server中是否有与Oracle INSTR
函数相同的功能?
我知道有CHARINDEX
和PATINDEX
,但是对于Oracle版本,我也可以指定我正在寻找的角色的第N个外观。
Oracle
INSTR
:instr( string1, string2 [, start_position [, **nth_appearance** ] ] )
CHARINDEX
几乎让我在那里,但我希望从字符串中字符的 nth_appearance
开始。
答案 0 :(得分:4)
您认为SQL Server中不存在nth_appearance
。
无耻地复制为您的问题创建的函数(Equivalent of Oracle's INSTR with 4 parameters in SQL Server)(请注意@Occurs的使用方式与Oracle不同 - 您不能指定“3rd appearance”,但“发生3次” ):
CREATE FUNCTION udf_Instr
(@str1 varchar(8000), @str2 varchar(1000), @start int, @Occurs int)
RETURNS int
AS
BEGIN
DECLARE @Found int, @LastPosition int
SET @Found = 0
SET @LastPosition = @start - 1
WHILE (@Found < @Occurs)
BEGIN
IF (CHARINDEX(@str1, @str2, @LastPosition + 1) = 0)
BREAK
ELSE
BEGIN
SET @LastPosition = CHARINDEX(@str1, @str2, @LastPosition + 1)
SET @Found = @Found + 1
END
END
RETURN @LastPosition
END
GO
SELECT dbo.udf_Instr('x','axbxcxdx',1,4)
GO
DROP FUNCTION udf_Instr
GO
答案 1 :(得分:0)
将@str1 varchar(8000), @str2 varchar(1000)
更改为@str1 varchar(1000), @str2 varchar(8000)
或
将CHARINDEX(@str1, @str2, @LastPosition + 1)
更改为CHARINDEX(@str2, @str1, @LastPosition + 1)
答案 2 :(得分:0)
您可以使用以下UDF(内联函数而不是标量)
CREATE FUNCTION dbo.INSTR
(
@str VARCHAR(8000),
@Substr VARCHAR(1000),
@start INT ,
@Occurance INT
)
RETURNS TABLE
AS
RETURN
WITH Tally (n) AS
(
SELECT TOP (LEN(@str)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM (VALUES (0),(0),(0),(0),(0),(0),(0),(0)) a(n)
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) b(n)
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) c(n)
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) d(n)
)
, Find_N_STR as
(
SELECT
CASE WHEN DENSE_RANK() OVER(PARTITION BY @Substr ORDER BY (CHARINDEX(@Substr ,@STR ,N))) = @Occurance
THEN MAX(N-@start +1) OVER (PARTITION BY CHARINDEX(@Substr ,@STR ,N) )
ELSE 0
END [Loc]
FROM Tally
WHERE CHARINDEX(@Substr ,@STR ,N) > 0
)
SELECT Loc= MAX(Loc)
FROM Find_N_STR
WHERE Loc > 0
使用方法:
declare @T table
(
Name_Level_Class_Section varchar(25)
)
insert into @T values
('Jacky_1_B2_23'),
('Johnhy_1_B2_24'),
('Peter_2_A5_3')
select t.Name_Level_Class_Section , l.Loc
from @t t
cross apply dbo.INSTR (t.Name_Level_Class_Section, '_',1,2) l
答案 3 :(得分:0)
这是 Oracle 的 INSTR 函数的一个版本,它也适用于反向查找的负位置,根据 Oracle 的 Doc here:- https://docs.oracle.com/cd/B28359_01/olap.111/b28126/dml_functions_1103.htm#OLADM564
CREATE FUNCTION dbo.INSTR(@str NVARCHAR(MAX), @substr NVARCHAR(MAX), @position INT = 1, @occurance INT = 1)
RETURNS INT
AS
BEGIN
DECLARE @loc INT = @position;
IF @loc < 0
BEGIN
SET @str = REVERSE(@str);
SET @substr = REVERSE(@substr);
SET @loc = @loc * -1;
END
IF @loc > 0
BEGIN
SET @loc = @loc - 1;
END
WHILE (@occurance > 0 AND CHARINDEX(@substr, @str, @loc + 1) > 0)
BEGIN
SET @loc = CHARINDEX(@substr, @str, @loc + 1);
SET @occurance = @occurance - 1;
END
IF @occurance > 0
BEGIN
SET @loc = 0;
END
IF @position < 0
BEGIN
SET @loc = LEN(@str) - @loc;
END
RETURN @loc
END
答案 4 :(得分:-1)
试试这个!!
CREATE FUNCTION dbo.INSTR (@str VARCHAR(8000), @substr VARCHAR(255), @start INT, @occurrence INT)
RETURNS INT
AS
BEGIN
DECLARE @found INT = @occurrence,
@pos INT = @start;
WHILE 1=1
BEGIN
-- Find the next occurrence
SET @pos = CHARINDEX(@substr, @str, @pos);
-- Nothing found
IF @pos IS NULL OR @pos = 0
RETURN @pos;
-- The required occurrence found
IF @found = 1
BREAK;
-- Prepare to find another one occurrence
SET @found = @found - 1;
SET @pos = @pos + 1;
END
RETURN @pos;
END
GO
用法:
- 找到第二次出现的字母&#39; o
选择dbo.INSTR(&#39;莫斯科&#39;,&#39; o&#39;,1,2);
- 结果:5