Вложенные таблицы Oracle. Oracle предоставляет возможность создавать отношение, атрибут которого является не просто объектом, а множеством объектов или, другими словами, отношением (таблицей). Ключевое слово THE позволяет рассматривать вложенное отношение как обычное. Ключевое слово CAST(MULTISET(...)) позволяет преобразовать результат запроса во вложенную таблицу. Определение табличного типа. Если у нас есть тип объекта, мы можем создать новый тип, являющийся набором объектов при помощи AS TABLE OF. Пример. Предположим, у нас есть более сложный тип сорта пива. CREATE TYPE BeerType AS OBJECT ( name CHAR(20), kind CHAR(10), color CHAR(10) ); / Мы можем создать тип, являющийся вложенной таблицей для этого типа с помощью: CREATE TYPE BeerTableType AS TABLE OF BeerType; / Теперь мы можем определить отношение производителей с вложенной таблицей сортов пива внутри В определенном смысле мы нормализуем ненормализованное отношение, поскольку данные о производителе появляются только один раз в независимости от количества сортов пива, которые он производит. CREATE TABLE Manfs ( name CHAR(30), addr CHAR(50), beers BeerTableType ) Однако, для того, чтобы указать системе, как хранить вложенные таблицы сортов пива, мы должны после оператора определения этого отношения, но до точки с запятой дополнительно указать: NESTED TABLE beers STORE AS BeerTable; Имя таблицы для хранения вложенных таблиц является произвольным, здесь мы использовали BeerTable. Запросы к вложенным таблицам. Атрибут, являющийся вложенной таблицей, может быть выведен так же, как любой другой атрибут. Значение имеет два типа конструкторов, один - для таблицы, другой - для ее кортежей. Пример. Выдать список сортов пива, производимых Anheuser-Busch. SELECT beers FROM Manfs WHERE name = 'Anheuser-Busch'; Единственное значение будет выведено следующим образом: BeerTableType( BeerType('Bud', 'lager', 'yellow'), BeerType('Lite', 'malt', 'pale'), ... ) Операции над вложенными таблицами. Используется THE для обращение к самой вложенной таблице, которая затем используется как обычно. Пример. Найти эли, производимые Anheuser-Busch. SELECT bb.name FROM THE( SELECT beers FROM Manfs WHERE name = 'Anheuser-Busch' ) bb WHERE bb.kind = 'ale'; Преобразование типа для создания вложенных таблиц. Сначала создается значение для вложенной таблицы, используя запрос "SELECT-FROM-WHERE", результат преобразуется к типу вложенной таблицы. Пример. Предположим, у нас есть отношение Beers(beer,manf), где beer является объектом типа BeerType и manf - его производитель. Мы хотим вставить в отношение Manfs кортеж для Pete's Brewing Co., со всеми сортами пива как одной вложенной таблицей. INSERT INTO Manfs VALUES( 'Pete''s', 'Palo Alto', CAST( MULTISET( SELECT bb.beer FROM Beers bb WHERE bb.manf = 'Pete''s' ) AS BeerType ) ); Транзакции. Транзакция = фрагмент(логическая единица) работы, который должен обладать следующими свойствами (ACID): 1. Атомарность(atomicity) = либо выполнена вся работа(весь фрагмент), либо ничего. 2. Согласованность(consistency) = транзакция переводит БД из одного согласованного состояния в другое (не нарушает ограничений целостности). 3. Изолированность (isolation) = выполнение должно выглядеть так, как будто нет никаких других операций(транзакций) над базой данных. Часто называют упорядоченным (serializable) поведением. В современных СУБД упорядоченность часто является одной из возможных альтернатив того, каким образом ограничено поведение транзакций. 4. Долговечность(durability) = если транзакция зафиксирована (завершена), то произведенные ею изменения сохраняются в БД постоянно, даже если в следующий момент произойдет сбой системы. Решение о завершении/откате транзакции. Каждая транзакция завершается указанием либо: 1. Завершить(зафиксировать)(COMMIT) = результат транзакции фиксируется в базе данных, до этого изменения БД в результате работы транзакции могут быть не видны другим транзакциям. 2. Прервать = никакие изменения, являющиеся следствием работы незавершенной транзакции в базу не записываются, как будто этой транзакции никогда не было. Откат(ROLLBACK) - термин, используемый в SQL и Oracle. В запросах интерфейса (Oracle SQLplus) транзакциями могут быть являются отдельные запросы или операторы модификации базы. Oracle имеет режим SET TRANSACTION READ ONLY для того чтобы начать транзакцию, состоящую из нескольких операторов, не изменяющих данные, но требующих целостных данных. В программном интерфейсе (Pro*C или PL/SQL) транзакция начинается как только происходит доступ к данным, либо при выполнении операторов COMMIT или ROLLBACK. Пример 1. Sells(bar, beer, price) . Joe's Bar продает Bud по цене $2.50, а Miller - по цене $3.00. Sally обращается к базе с запросом о максимальной и минимальной цене, по которой Joe продает пиво: (1) (2) SELECT MAX(price) FROM Sells WHERE bar = 'Joe''s Bar'; SELECT MIN(price) FROM Sells WHERE bar = 'Joe''s Bar'; В это же время Joe заменяет Miller и Bud на Heineken по цене $3.50: (3) (4) DELETE FROM Sells WHERE bar = 'Joe''s Bar' AND (beer = 'Miller' OR beer = 'Bud'); INSERT INTO Sells VALUES('Joe''s bar', 'Heineken', 3.50); Если порядок операторов 1, 3, 4, 2, то для Sally результатом будет, что минимальная цена Joe's больше его максимальной цены. Проблема решается помещением обоих запросов Sally в одну транзакцию, т.е. в один PL/SQL оператор. Пример 2: Проблема, возникающая при откате. Предположим, Joe выполняет оператор 4 (вставка Heineken), но затем, после размышления решает откатить транзакцию назад с помощью оператора ROLLBACK. Если Sally разрешено выполнить ее оператор 1 (найти max) непосредственно перед откатом, она получит $3.50, даже при случае, что Joe не продает никакое пиво за $3.50. Проблема решается путем объявления оператора 4 отдельной транзакцией, либо частью транзакции, таким образом его эффект не может быть виден Sally до тех пор пока транзакция не завершена при помощи оператора COMMIT. Уровни изоляции SQL. Уровни изоляции определяют, что может видеть транзакция. Объявление уровня изоляции имеет вид: SET TRANSACTION ISOLATION LEVEL X ; где: X = SERIALIZABLE: эта транзакция выполняется как будто в предположении, что все другие транзакции выполняются полностью либо до, либо после этой транзакции. Пример. Предположим, операторы Sally 1 и 2 являются одной транзакцией, а операторы Joe 3 и 4 - другой. Если транзакция Sally выполняется с уровнем изоляции SERIALIZABLE, она могла бы видеть отношение Sells либо до операторов 3 и 4, либо после, но никак не в середине. X = READ COMMITTED: эта транзакция может видеть только данные, полученные после полного завершения (committed) других транзакций. Пример. Если транзакции определены, как упомянуто выше, Sally может видеть оригинальное отношение Sells для оператора 1 и полностью измененное отношение для оператора 2. X = REPEATABLE READ: если транзакция читает данные дважды, то все что она видит первый раз должно быть видно второй раз (хотя во второй раз может быть видно больше, чем в первый) Пример. Если 1 выполняется перед 3, то 2 должен видеть Bud и Miller кортежи при вычислении min, даже если 2 выполняется после 3, 2 после 4 может видеть Heineken 4. Но если 1 выполняется между 3 и 4, то 2 после 4 может видеть один кортеж Heineken. X = READ UNCOMMITTED: нет ограничений, даже на чтение данных записанных, но затем удаленных из-за отката. Пример. 1 и 2 могли бы видеть Heineken, даже если Joe позже "откатил"(rolled back) свою транзакцию. Независимость уровней изоляции. Уровни изоляции для транзакции определяют, что может видеть данная транзакция. Они не ограничивают, что другие транзакции, возможно, с отличным уровнем изоляции, могут видеть в качестве результатов данной транзакции. Пример. Если транзакция 3-4 (Joe) имеет уровень serializable, а транзакция 1-2 (Sally) не имеет его, то Sally может видеть NULL в качестве значения для min и max, поскольку может случиться, что ее транзакция выполняется между 3 и 4. Авторизация в SQL. Файловые системы задают некоторые привилегии для работы с файлами: r, w, x. При частичной аналогии SQL определяет 9 привилегий доступа для отношений, из которых наиболее важными являются: 1. SELECT = право на выполнение запроса для отношения. 2. INSERT = право вставлять кортежи в отношение - может относиться к отдельному атрибуту, в этом случае привилегия задает только одного столбца вставляемого кортежа 3. DELETE = право удалять кортежи из отношения 4. UPDATE = право обновлять кортежи отношения - может относиться к отдельному атрибуту. Выдача(делегирование) привилегий. Вы имеете все возможные привилегии для отношений, которые вы сами создаете. Вы можете делегировать привилегии любому другому пользователю, если вы имеете саму привилегию и право ее делегирования (привилегию с режимом grant). Вы имеете этот режим для ваших собственных отношений. Пример. 1. Sally может выполнять запросы для Sells и может изменять цены, но не может передать эту привилегию. GRANT SELECT ON Sells, UPDATE(price) ON Sells TO sally; 2. Sally может выборочно делегировать эти привилегии другому: GRANT SELECT ON Sells, UPDATE(price) ON Sells TO sally WITH GRANT OPTION; Лишение привилегий. Привилегия, делегированная вам кем-то другим, может быть отобрана. Синтаксис похож на оператор делегирования, но использует REVOKE ... FROM вместо GRANT ... TO. Определение, имеете ли вы конкретную привилегию, может быть нетривиальной задачей, использующей граф делегирования (подробнее см. книгу). Основными принципами здесь являются: a) если привилегия была делегирована вам несколькими пользователями, то для лишения этой привилегии все эти пользователи должны ее отобрать. b) Отбор привилегии является транзитивным. Если A делегировал P to B , который делегирована P to C , затем А отбирает P у B , то автоматически P будет отобрана у C .