Firebird saklı prosedürü, satırı ayraçlarla bölerek kayıt kümesine dönüştürür.
Bu, Firebird PSQL üzerinde çalışan her geliştiricinin er ya da geç karşılaştığı görevlerden biridir - sınırlayıcılar içeren bir satırı ayrı değerler dizisine nasıl böleriz? Şöyle bir şey:
select * from sp_split_into_words('foo rio bar firebird,mysql,postgresql;mssql;redis/rty');
Çıktı:
######
WORD
==========
foo
rio
bar
firebird
mysql
postgresql
mssql
redis
rty
Bunu saf SQL ile yapmak mümkündür - lütfen aşağıdaki saklı prosedür kodunu kullanın, yazarı Pavel Zotov, Firebird QA mühendisi ve IBSurgeon baş DBA’sıdır.
Lütfen bu prosedürün boşluk dahil geniş bir olası sınırlayıcı listesi içerdiğini unutmayın, bu nedenle yalnızca virgül veya noktalı virgüle ihtiyacınız varsa, diğer sınırlayıcıları a_del değişkeninden kaldırabilirsiniz.
Ayrıca, döndürülen varchar boyutuna (return değişkeni word) dikkat edin - varsayılan olarak varchar(50)‘dir, ihtiyaçlarınıza göre ayarlayabilirsiniz.
set term ^;
create or alter procedure sp_split_into_words(
a_text varchar(2048) character set utf8,
a_dels varchar(20) default ',.<>/?;:''"[]{}`~!@#$%^&*()-_=+\|/',
a_special char(1) default ' '
)
returns (
word varchar(50)
) as
begin
-- Yalnızca oltp_data_filling.sql içinde PATTERNS tablosunu doldurmak için kullanılan yardımcı SP
-- SIMILAR TO testinde kullanılacak kelimelerin çeşitli kombinasyonlarıyla.
for
with recursive
j as( -- döngü #1: sınırlayıcı listesini satırlara dönüştür
select s,1 i, substring(s from 1 for 1) del
from(
select replace(:a_dels,:a_special,'') s
from rdb$database
)
UNION ALL
select s, i+1, substring(s from i+1 for 1)
from j
where substring(s from i+1 for 1)<>''
)
,d as(
select :a_text s, :a_special sp from rdb$database
)
,e as( -- döngü #2: her sınırlayıcıyı `boşluk` ile değiştir
select d.s, replace(d.s, j.del, :a_special) s1, j.i, j.del
from d join j on j.i=1
UNION ALL
select e.s, replace(e.s1, j.del, :a_special) s1, j.i, j.del
from e
-- nb: burada 'column unknown: e.i' hatası 2.5'in eski sürümlerinde oluşur,
-- örn: WI-V2.5.2.26540 (Alexey Kovyazin'den mektup, 24.08.2014 14:34)
join j on j.i = e.i + 1
)
,f as(
select s1 from e order by i desc rows 1
)
,r as ( -- döngü #3: metni tek tek kelimelere böl
select iif(t.k>0, substring(t.s from t.k+1 ), t.s) s,
iif(t.k>0,position( del, substring(t.s from t.k+1 )),-1) k,
t.i,
t.del,
iif(t.k>0,left(t.s, t.k-1),t.s) word
from(
select f.s1 s, d.sp del, position(d.sp, s1) k, 0 i from f cross join d
)t
UNION ALL
select iif(r.k>0, substring(r.s from r.k+1 ), r.s) s,
iif(r.k>0,position(r.del, substring(r.s from r.k+1 )),-1) k,
r.i+1,
r.del,
iif(r.k>0,left(r.s, r.k-1),r.s) word
from r
where r.k>=0
)
select word from r where word>''
into
word
do
suspend;
end
^
set term ;^
commit;