有没有找到使用SQL字符串中最后一次出现的索引的一种简单的方法? 我使用SQL Server 2000的现在。 基本上,我需要的是.NET的功能System.String.LastIndexOf
方法提供。 一个小Googling透露这一点- 函数来获取最后一个索引 -但如果你在“文本”列表达式传递不起作用。 在其他地方找到其他的解决方案只工作,只要您正在搜索的文本为1个字符长。
我可能会做饭的功能了。 如果我这样做,我将它张贴在这里,所以你的乡亲可以看看它,也许利用。
有没有找到使用SQL字符串中最后一次出现的索引的一种简单的方法? 我使用SQL Server 2000的现在。 基本上,我需要的是.NET的功能System.String.LastIndexOf
方法提供。 一个小Googling透露这一点- 函数来获取最后一个索引 -但如果你在“文本”列表达式传递不起作用。 在其他地方找到其他的解决方案只工作,只要您正在搜索的文本为1个字符长。
我可能会做饭的功能了。 如果我这样做,我将它张贴在这里,所以你的乡亲可以看看它,也许利用。
你是有限的功能小列表的文本数据类型。
所有我可以建议是开始PATINDEX
,但向后工作DATALENGTH-1, DATALENGTH-2, DATALENGTH-3
等,直到你得到的结果,或者在零结束(DATALENGTH,DATALENGTH)
这确实是一件SQL Server 2000
根本无法处理。
编辑其他答案 :REVERSE是不是可以用文本数据在SQL Server 2000中使用的功能列表中
简单的方法是什么? 没有,但我已经使用了反向。 从字面上看。
在以前的套路,找到一个给定的字符串的最后一个实例,我用REVERSE()函数,然后CHARINDEX,随后再次反向恢复原来的秩序。 例如:
SELECT
mf.name
,mf.physical_name
,reverse(left(reverse(physical_name), charindex('\', reverse(physical_name)) -1))
from sys.master_files mf
显示了如何从他们的“物理名称”提取实际的数据库文件名,不管有多深嵌套子文件夹中。 但这仅搜索一个字符(反斜线),但你可以建立在这个较长的搜索字符串。
唯一不足的是,我不知道该怎么好,这将文本数据类型的工作。 我一直在几年SQL 2005,现在,我没有用TEXT工作更精通 - 但我似乎记得,你可以使用左右就可以了?
菲利普
最简单的方法是....
REVERSE(SUBSTRING(REVERSE([field]),0,CHARINDEX('[expr]',REVERSE([field]))))
如果使用的是sqlserver的2005或以上,使用REVERSE
功能很多次会降低性能,下面的代码是更有效的。
DECLARE @FilePath VARCHAR(50) = 'My\Super\Long\String\With\Long\Words'
DECLARE @FindChar VARCHAR(1) = '\'
-- Shows text before last slash
SELECT LEFT(@FilePath, LEN(@FilePath) - CHARINDEX(@FindChar,REVERSE(@FilePath))) AS Before
-- Shows text after last slash
SELECT RIGHT(@FilePath, CHARINDEX(@FindChar,REVERSE(@FilePath))-1) AS After
-- Shows the position of the last slash
SELECT LEN(@FilePath) - CHARINDEX(@FindChar,REVERSE(@FilePath)) AS LastOccuredAt
DECLARE @FilePath VARCHAR(50) = 'My\Super\Long\String\With\Long\Words'
DECLARE @FindChar VARCHAR(1) = '\'
SELECT LEN(@FilePath) - CHARINDEX(@FindChar,REVERSE(@FilePath)) AS LastOccuredAt
这个工作对我非常好。
REVERSE(SUBSTRING(REVERSE([field]), CHARINDEX(REVERSE('[expr]'), REVERSE([field])) + DATALENGTH('[expr]'), DATALENGTH([field])))
老了,但仍然有效的问题的基础上,由他人这里提供的信息,以便继承人是我创建的。
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(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
获取每个分隔符的位置,那么你只能在该组的最大位置。
理货表是真棒。 如果你以前没有使用过他们,有一个很好的文章SQL Server管理中心 (免费REG,或者只是使用虫不知( http://www.bugmenot.com/view/sqlservercentral.com ))。
*编辑:删除n <= LEN(TEXT_FIELD)
因为你不能在TEXT类型使用LEN()。 只要substring(...) = @delim
仍尽管结果仍然是正确的。
反向既您的字符串和你的子,然后搜索第一次出现。
我意识到这是一个好几年的老问题,但...
在Access 2010
,您可以使用InStrRev()
来做到这一点。 希望这可以帮助。
我知道,这将是低效的,但是你有没有考虑铸造text
字段varchar
,这样你可以使用该网站提供的解决方案,你发现了什么? 我知道,这个解决方案会产生问题,你可能会截断记录,如果在长度text
字段溢出您的长度varchar
(更不用说它不会是非常高性能的)。
由于您的数据是内部text
字段(和你正在使用SQL Server 2000),您的选择是有限的。
@indexOf = <whatever characters you are searching for in your string>
@LastIndexOf = LEN([MyField]) - CHARINDEX(@indexOf, REVERSE([MyField]))
没有测试,它可能是由一个因为零指数处于关闭状态,但在工作SUBSTRING
从斩去时功能@indexOf
字符来结束你的字符串
SUBSTRING([MyField], 0, @LastIndexOf)
一些其他的答案返回一个实际的字符串,而我更需要知道实际的指数INT。 而且这样做似乎是答案的事情过分复杂化。 使用一些其他的答案为灵感的,我做了以下...
首先,我创建了一个功能:
CREATE FUNCTION [dbo].[LastIndexOf] (@stringToFind varchar(max), @stringToSearch varchar(max))
RETURNS INT
AS
BEGIN
RETURN (LEN(@stringToSearch) - CHARINDEX(@stringToFind,REVERSE(@stringToSearch))) + 1
END
GO
然后,在你的查询,你可以简单地这样做:
declare @stringToSearch varchar(max) = 'SomeText: SomeMoreText: SomeLastText'
select dbo.LastIndexOf(':', @stringToSearch)
上述应返回23(最后指数“:”)
希望这使得它的人更容易一些!
这个答案使用MS SQL Server 2008中(我没有访问MS SQL Server 2000中),但我根据OP看到它的方式是3种情况来考虑。 从我已经试过没有答案在这里涵盖了所有的人都3:
0
我想出了这个功能需要两个参数:
@String NVARCHAR(MAX)
在被搜索的字符串
@FindString NVARCHAR(MAX)
无论是单个字符或子串来获得在最后一个索引@String
它返回一个INT
是任阳性指数@FindString
在@String
或0
含义@FindString
不在@String
这里的功能所做的解释:
@ReturnVal
至0
指示@FindString
不在@String
@FindString
在@String
通过使用CHARINDEX()
@FindString
在@String
是0
, @ReturnVal
保留为0
@FindString
在@String
是> 0
, @FindString
是在@String
所以它计算的最后一个索引@FindString
在@String
通过使用REVERSE()
@ReturnVal
其或者正数即最后索引@FindString
在@String
或0
指示@FindString
不在@String
下面是创建功能脚本(复制和粘贴准备):
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+至少是好的。
请享用。
如果你想获得最后空间的指数一串字,你可以用这个表达RIGHT(名称,(CHARINDEX(””,反向(名称),0))返回字符串中的最后一个字。这如果你想解析出包括第一和/或中间名缩写全名的姓氏是有帮助的。
我需要找到一个文件夹路径反斜杠的第n个最后的位置。 这里是我的解决方案。
/*
http://stackoverflow.com/questions/1024978/find-index-of-last-occurrence-of-a-sub-string-using-t-sql/30904809#30904809
DROP FUNCTION dbo.GetLastIndexOf
*/
CREATE FUNCTION dbo.GetLastIndexOf
(
@expressionToFind VARCHAR(MAX)
,@expressionToSearch VARCHAR(8000)
,@Occurrence INT = 1 -- Find the nth last
)
RETURNS INT
AS
BEGIN
SELECT @expressionToSearch = REVERSE(@expressionToSearch)
DECLARE @LastIndexOf INT = 0
,@IndexOfPartial INT = -1
,@OriginalLength INT = LEN(@expressionToSearch)
,@Iteration INT = 0
WHILE (1 = 1) -- Poor man's do-while
BEGIN
SELECT @IndexOfPartial = CHARINDEX(@expressionToFind, @expressionToSearch)
IF (@IndexOfPartial = 0)
BEGIN
IF (@Iteration = 0) -- Need to compensate for dropping out early
BEGIN
SELECT @LastIndexOf = @OriginalLength + 1
END
BREAK;
END
IF (@Occurrence > 0)
BEGIN
SELECT @expressionToSearch = SUBSTRING(@expressionToSearch, @IndexOfPartial + 1, LEN(@expressionToSearch) - @IndexOfPartial - 1)
END
SELECT @LastIndexOf = @LastIndexOf + @IndexOfPartial
,@Occurrence = @Occurrence - 1
,@Iteration = @Iteration + 1
IF (@Occurrence = 0) BREAK;
END
SELECT @LastIndexOf = @OriginalLength - @LastIndexOf + 1 -- Invert due to reverse
RETURN @LastIndexOf
END
GO
GRANT EXECUTE ON GetLastIndexOf TO public
GO
这里是我的测试案例,其通过
SELECT dbo.GetLastIndexOf('f','123456789\123456789\', 1) as indexOf -- expect 0 (no instances)
SELECT dbo.GetLastIndexOf('\','123456789\123456789\', 1) as indexOf -- expect 20
SELECT dbo.GetLastIndexOf('\','123456789\123456789\', 2) as indexOf -- expect 10
SELECT dbo.GetLastIndexOf('\','1234\6789\123456789\', 3) as indexOf -- expect 5
为了分隔符的最后一次出现之前获得的部分(仅适用于NVARCHAR
由于DATALENGTH
用法):
DECLARE @Fullstring NVARCHAR(30) = '12.345.67890.ABC';
DECLARE @Delimiter CHAR(1) = '.';
SELECT SUBSTRING(@Fullstring, 1, DATALENGTH(@Fullstring)/2 - CHARINDEX(@Delimiter, REVERSE(@Fullstring)));
这个答案符合OP的要求。 具体地,其允许针为比单个字符更并且当在草堆未找到针它不产生一个错误。 在我看来,其他的答案大多数(全部?)没有处理的边缘情况。 除此之外,我还通过本地MS SQL服务器CHARINDEX函数提供“起始位置”的说法。 我试图为CHARINDEX规范准确反映除了到左,而不是从左到右程序的权利。 例如,我返回null如果任一针或草垛为空,我回零,如果针头未在草堆里找到。 有一两件事,我无法避开的是,与内置的函数的第三个参数是可选。 在SQL Server用户自定义函数,所有参数必须在通话中提供,除非该功能是使用“EXEC”之称。 而第三个参数必须包含在参数列表中,您可以提供关键字“默认”作为它的占位符,而不必给它一个值(见下面的例子)。 因为它是比较容易,如果不希望这个函数删除第三个参数比起来,如果需要,我在这里为起点,包括它来添加。
create function dbo.lastCharIndex(
@needle as varchar(max),
@haystack as varchar(max),
@offset as bigint=1
) returns bigint as begin
declare @position as bigint
if @needle is null or @haystack is null return null
set @position=charindex(reverse(@needle),reverse(@haystack),@offset)
if @position=0 return 0
return (len(@haystack)-(@position+len(@needle)-1))+1
end
go
select dbo.lastCharIndex('xyz','SQL SERVER 2000 USES ANSI SQL',default) -- returns 0
select dbo.lastCharIndex('SQL','SQL SERVER 2000 USES ANSI SQL',default) -- returns 27
select dbo.lastCharIndex('SQL','SQL SERVER 2000 USES ANSI SQL',1) -- returns 27
select dbo.lastCharIndex('SQL','SQL SERVER 2000 USES ANSI SQL',11) -- returns 1
我碰到这个线程来同时寻找解决我类似的问题,其中有完全相同的要求,但对于不同类型的数据库,这也是缺乏REVERSE
功能。
在我的情况,这是一个OpenEdge(进度)数据库,该数据库有一个稍微不同的语法。 这使得INSTR
提供的功能,我认为大多数Oracle数据库的输入提供 。
所以,我想出了下面的代码:
SELECT
INSTR(foo.filepath, '/',1, LENGTH(foo.filepath) - LENGTH( REPLACE( foo.filepath, '/', ''))) AS IndexOfLastSlash
FROM foo
但是,对于我的具体情况(为OpenEdge(进度)数据库),这并不会导致到所需的行为,因为用空字符替换字符给了相同长度的原始字符串。 这并没有太大的意义给我,但我能够绕过与下面的代码的问题:
SELECT
INSTR(foo.filepath, '/',1, LENGTH( REPLACE( foo.filepath, '/', 'XX')) - LENGTH(foo.filepath)) AS IndexOfLastSlash
FROM foo
现在我明白了,因为没有替代这个代码将不会解决T-SQL的问题INSTR
,提供的功能Occurence
财产。
只是要彻底的,我会加入到创建此标量函数,因此可以使用相同的方式就像我在上面的例子中确实需要的代码。
-- Drop the function if it already exists
IF OBJECT_ID('INSTR', 'FN') IS NOT NULL
DROP FUNCTION INSTR
GO
-- User-defined function to implement Oracle INSTR in SQL Server
CREATE FUNCTION 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
为了避免明显的,当REVERSE
功能可用,你不需要创建这个标量函数和你可以得到这样的要求的结果:
SELECT
LEN(foo.filepath) - CHARINDEX('/', REVERSE(foo.filepath))+1 AS LastIndexOfSlash
FROM foo
此代码的工作,即使子包含超过1个字符。
DECLARE @FilePath VARCHAR(100) = 'My_sub_Super_sub_Long_sub_String_sub_With_sub_Long_sub_Words'
DECLARE @FindSubstring VARCHAR(5) = '_sub_'
-- Shows text before last substing
SELECT LEFT(@FilePath, LEN(@FilePath) - CHARINDEX(REVERSE(@FindSubstring), REVERSE(@FilePath)) - LEN(@FindSubstring) + 1) AS Before
-- Shows text after last substing
SELECT RIGHT(@FilePath, CHARINDEX(REVERSE(@FindSubstring), REVERSE(@FilePath)) -1) AS After
-- Shows the position of the last substing
SELECT LEN(@FilePath) - CHARINDEX(REVERSE(@FindSubstring), REVERSE(@FilePath)) AS LastOccuredAt