Я наткнулся на эту ветку, когда искал решение моей аналогичной проблемы, которая имела те же требования, но была для другого типа базы данных, в которой также не хватало 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
свойство.
Чтобы быть внимательным, я добавлю код, необходимый для создания этой скалярной функции, чтобы ее можно было использовать так же, как и в приведенных выше примерах.
-- 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