В некоторых случаях при использовании хранимых процедур ну очень хочется иметь механизм получения нескольких строк в 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 я пока не могу дать гарантированного решения с несколькими такими таблицами в одном запросе, поскольку пока они используют одну и ту же локальную переменную.
Комментариев нет:
Отправить комментарий