Ini adalah jawaban termudah untuk mengambil 67 (type-safe!! ):
SELECT CAST('<x>' + REPLACE('1,222,2,67,888,1111',',','</x><x>') + '</x>' AS XML).value('/x[4]','int')
Berikut ini Anda akan menemukan contoh bagaimana menggunakan ini dengan variabel untuk string, pembatas dan posisi (bahkan untuk kasus tepi dengan karakter terlarang XML)
Yang mudah
Pertanyaan ini bukan tentang pendekatan pemisahan string , tetapi tentang cara mendapatkan elemen ke-n . Cara termudah dan sepenuhnya tidak dapat diluruskan adalah IMO ini:
Ini adalah one-liner asli untuk mendapatkan bagian 2 yang dibatasi oleh spasi:
DECLARE @input NVARCHAR(100)=N'part1 part2 part3';
SELECT CAST(N'<x>' + REPLACE(@input,N' ',N'</x><x>') + N'</x>' AS XML).value('/x[2]','nvarchar(max)')
Variabel dapat digunakan dengan sql:variable()
atau sql:column()
Tentu saja Anda dapat menggunakan variabel untuk pembatas dan posisi (gunakan sql:column
untuk mengambil posisi langsung dari nilai kueri):
DECLARE @dlmt NVARCHAR(10)=N' ';
DECLARE @pos INT = 2;
SELECT CAST(N'<x>' + REPLACE(@input,@dlmt,N'</x><x>') + N'</x>' AS XML).value('/x[sql:variable("@pos")][1]','nvarchar(max)')
Edge-Case dengan karakter terlarang XML
Jika string Anda mungkin menyertakan karakter terlarang , Anda masih bisa melakukannya dengan cara ini. Cukup gunakan FOR XML PATH
pada string Anda terlebih dahulu untuk mengganti semua karakter terlarang dengan urutan escape yang pas secara implisit.
Ini adalah kasus yang sangat khusus jika - selain itu - pembatas Anda adalah titik koma . Dalam hal ini saya mengganti pembatas terlebih dahulu menjadi '#DLMT#', dan akhirnya mengganti ini dengan tag XML:
SET @input=N'Some <, > and &;Other äöü@€;One more';
SET @dlmt=N';';
SELECT CAST(N'<x>' + REPLACE((SELECT REPLACE(@input,@dlmt,'#DLMT#') AS [*] FOR XML PATH('')),N'#DLMT#',N'</x><x>') + N'</x>' AS XML).value('/x[sql:variable("@pos")][1]','nvarchar(max)');
PERBARUI untuk SQL-Server 2016+
Sayangnya pengembang lupa mengembalikan indeks bagian dengan STRING_SPLIT
. Tapi, menggunakan SQL-Server 2016+, ada JSON_VALUE
dan OPENJSON
.
Dengan JSON_VALUE
kita dapat meneruskan posisi sebagai array indeks.
Untuk OPENJSON
dokumentasi menyatakan dengan jelas:
Saat OPENJSON mem-parsing larik JSON, fungsi mengembalikan indeks elemen dalam teks JSON sebagai kunci.
String seperti 1,2,3
hanya membutuhkan tanda kurung:[1,2,3]
.
Rangkaian kata seperti this is an example
harus ["this","is","an"," example"]
.
Ini adalah operasi string yang sangat mudah. Coba saja:
DECLARE @str VARCHAR(100)='Hello John Smith';
DECLARE @position INT = 2;
--We can build the json-path '$[1]' using CONCAT
SELECT JSON_VALUE('["' + REPLACE(@str,' ','","') + '"]',CONCAT('$[',@position-1,']'));
--Lihat ini untuk pemisah string yang aman (berbasis nol ):
SELECT JsonArray.[key] AS [Position]
,JsonArray.[value] AS [Part]
FROM OPENJSON('["' + REPLACE(@str,' ','","') + '"]') JsonArray
Dalam posting ini saya menguji berbagai pendekatan dan menemukan, bahwa OPENJSON
benar-benar cepat. Bahkan jauh lebih cepat daripada metode "delimitedSplit8k()" yang terkenal...
PERBARUI 2 - Dapatkan nilai type-safe
Kita dapat menggunakan array di dalam array cukup dengan menggunakan [[]]
dua kali lipat . Ini memungkinkan untuk mengetik WITH
-klausa:
DECLARE @SomeDelimitedString VARCHAR(100)='part1|1|20190920';
DECLARE @JsonArray NVARCHAR(MAX)=CONCAT('[["',REPLACE(@SomeDelimitedString,'|','","'),'"]]');
SELECT @SomeDelimitedString AS TheOriginal
,@JsonArray AS TransformedToJSON
,ValuesFromTheArray.*
FROM OPENJSON(@JsonArray)
WITH(TheFirstFragment VARCHAR(100) '$[0]'
,TheSecondFragment INT '$[1]'
,TheThirdFragment DATE '$[2]') ValuesFromTheArray