Я натрапив на цю тему, шукаючи рішення для моєї подібної проблеми, яка мала точно таку ж вимогу, але стосувалася бази даних іншого типу, яка також не мала REVERSE
функції.
У моєму випадку це було для бази даних OpenEdge (Прогрес) , яка має дещо інший синтаксис. Це зробило 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