nsutextbook (1037554), страница 19
Текст из файла (страница 19)
Различие проявляется на третьем уровне, сортировка выполняетсяв соответствие со строковой последовательностью сортировки.• Появляется модель данных, которую можно представить в виде многомерного кубаданных: название факультета, ФИО декана и телефон деканата располагаются на первомуровне, номер группы и ФИО куратора на втором, а № зачетки и информация о студентена третьем.• Caché предоставляет все инструменты для анализа этой модели данных.Интересный пример прототипа экономической системы торговли текстильными товарами, приведен также в книге «СУБД Caché, объектно-ориентированная разработкаприложений» [2].7.5. Работа с глобаламиРабота с глобалами выполняется в проводнике Caché. Глобальные данные сохраняются в B*-деревьях.
Дерево, которое имеет одинаковое число подуровней в каждом своемподдереве, называется сбалансированным (balanced tree, отсюда и B-дерево). Дерево, укоторого каждый ключ указывает на блок данных, содержащий требуемую запись, называется B*-деревом. Оно делает возможной интеграцию области указателей и области данных.7.6. Функции для работы с многомерными массивами7.6.1.
Функция $Data$Data (коротко - $D) – может работать с глобальной, локальной, скалярной или индексированной переменной. Функция определяет, существует ли заданная в виде аргумента переменная и какая у нее структура данных. Функция может возвращать четыре значения. Синтаксис:$DATA(variable,target)$D(variable,target)Где variable – переменная, target – необязательный, возвращает текущее значение переменной. Если переменная не определена, то остается неизменным. В табл.
15 приведенызначения, возвращаемые функцией $DATA.Таблица 15ЗначениеОписание0Переменная с заданным индексом не существует10 (десять) Переменная указывает на элемент массива, который имеет потомков, носам не имеет значения. Любая прямая ссылка на такую переменную будет вызывать ошибку <UNDEFINED>. Например, если $DATA(y) воз85111(одиннадцать)вращает 10, то set x=y будет вызывать ошибку <UNDEFINED>.Переменная существует и содержит значение, но не имеет потомков.Заметим, что пустая строка «» рассматривается как имеющая значение.Переменная имеет потомков и имеет значение.
Такие переменные можно использовать в выражениях.Замечание. Значение 1 и 11 только указывают на существование значения, но не на еготип.С помощью функции $Data можно с уверенностью сказать существует ли переменная и имеет ли она значение. Например:If $Data(^Univer(“математический”, 104))#10 write “Такая группа есть на факультете”If $Data((^Univer(“математический”, 110))#10=0 write “Такой группы нет”.При делении по модулю 10 оба результата функции $Data сигнализирующие о существовании, а именно 1 или 11, преобразуются в значение 1, интерпретируемое как логическая ИСТИНА.Аналогичного результата достигают путем целочисленного деления на 10, когда хотят установить присутствует ли значение на более высоком уровне. Как 10, так и 11 прицелочисленном делении на 10 дают в результате 1, а 0 и 1 дают в результате 0.Часто вопрос стоит так: хотелось бы знать, имеется ли значение глобала и, если оноимеется, то с этим значением работать дальше.
Пример:If ($Data(^Univer(“математический”, 104))#10{ Set Fio=^Univer(“математический”, 104)write Fio}Такая проверка позволяет избежать ошибки <UNDEFINED>, если переменная отсутствует. Эта часто встречающаяся проверка может быть значительно упрощена с помощьюфункции $Get ( сокращенно $G). Пример:Set Fio=$Get(^Univer(“математический”, 110),””)Если глобал существует, то значением Fio становится результат функции, если нет топустая строка – “ ”.Пример.
В этом примере выбраны некоторые записи массива ^client, это разреженный массив, имеющий три уровня. Первый уровень содержит имя клиента, второй – адресклиента, а третий – тип счета, номер счета, остаток по счету. Каждый клиент может иметьдо четырех разных счетов. Так как ^client это разреженный массив, то могут быть неопределенные элементы на всех трех уровнях. Примеры записей массива приведены ниже:^client(5)John Jones // первый уровень^client(5,1)23 Bay Rd./Boston/MA 02049 // второй уровень^client(5,1,1) Checking/45673/1248.00 // третий^client(5,1,2) Savings/27564/3270.00 // третий^client(5,1,3) Reserve Credit/32456/125.00 // третий^client(5,1,4) Loan/81263/460.00// третийПрограмма для создания такого глобала приведена ниже:Set ^client(5)="John Jones" // первый уровеньSet ^client(5,1)=$ListBuild("23 Bay Rd.","Boston","MA 02049") // второй уровеньSet ^client(5,1,1)=$ListBuild("Checking","45673","1248.00") // третийSet ^client(5,1,2)=$ListBuild("Savings","27564","3270.00") // третийSet ^client(5,1,3)=$ListBuild("Reserve Credit","32456","125.00") // третийSet ^client(5,1,4)=$ListBuild("Loan","81263","460.00")// третий86Нижеследующий код это подпрограмма для проверки данных каждого уровня.
Онаиспользует функцию $DATA для проверки существования текущего элемента. Если$DATA=0 на 1,2, и 3 уровнях, это означает, что текущий элемент не существует. Функция$DATA=10 если на 1 и 2 уровнях есть потомки, но нет данных. Команда WRITE на уровнях 2 и 3 использует функцию $List для извлечения информации о текущем элементе массива.Start Read !,"Введите количество записей: ",nRead !,"Начать с записи номер: ",sFor i=s : 1 : s + n {// первый уровеньIf $Data(^client(i)) {If $Data(^client(i))=10 {Write !," Имя : Данных нет"}Else {Write !," Имя : " ,^client(i)}If $Data(^client(i,1)) {// второй уровеньIf $Data(^client(i,1))=10 {Write !,"Адрес: Нет данных" }Else { // вывод адресаWrite !,"Адрес: ",$List(^client(i,1),1)Write " , ",$List(^client(i,1),2)Write " , ",$List(^client(i,1),3)}}For j=1:1:4 {// третий уровеньIf $Data(^client(i,1,j)) { Write !,"Тип счета: ",$List(^client(i,1,j),1)Write ?30," Номер #: ",$List(^client(i,1,j),2)Write ?50," Остаток: ",$List(^client(i,1,j),3)}}}}Write !,"Конец"Quit7.6.2.
Функция $GetФункция $Get возвращает значение глобала, если он существует и пустую строку,если его значение отсутствует. Синтаксис:$Get(<имя глобала> [,<новое значение глобала>])В форме со вторым аргументом глобалу будет присвоено значение, заданное вторымаргументом.Например:Set Fio=$Get(^Univer(“математический”, 110),””)7.6.3. Функция $OrderФункция – $Order ($O) служит для получения очередного в последовательности сортировки индекса локальной или глобальной индексированной переменной. С помощьюцикла в соответствии с порядком сортировки могут быть получены все существующие87индексы данного уровня.
Рассмотрим простой пример, ориентируясь на одномерную версию глобала ^Univer.^Univer(“математический”) = Волков Ю.Н.| 22-33-45^Univer(“физический”) = Семенов А.К.| 34-32-12^Univer(“исторический”) = Фофанов М.Н.| 45-90-78Команда write $Order(^Univer(“математический”)) выдаст: “физический”. Аргументом функции является конкретный узел глобала ^Univer(“математический”), при этом вкачестве результата возвращается следующий существующий индекс, а именно “физический”. Если поместить его в функцию, то получим следующий индекс в порядке сортировки и т.д.
вплоть до последнего. Если задать и его, получим пустую строку, которуюможно использовать в качестве критерия окончания цикла. Например, следующий циклпозволяет получить список всех факультетов университета:Set x=””For {Set x=$Order(^Univer(x))Quit: x=””Write !,x}Замечания1. Индекс, используемый при обращении к функции, может не существовать, при этом выдается очередной существующий индекс, например:> write $Order(^Univer(“математический”, 004))> 1042.
Часто возникает потребность в получении не всех значений глобала, а в пределах интервала, например, мы хотели бы получить список всех групп на математическом факультете в пределах от 104 до 115.Set x=104For {Set x=$Order(^Univer(“математический”, x))Quit:x=””!(x>115)Write !, x }3. Часто требуется двигаться в обратном порядке последовательности сортировки:Set x=””For {Set x=$Order(^Univer(x), -1)Quit:x=””Write !, x}Получим:физическийматематическийисторический4. Каким образом получают к уже заданному индексу “математический” первый индексна втором уровне? Это делается путем использования пустой строки на втором уровне индексации:> write $Order(^Univer(“математический”, ””))> 104// получаем первый индекс второго уровняТеперь можем получить все индексы второго уровня:Set Fac="математический", x=""For {Set x=$Order(^Univer(Fac,x))88Quit:x=""Write !, x}Задача: выдать список всех студентов математического факультета группы 104.Решение:Set Fac="математический", Gr=104, x=""For {Set x=$Order(^Univer(Fac,Gr,x))Quit:x=""Write "№ зачетки ",x,!Write "ФИО студента :",$List(^Univer(Fac,Gr,x),1) ,!Write "Адрес :",$List(^Univer(Fac,Gr,x),2) ,!Write "Телефон :",$List(^Univer(Fac,Gr,x),3) ,!}7.6.4.
Функция $QueryФункция $Query возвращает имя следующего узла глобала в виде строки символов,позволяет обойти глобал сверху вниз. В отличие от функции $Order получаем полнуюссылку. Например, пусть имеем глобал:^Univer=”N-ский Государственный Университет”^Univer(“математический”) = Волков Ю.Н.| 22-33-45^Univer(“физический”) = Семенов А.К.| 34-32-12^Univer(“исторический”) = Фофанов М.Н.| 45-90-78^Univer(“математический”, 104) = Иванов А.П.^Univer(“математический”, 105) = Розанов С.И.^Univer(“математический”, 106) = Потапова Т.А.^Univer(“математический”, 104, 91232) = Иванов П.И.|Ленина 10,3| 67-56-32^Univer(“математический”, 104, 91233) = Петров И.М.|Мира 45,9| 78-56-34^Univer(“математический”, 104, 91234) = Сидоров В.А.|Русская 10,78| 33-45-67Тогда> write $Query(^Univer(“математический”))выдает ^Univer("математический",104)> write $Query(^Univer("математический",104))выдает ^Univer("математический",104,91232)> write $Query(^Univer("математический",104,91232))выдает $Query(^Univer("математический",104,91233))> write $Query(^Univer("математический",104,91233))выдает $Query(^Univer("математический",104,91234))Таким образом, обходим дерево в глубь, каждый раз получая уровень с большейразмерностью, если таковой существует.