left last index hasta ejemplos charindex caracter sql sql-server sql-server-2016

hasta - ¿Hay un LastIndexOf en SQL Server?



sql substring hasta un caracter (6)

Encontré este hilo mientras buscaba una solución a mi problema similar que tenía exactamente el mismo requisito, pero era para un tipo diferente de base de datos que carecía de la función REVERSE .

En mi caso, esto fue para una base de datos OpenEdge (Progreso) , que tiene una sintaxis ligeramente diferente. Esto hizo que la función INSTR disponible para mí que la mayoría de las bases de datos de tipo Oracle ofrecen .

Así que se me ocurrió el siguiente código:

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

Sin embargo, para mi situación específica (siendo la base de datos OpenEdge (Progress) ) esto no resultó en el comportamiento deseado porque reemplazar el carácter por un carácter vacío dio la misma longitud que la cadena original. Esto no tiene mucho sentido para mí, pero pude evitar el problema con el siguiente código:

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

Ahora entiendo que este código no solucionará el problema para T-SQL porque no hay alternativa a la función INSTR que ofrece la propiedad INSTR .

Solo para ser exhaustivo, agregaré el código necesario para crear esta función escalar para que pueda usarse de la misma manera que lo hice en los ejemplos anteriores. Y hará exactamente lo que el OP quería, servirá como un método LastIndexOf para SQL Server.

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

Para evitar lo obvio, cuando la función REVERSE está disponible, no necesita crear esta función escalar y puede obtener el resultado requerido de esta manera:

SELECT LEN(foo.filepath) - CHARINDEX(''/', REVERSE(foo.filepath))+1 AS LastIndexOfSlash FROM foo

Estoy tratando de analizar un valor de una cadena que implica obtener el last index de una string . Actualmente, estoy haciendo un truco horrible que implica revertir una cadena:

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

Para mí este código es casi ilegible. Acabo de actualizar a SQL Server 2016 y espero que haya una mejor manera. ¿Esta ahí?


Escribió 2 funciones, 1 para devolver LastIndexOf para el carácter seleccionado.

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

y 1 para devolver una cadena antes de este LastIndexOf. Tal vez sea de utilidad para alguien.

CREATE FUNCTION dbo.StringBeforeLastIndex(@source nvarchar(20), @pattern char) RETURNS nvarchar(20) 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


No, el servidor SQL no tiene LastIndexOf.

Estas son las functions cadena disponibles functions

Pero siempre puedes crear tu propia función.

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


Si quieres todo después del último _ , usa:

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

Si quieres todo antes, usa left() :

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


Una vez que tenga una de las cadenas divididas de aquí , puede hacerlo de una manera basada en un conjunto como este ...

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


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

  • Permite delimitadores de múltiples caracteres como "," (espacio de coma).
  • Devuelve 0 si no se encuentra el delimitador.
  • Toma un NTEXT por razones de comodidad, ya que los NVARCHAR (MAX) se convierten implícitamente en NTEXT, pero no al revés.
  • Maneja los delimitadores con el espacio inicial o de cola correctamente!