Saya menemukan utas ini saat mencari solusi untuk masalah saya yang serupa yang memiliki persyaratan yang sama persis tetapi untuk jenis database yang berbeda yang juga tidak memiliki REVERSE
fungsi.
Dalam kasus saya ini adalah untuk database OpenEdge (Progress) , yang memiliki sintaks yang sedikit berbeda. Ini membuat INSTR
fungsi tersedia untuk saya yang ditawarkan sebagian besar tipe database Oracle .
Jadi saya datang dengan kode berikut:
SELECT
INSTR(foo.filepath, '/',1, LENGTH(foo.filepath) - LENGTH( REPLACE( foo.filepath, '/', ''))) AS IndexOfLastSlash
FROM foo
Namun, untuk situasi spesifik saya (menjadi basis data OpenEdge (Progress) ) ini tidak menghasilkan perilaku yang diinginkan karena mengganti karakter dengan char kosong memberikan panjang yang sama dengan string asli. Ini tidak masuk akal bagi saya tetapi saya dapat mem-bypass masalah dengan kode di bawah ini:
SELECT
INSTR(foo.filepath, '/',1, LENGTH( REPLACE( foo.filepath, '/', 'XX')) - LENGTH(foo.filepath)) AS IndexOfLastSlash
FROM foo
Sekarang saya mengerti bahwa kode ini tidak akan menyelesaikan masalah untuk T-SQL karena tidak ada alternatif untuk INSTR
fungsi yang menawarkan Occurence
properti.
Hanya untuk menyeluruh saya akan menambahkan kode yang diperlukan untuk membuat fungsi skalar ini sehingga dapat digunakan dengan cara yang sama seperti yang saya lakukan pada contoh di atas.
-- 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
Untuk menghindari hal yang jelas, ketika REVERSE
fungsi tersedia, Anda tidak perlu membuat fungsi skalar ini dan Anda hanya bisa mendapatkan hasil yang diperlukan seperti ini:
SELECT
LEN(foo.filepath) - CHARINDEX('/', REVERSE(foo.filepath))+1 AS LastIndexOfSlash
FROM foo