ОПЕРАТОРИ і реляційна модель

Досі всі визначення операторів, що застосовувалися в цій главі, ставилися або до селекторам, або до операторам ТНЕ_, а тепер розглянемо визначення операторів в цілому Як перший приклад нижче показаний визначається користувачем оператор ABS для вбудованого типу RATIONAL

OPERATOR ABS ( Z RATIONAL ) RETURNS RATIONAL RETURN ( CASE

WHEN Z &gt 0 0 THEN +Z WHEN Z &lt 00

THEN -Z END CASE ) END OPERATOR

;

Оператор ABS (скорочення від absolute value – абсолютне значення) визначений у термінах тільки одного параметра, z, що має тип RATIONAL, І повертає результат того ж типу Тому будь-який виклик оператора ABS, наприклад ABS (AMTl + AMT2), є за визначенням виразом типу RATIONAL

Розглянутий в наступному прикладі оператор DIST (скорочення від distance between – відстань між двома точками) приймає два параметра одного і того ж визначається користувачем типу (POINT) І повертає результат іншого типу

(LENGTH)

OPERATOR DIST ( P1 POINT, P2 POINT ) RETURNS LENGTH RETURN { WITH THE_X ( P1 ) AS   X1 ,

THE_X ( P2) AS X2 ,

THE_Y ( P1) AS Y1 ,

THE_Y ( P2) AS Y2 :

LENGTH ( SQRT (( X1 X2 ) ** 2

+ ( Y1 Y2 ) ** 2 ) ) )

;

END OPERATOR

Передбачається, що селектор LENGTH приймає параметр типу RATIONAL Крім того, заслуговує на увагу те, як застосовується конструкція WITH ДЛЯ присвоювання імен результатами деяких подвираженій Ця конструкція буде широко використовуватися в наступних розділах

В якості наступного прикладу розглядається один з обовязкових операторів порівняння, = (Порівняння на равенство7), для типу POINT

7 Наведений тут оператор порівняння на рівність було б точніше назвати оператором порівняння на ідентичність, оскільки вираження vl = v2 приймає істинне значення, якщо і тільки якщо значення vl і v2 по суті є повністю однаковими

OPERATOR EQ ( P1 POINT, P2 POINT   )    RETURNS BOOLEAN RETURN ( THE_X ( P1 ) = THE_X   (    P2 ) AND

THE_Y ( P1 ) = THE_Y {  P2 )

)

END OPERATOR

Слід зазначити, що тут у вираженні, яке входить до складу оператора RETURN, використовується вбудований оператор = для типу RATIONAL З метою спрощення з цього моменту будемо вважати, що в якості оператора перевірки на рівність може використовуватися звичайне інфіксне позначення = (Для всіх типів, тобто не тільки для типу POINT) тут не наведені міркування на тему, що стосується того, як інфіксне позначення можуть бути визначені на практиці, оскільки по суті таке рішення відноситься просто до сфери синтаксису

Нижче наведений оператор > для типу QTY

OPERATOR GT ( Q1 QTY, Q2 QTY ) RETURNS BOOLEAN RETURN ( THE_QTY ( Ql ) &gt THE_QTY ( Q2 )

) END OPERATOR

Тут у виразі у складі оператора RETURN використовується вбудований оператор > для типу INTEGER І в даному випадку мається на увазі, що починаючи з цього моменту в якості даного оператора може використовуватися звичайне інфіксне позначення, причому не тільки для типу QTY, а й для всіх так званих порядкових типів (За визначенням порядковим типом називається тип, до якого застосуємо оператор >. Простим прикладом непорядкового типу є POINT)

Нарешті, нижче наведено приклад визначення оператора поновлення (усі попередні приклади ставилися до типу операторів, призначених тільки для читання, в яких не допускається оновлювати небудь, за винятком, можливо, локальних змінних) 8 Цілком очевидно, що в цьому визначенні замість специфікації RETURNS застосовується специфікація UPDATES оператори оновлення не повертають значення і повинні викликатися за допомогою явно заданих операторів CALL [33]

OPERATOR REFLECT (Р POINT) UPDATES P BEGIN

THE_X ( P ) := THE_X ( P )

THE_Y ( P ) := THE_Y ( P ) RETURN END END OPERATOR

