Поля двух таблиц связаны внешним ключом (foreign key), а заполняя базу данных, пользователь заносит в связанные поля одинаковые значения. Таким образом нет нужды указывать эти связи в запросе. Такое удобство открывает возможность построения древовидного запроса вида
Пусть предшествующим звеном дерева является родительская таблица (таблица "a"), а последующим - дочерняя (таблица "b"), ссылающаяся на первичный ключ родительской. Пусть в дочерней таблице существует несколько записей, ссылающихся на одну и ту же родительскую запись - это означает, что следующий уровень дерева содержит несколько элементов. Звено дерева, состоящее из нескольких записей дочерней таблицы, будем называть множеством (set). Для извлечения дерева перечисляем имена таблиц - сначала родительской, затем дочерней.
DDL | TML | вывод из СУБД |
create table a ( id num primary key, data float ); create table b ( id num primary key, ref num references a(id), data float ); create table c ( id num primary key, link num references b(id), data float ); insert into a values (1, 12.3); insert into b values (10, 1, 23.4); insert into b values (20, 1, 34.5); insert into b values (30, 1, 45.6); insert into c values (100,10,56.7); insert into c values (101,10,67.8); insert into c values (200,20,78.9); insert into c values (201,20,89.1); insert into c values (300,30,91.2); |
a.b.c |
<a id=1 data=12.3> <b id=10 data=23.4> <c id=100 data=56.7/> <c id=101 data=67.8/> </b> <b id=20 data=34.5> <c id=200 data=78.9/> <c id=201 data=89.1/> </b> <b id=30 data=45.6> <c id=200 data=91.2/> </b> </a> |
DDL | TML | вывод из СУБД |
create table a ( id num primary key, data float ); create table b ( id num primary key, ref1 num references a(id), ref2 num references a(id), data float ); create table c ( id num primary key, lnk1 num references b(id), lnk2 num references b(id), data float ); insert into a values (1, 12.3); insert into a values (2, 23.4); insert into b values (10, 1, 2, 34.5); insert into b values (20, 1, 2, 45.6); insert into b values (30, 1, 2, 56.7); insert into b values (40, 1, 2, 67.8); insert into c values (100,10,20,78.9); insert into c values (101,10,20,89.1); insert into c values (200,30,40,91.2); insert into c values (201,30,40,88.8); |
a.b/ref1.c/lnk1 |
<a id=1 data=12.3> <b id=10 ref2=2 data=34.5> <c id=100 lnk2=20 data=78.9/> <c id=101 lnk2=20 data=89.1/> </b> <b id=30 ref2=2 data=56.7> <c id=200 lnk2=40 data=91.2/> <c id=201 lnk2=40 data=88.8/> </b> </a> |
Пусть предшествующим звеном дерева является дочерняя таблица (таблица "a"), а последующим - родительская (таблица "b"). Звено дерева, состоящее из записи родительской таблицы, будем называть эстафета (relay-race). Для извлечения дерева перечисляем имена таблиц - сначала дочерней, затем родительской.
DDL | TML | вывод из СУБД |
create table a ( id num primary key, ref num references b(id), data float ); create table b ( id num primary key, link num references c(id), data float ); create table c ( id num primary key, data float ); insert into с values (100, 34.5); insert into b values (10, 100,23.4); insert into a values (1, 10, 12.3); |
a.b.c |
<a id=1 data=12.3> <b id=10 data=23.4> <c id=100 data=34.5/> </b> </a> |
DDL | TML | вывод из СУБД |
create table a ( id num primary key, ref1 num references b(id), ref2 num references b(id), data float ); create table b ( id num primary key, lnk1 num references c(id), lnk2 num references c(id), data float ); create table c ( id num primary key, data float ); insert into с values (201, 78.9); insert into с values (200, 67.8); insert into с values (101, 56.7); insert into с values (100, 45.6); insert into b values (20, 200,201,34.5); insert into b values (10, 100,101,23.4); insert into a values (1, 10, 20, 12.3); |
a/ref1.b/lnk1.c |
<a id=1 data=12.3> <b id=10 data=23.4> <c id=100 data=45.6/> </b> </a> |
Медвежье ухо - это внешний ключ, ссылающийся на первичный ключ этой же самой таблицы. Несколько подряд идущих эстафет, порожденных медвежьим ухом, всегда будем рассматривать как одно звено, и будем называть такое звено списком (list).
По выходным данным (в xml-виде) невозможно определить, было ли звено в базе данных множеством или списком.
Если детерминация не используется, то внешний ключ из нескольких полей не вносит ничего нового. При использовании детерминации все ссылающиеся поля внешнего ключа должны быть перечислены через знак умножения, например как в примере ниже.
Деревянная модель данных (поверх реляционной) будет иметь своим следствием еще и то, что агрегаты у нее тоже будут деревянные: на любом уровне иерархии дерева, в любом количестве мест могут находится временные переменные, в которых будут накапливаться значения агрегата. А значит располагать временные переменные нужно не в агрегате (как в SQL), а в самой модели данных. Такие "временные" поля реально не существуют, и мы будем помечать их как "fictional" (но они доступны для записи, в отличие от полей с пометкой 'secondary'). Таким образом TML незначительно затрагивает DDL.
Как вывод, так и ввод данных наиболее естественен в виде XML-текста, ибо он доступен человеку для непосредственного восприятия и редактирования (в отличие от бинарных форматов). Для целей ввода и вывода будем полагать, что слова "запись" (из СУБД) и "тег" (из XML) являются синонимами, а также что слова "поле" и "атрибут" также являются синонимами. Например, совершенно законны выражения "вложенная запись" и "вложенная таблица".
Номер TCP-порта, на котором сидит СУБД, и вид протокола связи желательно выбирать таким образом, чтобы хотя бы один из возможных клиентов СУБД мог общаться с нею без промежуточного ПО (без middle-ware). Из всех протоколов (http, ftp, smtp, pop3 и т.д.) наиболее употребительным является HTTP как используемый браузером, поэтому именно через него и будет принимать и отправлять xml-данные ТML4. Значением поля может быть картинка, но по TML-запросу как значение поля отправляется не она, а ее URL для отдельного HTTP-запроса браузера.
Пользователь может отправлять в удаленную или локальную базу данных из командной строки ОС (HTTP спросит логин).
|
|
Все, что посылает триггер или таймер, пользователь может послать из коммандной строки программы-терминала: для Oracle это 'SqlPlus.exe', для Postgres это 'PgSql.exe', для InterBase это 'iSql.exe' и т.д. В каждой начавшейся транзакции (после соединения с базой данных или после команд 'commit' или 'rollback') поля 'ran' и 'ral' таблицы 'sys' всегда указывает на местонахождение самой программы-терминала, поэтому команда
DML- и TML-коды и данные могут перемежаться: если выражение начинается
Таким образом отличительными особенностями Tree Manipulation Language являются: