В некоторых случаях при использовании хранимых процедур ну очень хочется иметь механизм получения нескольких строк в select где значения строк определяются содержанием параметра запроса. Как это сделать в Cache?Наша задача - принять перечень значений в виде одной строки - параметра запроса, которые разделены разделителем или как-то еще, например с разделителем - запятой. При выполнении запроса мы должны получить столько строк сколько этих значений передано в строке. Для развертывания строки - параметра применим идеи статей Cache': Как сделать select from dual и Cache': Где наши данные?.
Вынудим движок Cache применить select к определенному нами способу хранения так, чтобы перед обращением к нему мы могли принять параметр и сконструировать в локальной переменной такую конструкцию, из которой Cache взяла бы наши строки как строки sql таблицы. Назовем группу имен для этого трюка Expand. Экспериментировать будем с версией 5.0.
Создадим класс persistent с именем User.Expand, в котором и определим необходимые нам сущности:
Class User.Expand Extends %Persistent [ ClassType = persistent,
Not ProcedureBlock, SqlTableName = EXPAND ]
{
}
Чтобы принять значения параметров из строки, мы должны соблюдать соглашения SQL
о передаче параметров и принять значение до того, как sql движок обратится к
нашей условной таблице. Это можем сделать в написанной нами хранимой процедуре,
которая примет значение параметра и по нему сконструирует с локальной переменной
таблицу.
Class User.Expand Extends %Persistent [ ClassType = persistent,
Not ProcedureBlock, SqlTableName = EXPAND ]
{
ClassMethod Expand(Arg1 As %String) As %String [ SqlProc ]
{
k zzzzexpand
n i
f i=1:1:$l(Arg1,",") s zzzzexpand($p(Arg1,",",i))=""
q ""
}
}
При этом нам надо определить хранение данных так, чтобы sql движок достал наши
данные как данные таблицы и стал применять к ним операции sql. Модифицируем
способ хранения таблицы соответствующим способом:
Class User.Expand Extends %Persistent [ ClassType = persistent,
Not ProcedureBlock, SqlTableName = EXPAND ]
{
ClassMethod Expand(Arg1 As %String) As %String [ SqlProc ]
{
k zzzzexpand
n i
f i=1:1:$l(Arg1,",") s zzzzexpand($p(Arg1,",",i))=""
q ""
}
<Storage name="Default">
<Data name="ExpandDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
</Data>
<DataLocation>zzzzexpand</DataLocation>
<DefaultData>ExpandDefaultData</DefaultData>
<IdLocation>zzzzexpand</IdLocation>
<IndexLocation>zzzzexpand</IndexLocation>
<StreamLocation>zzzzexpand</StreamLocation>
<Type>%Library.CacheStorage</Type>
</Storage>
}
В результате получили возможность передать извне через хранимую процедуру
значения в нашу условную таблицу. Например:
USER>d $System.SQL.Shell()
>>select ID, Expand_Expand('a,b,c,d,e,f') from Expand
(1)>>go
a
b
c
d
e
f
>>
В отличие от результатов экспериментов с условной таблицей dual в "Cache':
Как сделать select from dual" мы явно и извне, с
использованием параметра, задаем сколько строк нужно получить в select и какие у
них должны быть значения.
Можем сделать view, которые будут возвращать заранее заданные наборы строк с заданными значениями, например:
create view abcdef1 as select ID,
Expand_Expand('a,b,c,d,e,f') from Expand
create view abcdef as select ID from abcdef1
>>select * from abcdef
(1)>>go
a
b
c
d
e
f
>>
В отличие от гарантированности результата select из псевдотаблицы Dual в случае
псевдотаблицы Expand я пока не могу дать гарантированного решения с несколькими
такими таблицами в одном запросе, поскольку пока они используют одну и ту же
локальную переменную.
Комментариев нет:
Отправить комментарий