Оператор REFLECT по суті переміщує точку, позначену своїми декартовими координатами (х, у), в протилежну позицію (-х,-у) він виконує цю дію шляхом відповідного оновлення переданих йому фактичних параметрів з координатами точки Зверніть увагу на те, що в цьому прикладі використовуються псевдопеременние ТНЕ_ Псевдопеременная ТНЕ_ являє собою виклик оператора ТНЕ_ в цільової позиції (зокрема, зліва від оператора привласнення) При такому виклику

8 Оператори, призначені тільки для читання, і оператори поновлення часто називають також, відповідно, спостерігачами та модифікаторами, особливо в обєктних системах (див главу 25) Для позначення операторів, призначених тільки для читання, застосовується ще один синонім – функція (і цей термін час від часу використовується у зазначеному значенні й у даній книзі)

фактично позначається заданий компонент (відповідного можливого подання) фактичного параметра (а не просто повертається його значення) Наприклад, у визначенні оператора REFLECT наступний оператор присвоювання

ТН Е _ Х (Р): =

фактично привласнює значення компоненту X (декартового можливого подання) змінної формального параметра, відповідної параметру Р Безумовно, будь формальний параметр, який необхідно оновити за допомогою оператора поновлення (зокрема, шляхом надання значення псевдопеременной ТНЕ_), повинен бути заданий саме як змінна, а не у вигляді деякого більш загального вираження Псевдопеременние можуть бути вкладеними, як показано нижче

VAR LS LINESEG

ТНЕ_Х (THE_BEGIN (LS)): = 65

Але слід зазначити, що в принципі псевдопеременние ТНЕ_ не є строго необхідними Ще раз розглянемо наступний оператор присвоювання

ТНЕ_Х (Р): = ТНЕ_Х (Р)

Цей оператор присвоювання, в якому використовується псевдопеременная, є логічно еквівалентним оператору, наведеному нижче, в якому така не використовується

. Р: = CARTESIAN (ТНЕ_Х (Р), THE_Y (Р)) Аналогічним чином, наступний оператор присвоювання ТНЕ_Х (THE_BEGIN (LS)): = б5

є логічно еквівалентним наведеному нижче

LS := LINESEG ( CARTESIAN ( 65,

THE_Y ( THE_BEGIN ( LS ) )

) , THE_END ( LS ) )

Іншими словами, псевдопеременние як такі не є строго необхідними для підтримки того різновиду поновлення на рівні компонентів, яка розглядається в цьому розділі Але інтуїтивно підхід з використанням псевдопеременних здається більш привабливим, ніж показаний вище альтернативний підхід (до того ж він може розглядатися як більш спрощений варіант цього альтернативного підходу) крім того, він також забезпечує більш високий ступінь несприйнятливості до змін у синтаксисі відповідного селектора (До того ж може виявитися, що його простіше реалізувати найбільш ефективно)

Торкнувшись теми спрощень, слід вказати, що єдиним оператором оновлення, який в принципі необхідний, є оператор присвоювання (: =) всі інші оператори оновлення можуть бути визначені виключно в термінах привласнення (як уже фактично було показано в розділі 3, особливо на прикладі реляційних операторів оновлення) Але потрібна також підтримка для множинної форми присвоювання, яка дозволяє одночасно виконати будь-яку кількість

Глава 5 Типи 181

окремих присвоювань [33] Наприклад, можна замінити два оператора присвоювання у визначенні оператора REFLECT наступним оператором множинного присвоювання

ТНЕ_Х (Р): = ТНЕ_Х (Р)

THE_Y (Р): = THE_Y (Р)

(У цій конструкції заслуговує особливої ​​уваги роздільник у вигляді коми) Цей оператор має наступну семантику: по-перше, обчислюються всі вихідні вирази з правих сторін операторів присвоювання по-друге, після цього всі окремі оператори присвоювання виконуються в тій послідовності, в якій вони запісани9

Примітка Оскільки операція множинного присвоювання розглядається як одна операція, в процесі подібного присвоювання перевірка цілісності не проводиться насправді цей факт є однією з основних причин, по яких ми прагнемо в першу чергу забезпечити підтримку множинного присвоювання Додаткові відомості з цієї теми наведені в розділах 9 і 16

