SQL Server中是否有LastIndexOf?


75

我试图分析出从涉及获取一个字符串值最后一个 指标一个的字符串。目前,我正在做一个骇人的骇客工作,其中涉及反转字串:

SELECT REVERSE(SUBSTRING(REVERSE(DB_NAME()), 1, 
    CHARINDEX('_', REVERSE(DB_NAME()), 1) - 1))

对我来说,这段代码几乎是不可读的。我刚刚升级到SQL Server 2016,希望有更好的方法。在那儿?


2
您可以显示一些字符串示例吗?
瓦姆西·普拉巴拉

对我来说,这不仅不可读,而且没有示例数据也无法猜测您要实现的目标:)
techspider 16/08/17

6
一定喜欢Stack Overflow,即使问题不需要更多信息来解决,人们的第一反应就是要求提供更多信息:)
Sam Williams

Answers:


191

如果您想要在last之后的所有内容_,请使用:

select right(db_name(), charindex('_', reverse(db_name()) + '_') - 1)

如果您之前想要所有东西,请使用left()

select left(db_name(), len(db_name()) - charindex('_', reverse(db_name()) + '_'))

我必须将第一个表达式更改为:right(db_name(), charindex('_', reverse(db_name()) + '_') - 1)使其工作!否则很棒!
伊甘

左侧也应具有类似于右侧的“ -1”的偏移量。应该是:(select left(db_name(), len(db_name()) - charindex('_', reverse(db_name()) + '_') + 1)我尝试进行编辑,但是更改必须至少包含6个字符。)
Joakim MH,

1
“ +'_'`部分是否可以处理数据库名称中没有_的情况?
mlhDev

1
@mlhDev。。。是的,这就是目的。
Gordon Linoff

21

编写了2个函数,其中1个为所选字符返回LastIndexOf

CREATE FUNCTION dbo.LastIndexOf(@source nvarchar(80), @pattern char)
RETURNS int
BEGIN  
       RETURN (LEN(@source)) -  CHARINDEX(@pattern, REVERSE(@source)) 
END;  
GO

1返回此LastIndexOf之前的字符串。也许对某人有用。

CREATE FUNCTION dbo.StringBeforeLastIndex(@source nvarchar(80), @pattern char)
RETURNS nvarchar(80)
BEGIN  
       DECLARE @lastIndex int
       SET @lastIndex = (LEN(@source)) -  CHARINDEX(@pattern, REVERSE(@source)) 

     RETURN SUBSTRING(@source, 0, @lastindex + 1) 
     -- +1 because index starts at 0, but length at 1, so to get up to 11th index, we need LENGTH 11+1=12
END;  
GO

5

不,SQL Server没有LastIndexOf。

这是可用的字符串函数

但是您始终可以创建自己的功能

CREATE FUNCTION dbo.LastIndexOf(@source text, @pattern char)  
RETURNS 
AS       
BEGIN  
    DECLARE @ret text;  
    SELECT into @ret
           REVERSE(SUBSTRING(REVERSE(@source), 1, 
           CHARINDEX(@pattern, REVERSE(@source), 1) - 1))
    RETURN @ret;  
END;  
GO 

4

一旦从这里有了一个分割字符串,就可以像这样基于集合的方式来实现。

declare @string varchar(max)
set @string='C:\Program Files\Microsoft SQL Server\MSSQL\DATA\AdventureWorks_Data.mdf'

;with cte
as
(select *,row_number() over (order by (select null)) as rownum
from [dbo].[SplitStrings_Numbers](@string,'\')
)
select top 1 item from cte order by rownum desc

**Output:**  
AdventureWorks_Data.mdf

4
CREATE FUNCTION dbo.LastIndexOf(@text NTEXT, @delimiter NTEXT)  
RETURNS INT
AS       
BEGIN  
  IF (@text IS NULL) RETURN NULL;
  IF (@delimiter IS NULL) RETURN NULL;
  DECLARE @Text2 AS NVARCHAR(MAX) = @text;
  DECLARE @Delimiter2 AS NVARCHAR(MAX) = @delimiter;
  DECLARE @Index AS INT = CHARINDEX(REVERSE(@Delimiter2), REVERSE(@Text2));
  IF (@Index < 1) RETURN 0;
  DECLARE @ContentLength AS INT = (LEN('|' + @Text2 + '|') - 2);
  DECLARE @DelimiterLength AS INT = (LEN('|' + @Delimiter2 + '|') - 2);
  DECLARE @Result AS INT = (@ContentLength - @Index - @DelimiterLength + 2);
  RETURN @Result;
END
  • 允许使用多字符定界符,例如“,”(逗号空间)。
  • 如果找不到分隔符,则返回0。
  • 出于舒适性原因而采用NTEXT,因为NVARCHAR(MAX)被隐式转换为NTEXT,反之则不然。
  • 正确处理带有前导或尾部空格的定界符!

2

我在寻找类似问题的解决方案时遇到了这个问题,该解决方案具有完全相同的要求,但针对的是缺少该REVERSE功能的另一种数据库。

在我的情况下,这是针对OpenEdge(Progress)数据库的,该数据库的语法略有不同。这使INSTR我可以使用大多数Oracle类型数据库提供的功能

所以我想出了以下代码:

SELECT 
  INSTR(foo.filepath, '/',1, LENGTH(foo.filepath) - LENGTH( REPLACE( foo.filepath, '/',  ''))) AS IndexOfLastSlash 
FROM foo

但是,对于我的特定情况(作为OpenEdge(Progress)数据库),这并没有导致所需的行为,因为用空字符替换字符会得到与原始字符串相同的长度。这对我来说没有多大意义,但是我可以使用以下代码绕过该问题:

SELECT 
  INSTR(foo.filepath, '/',1, LENGTH( REPLACE( foo.filepath, '/',  'XX')) - LENGTH(foo.filepath))  AS IndexOfLastSlash 
FROM foo

现在,我知道此代码不会解决T-SQL的问题,因为INSTR提供该Occurence属性的函数别无选择。

为了更全面,我将添加创建此标量函数所需的代码,以便可以像在上面的示例中一样使用它。并且将完全按照OP的要求进行操作,用作SQL Server的LastIndexOf方法。

  -- 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

0

尝试这个。

drop table #temp
declare @brokername1 nvarchar(max)='indiabullssecurities,canmoney,indianivesh,acumencapitalmarket,sharekhan,edelweisscapital';
Create Table #temp
(
ID int identity(1,1) not null,
value varchar(100) not null
)

INSERT INTO #temp(value) SELECT value from STRING_SPLIT(@brokername1,',')
declare @id int;
set @id=(select max(id) from #temp)
--print @id
declare @results varchar(500)
select @results = coalesce(@results + ',', '') +  convert(varchar(12),value)
from #temp where id<@id
order by id
print @results
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.