有没有一种简单的方法使用SQL查找字符串的最后一次出现的索引?我目前正在使用SQL Server 2000。基本上,我需要 .NET System.String.LastIndexOf
方法提供的功能。通过一些谷歌搜索发现了这个链接 - 检索最后索引的函数 - 但是如果您传递 "text" 列表达式,它将无法工作。在其他地方找到的解决方案只在搜索的文本长度为1字符时有效。
我可能需要编写一个函数。如果我这样做,我会在这里发布它,以便您们可以查看并可能利用它。
有没有一种简单的方法使用SQL查找字符串的最后一次出现的索引?我目前正在使用SQL Server 2000。基本上,我需要 .NET System.String.LastIndexOf
方法提供的功能。通过一些谷歌搜索发现了这个链接 - 检索最后索引的函数 - 但是如果您传递 "text" 列表达式,它将无法工作。在其他地方找到的解决方案只在搜索的文本长度为1字符时有效。
我可能需要编写一个函数。如果我这样做,我会在这里发布它,以便您们可以查看并可能利用它。
有直接的方法吗?没有,但我使用了反转。字面意思。
在之前的例程中,要查找给定字符串的最后一个出现位置,我使用了REVERSE()函数,然后是CHARINDEX,再次使用REVERSE恢复原始顺序。例如:
SELECT
mf.name
,mf.physical_name
,reverse(left(reverse(physical_name), charindex('\', reverse(physical_name)) -1))
from sys.master_files mf
示范如何从“物理名称”中提取实际数据库文件名,无论它们嵌套在子文件夹中多深。这只搜索一个字符(反斜杠),但您可以在此基础上构建更长的搜索字符串。
唯一的缺点是,我不知道这对TEXT数据类型的处理效果如何。 我已经使用SQL 2005几年了,不再熟悉TEXT - 但我记得你可以在其上使用LEFT和RIGHT?
Philip
最简单的方法是....
REVERSE(SUBSTRING(REVERSE([field]),0,CHARINDEX('[expr]',REVERSE([field]))))
[expr]
长度超过1个符号,你也需要将其反转! - Andrius NaruševičiusREVERSE
函数会对性能产生不利影响,下面的代码更有效率。DECLARE @FilePath VARCHAR(50) = 'My\Super\Long\String\With\Long\Words'
DECLARE @FindChar VARCHAR(1) = '\'
-- text before last slash
SELECT LEFT(@FilePath, LEN(@FilePath) - CHARINDEX(@FindChar,REVERSE(@FilePath))) AS Before
-- text after last slash
SELECT RIGHT(@FilePath, CHARINDEX(@FindChar,REVERSE(@FilePath))-1) AS After
-- the position of the last slash
SELECT LEN(@FilePath) - CHARINDEX(@FindChar,REVERSE(@FilePath)) + 1 AS LastOccuredAt
PATINDEX
开始,但是从DATALENGTH-1,DATALENGTH-2,DATALENGTH-3
等逆向推导,直到得出结果或者回溯到零(DATALENGTH-DATALENGTH)为止。SQL Server 2000
无法处理的事情。
其他答案的编辑:在SQL Server 2000中,REVERSE不在可用于文本数据的函数列表中。DATALENGTH
返回的是字节数而不是字符数。因此,对于NVARCHAR
字符串,DATALENGTH
返回的是字符串中字符数的2倍。然而,LEN
返回的是字符数,减去任何尾随空格。我从不使用DATALENGTH
来计算字符长度,除非尾随空格很重要,并且我确定我的数据类型是一致的,无论它们是VARCHAR
还是NVARCHAR
。 - rbsdcaDECLARE @FilePath VARCHAR(50) = 'My\Super\Long\String\With\Long\Words'
DECLARE @FindChar VARCHAR(1) = '\'
SELECT LEN(@FilePath) - CHARINDEX(@FindChar,REVERSE(@FilePath)) AS LastOccuredAt
虽然这是一个古老但仍然有效的问题,以下是我根据其他人提供的信息所创建的答案。
create function fnLastIndexOf(@text varChar(max),@char varchar(1))
returns int
as
begin
return len(@text) - charindex(@char, reverse(@text)) -1
end
REVERSE(SUBSTRING(REVERSE([field]), CHARINDEX(REVERSE('[expr]'), REVERSE([field])) + DATALENGTH('[expr]'), DATALENGTH([field])))
REVERSE(SUBSTRING(REVERSE(ap_description),CHARINDEX('.',REVERSE(ap_description)),len(ap_description)))
在我看来,它的表现更好
嗯,我知道这是一个旧贴子,但在SQL2000(或任何其他数据库)中可以使用计数表来完成此操作:
DECLARE @str CHAR(21),
@delim CHAR(1)
SELECT @str = 'Your-delimited-string',
@delim = '-'
SELECT
MAX(n) As 'position'
FROM
dbo._Tally
WHERE
substring(@str, _Tally.n, 1) = @delim
substring(@str, _Tally.n, 1) = @delim
获取每个分隔符的位置,然后只需获取该集合中的最大位置。n <= LEN(TEXT_FIELD)
,因为您不能在TEXT类型上使用LEN()。 只要substring(...) = @delim
仍然正确,结果仍然正确。CREATE FUNCTION [dbo].[fn_LastIndexOf]
(@String NVARCHAR(MAX)
, @FindString NVARCHAR(MAX))
RETURNS INT
AS
BEGIN
DECLARE @ReturnVal INT = 0
IF CHARINDEX(@FindString,@String) > 0
SET @ReturnVal = (SELECT LEN(@String) -
(CHARINDEX(REVERSE(@FindString),REVERSE(@String)) +
LEN(@FindString)) + 2)
RETURN @ReturnVal
END
DECLARE @TestString NVARCHAR(MAX) = 'My_sub2_Super_sub_Long_sub1_String_sub_With_sub_Long_sub_Words_sub2_'
, @TestFindString NVARCHAR(MAX) = 'sub'
SELECT dbo.fn_LastIndexOf(@TestString,@TestFindString)
我只在MS SQL Server 2008上运行过此项操作,因为我无法使用其他版本,不过根据我的了解,该方法至少适用于2008+。
祝使用愉快。