Нарешті, повинна бути передбачена можливість позбутися від деякого оператора, якщо він надалі не буде потрібно, наприклад, як показано нижче

DROP  OPERATOR  REFLECT  

Даний конкретний оператор повинен бути визначеним користувачем, а не вбудо-

енним

Перетворення типів

Ще раз розглянемо таке визначення типу

TYPE S# POSSREP { CHAR }

Тут за умовчанням можливе уявлення має успадковане імя S # і тому таке ж імя має і відповідний оператор-селектор Таким чином, показаний нижче виклик селектора є допустимим

S#    ( S I )

(Цей виклик повертає певний номер постачальника) Тому можна зробити висновок, що даний селектор s # може неформально розглядатися як оператор перетворення типу, який перетворює символьні рядки в номери постачальників Аналогічним чином, селектор Р # може розглядатися як оператор перетворення, який перетворює символьні рядки в номери деталей, а селектор QTY – як оператор перетворення, що перетворює цілі числа в значення кількості, і тд

На підставі таких же міркувань оператори ТНЕ_ можуть розглядатися як оператори, що здійснюють перетворення типу в протилежному напрямку Наприклад, ще раз повернемося до визначення типу WEIGHT, наведеним на початку розділу 54

9 Це визначення потребує деякого уточнення в тому випадку, якщо два або більше окремих операторів присвоювання відносяться до однієї і тієї ж цільової змінної Детальні відомості про таку ситуацію виходять за рамки даної книги досить відзначити, що подібні операції повинні бути ретельно визначені, з тим щоб досягався необхідний результат в тих випадках, коли (як у розглянутій прикладі) фактично різні окремі оператори присвоювання оновлюють окремі частини однієї і тієї ж цільової змінної (цей конкретний випадок є особливо важливим)

TYPE WEIGHT POSSREP { D DECIMAL (5,1)

CONSTRAINT D &gt 00 AND D &lt 50000 }

Якщо w відноситься до типу WEIGHT, то вираз

THE_D    (   W   )

фактично перетворює вага, позначений змінної w, в десяткове число

D E C I M A L ( 5, 1)

Отже, в розділі 52 було зазначено, що джерело і мета в операторі присвоювання повинні ставитися до одного і того ж типу і що до однакового типу повинні ставитися операнди в операції порівняння на рівність Але в деяких системах дотримання цих правил безпосередньо не наказано, тому в таких системах можна, наприклад, сформувати запит на проведення порівняння між номером деталі і символьним рядком (Припустимо, в конструкції WHERE), як показано нижче

… WHERE Р # = Р2

У даному випадку лівий операнд відноситься до типу Р #, а правий – до типу CHAR, тому за вказаними вище міркувань спроба провести таке порівняння має закінчитися невдачею через помилки, повязаної з невідповідністю типів (Фактично помилка, повязана з невідповідністю типів, повинна виявлятися на етапі компіляції) Але концептуально тут відбувається саме те, що система визначає можливість використання оператора перетворення Р # (іншими словами, селектора Р #) для перетворення операнда операції порівняння типу CHAR в тип Р #, і тому фактично перетворює цю операцію порівняння в представлену нижче

… WHERE Р # = Р # (Р2)

Після цього операція порівняння стає допустимою

Неявний виклик оператора перетворення подібним чином називається приведенням типу (Coercion) Але добре відомо, що непродумане використання приведення типу може стати причиною виникнення помилок у програмі З цієї причини ми в

даній книзі дотримуємося консервативної позиції, згідно з якою неявно задані операції приведення типу не допускаються: операнди завжди повинні ставитися до відповідних типів, а не просто бути приводяться до цих типів Безумовно, автор допускає можливість визначення операторів перетворення типу (або операторів CAST, як вони зазвичай називаються) і явного їх виклику у разі

необхідності, наприклад, як показано нижче

CAST_AS_CHAR ( 53 000 )

Як вже було сказано, селектори (щонайменше, ті з них, які приймають тільки один параметр) можуть розглядатися як свого роду оператори явного перетворення

Отже, читач до цього часу цілком міг прийти до висновку, що все сказане тут відноситься до підходу, відомому в колу користувачів мов програмування як сувора типізація Різні автори наводять трохи різні визначення для цього поняття, але в тому вигляді, в якому воно визначене в даній книзі, це поняття означає, крім усього іншого, що кожне значення має тип і при кожній спробі

виконати деяку операцію система перевіряє, чи мають операнди типи, допустимі для використання в даній операції Наприклад, розглянемо такі вирази

WEIGHT + QTY / * Підсумовування ваги деталі з кількістю деталей в постачанні * /

WEIGHT * QTY / * Множення ваги деталі на кількість деталей у постачанні * /

Перше з цих виразів не має сенсу, і система повинна відкинути спробу його виконати З іншого боку, другий вираз цілком обгрунтовано: воно позначає загальну вагу всіх деталей, які входять до дану поставку Тому оператори, які можуть бути визначені для ваг і кількостей, застосовуваних у поєднанні, повинні, по всій видимості, включати *, але не +.

Нижче наведено ще кілька прикладів, в яких цього разу розглядаються операції порівняння

WEIGHT &gt QTY EVEN &gt ODD

(У другому прикладі передбачається, що операнд EVEN відноситься до типу парного цілого числа EVEN_INTEGER, а операнд ODD – до типу непарного цілого числа ODD_INTEGER, причому семантика цих типів є очевидною) Тому і в даному випадку перший вираз не має сенсу, а друга дійсно має сенс Тому оператори, які можуть бути визначені для поєднань ваг і кількостей, мабуть, не повинні включати >, а для парних і непарних цілих чисел застосування оператора > є цілком допустімим10 (Що стосується проблеми визначення того, які оператори є допустимими для тих чи інших типів, слід зазначити, що за традицією в більшій частині літератури по базах даних, включаючи перші

кілька видань цієї книги, розглядалися тільки оператори порівняння та ігнорувалися всі інші оператори, такі як + і *.)

Заключні зауваження

Вивчення питання про повну підтримку операторів, відповідних вимогам, викладеним у цьому розділі, призводить до кількох важливих висновків, які коротко викладені нижче

■ Перший і найбільш важливий висновок полягає в тому, що система повинна мати ін формацію про те, які саме висловлювання є допустимими і яким повинен

бути тип результату для кожного такого допустимого вираження

■ Це також означає, що загальна колекція типів для конкретної бази даних повинна являти собою замкнутий безліч з цього випливає висновок, що тип результату кожного допустимого вираження повинен бути типом, відомим сис темі Зокрема, слід зазначити, що це замкнутий безліч типів повинно

10 На практиці типи EVEN_INTEGER і ODD_INTEGER цілком могли бути визначені як підтипи типу INTEGER, і в цьому випадку оператор >, ймовірно, був би успадкований від цього останнього типу (див главу 20)

також включати логічний тип (Або істиннісне значення), оскільки в іншому випадку жоден оператор порівняння не буде допустимим

■ Зокрема, з того факту, що системі повинен бути відомий тип результату кожного допустимого вираження, слід, що системі має бути відомо, які операції присвоювання і які операції порівняння є допустимими

Завершуємо цей розділ посиланням на викладений нижче матеріал Перед цим уже було зазначено, що поняття, звані за традицією в співтоваристві користувачів реляційних систем доменами, насправді є типами даних, обумовленими системою або користувачем, що мають довільну внутрішню складність, значеннями яких можна оперувати виключно за допомогою операторів, визначених для розглянутого типу (і фізичне уявлення яких з цієї причини має бути приховане від користувача) Отже, якщо ми тепер звернемо нашу увагу на обєктні системи, то виявимо, що найбільш фундаментальна концепція обєкта, клас обєкта, насправді являє собою тип даних, який визначається системою або користувачем, що має довільну внутрішню складність, значеннями якого можна оперувати виключно за допомогою операторів, визначених для розглянутого типу (і фізичне уявлення яких з цієї причини має бути приховане від користувача) .. Іншими словами, домени і класи обєктів являють собою одне і те ж І тому нам залишається тільки зєднати ці дві технології (відносини і обєкти) Це важливе питання досліджується в главі 26

Джерело: Дейт К Дж, Введення в системи баз даних, 8-е видання: Пер з англ – М: Видавничий дім «Вільямс», 2005 – 1328 с: Ил – Парал тит англ

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*