Рубрика: SQL

  • Знакомство с командой SELECT

    Знание как получить данные используя язык запросов – это первый шаг к пониманию возможностей команды SELECT. Описание используемых взаимоотношений данных предоставляет ощутимую связь между теорией о том как данные хранятся в таблицах и практической визуализацией этих данных. Эти темы очень важны для обсуждения возможностей команды SELECT. Мы рассмотрим темы в следующем порядке

    • Знакомство с командой SELECT
    • Команда DESCRIBE
    • Возможности команды SELECT

    Команда SELECT языка SQL  — это гибкий, понятный и расширяемый механизм созданный для получения информации из базы данных. БД были бы гораздо менее ценными если бы мы не могли писать запросы для получения ответов на наши вопросы. Например у вас может быть база данных в которой хранится ваша финансовая информация: платажи в банке, счета и зарплата. Вы можете легко спросить базу данных, чтобы она предоставила список упорядоченный по дате о счетах за электричество за последние пол года или ваши платежи с определённого счёта за тот же срок. Красота SQL команды спрятана в её простоте, формате похожем на обычный язык, с помощью которого можно задавать вопросы базе данных в формате диалога.

     

    Команда DESCRIBE

     

    Чтобы получить ответ на вопрос, надо задавать правильный вопрос. Понимание предмета обсуждения, в нашем случае реляционных таблиц, это эссенция для формулировки правильных вопросов. Описание структуры таблицы полезно для понимания какие вопросы можно задать таблице. Oracle хранит информацию о всет таблицах в специальном наборе таблиц, называемых словарём данных, для управления ими. Словарь данных это почти тоже самое что обычный словарь. В нём хранятся определения объектов базы данных в централизованном, упорядоченном и отсортированном формате.

    Мы должны чётко разделять определение таблицы и её содержимое. Определение таблицы включает в себя такую информацию как имя, владелец, сведения о столбцах, физическом расположении на диске и т.п. Эта информация является метаданными. Содержимое таблиц хранится в виде строк и называется непосредственно данными.

    Метаданные структуры таблицы можно узнать запросив список столбцов этой таблицы. Для этого можно использовать команду DESCRIBE. Синтаксис команды

     

    DESCRIBE <schema>.tablename

     

    Эта команду можно сократить до DESC. Все таблицы принадлежат владельцу – схеме. Если вы хотите узнать описание таблицы из схемы текущего аккаунта, то можно не указывать явно имя схемы. На рисунке 9-1 отображено выполнение команд DESCRIBE из SQL *Plus подключенного как пользователь HR.

    1

     

    В первой команде запрашивается описание таблицы EMPLOYEES. Во втором запросе используется сокращённый псевдоним команды и явно указывается схема, хотя можно было не указывать имя схемы явно, так как таблица DEPARTMENTS принадлежит схеме HR. Также пользователь HR (и все другие пользователи) имеет доступ к специальной таблице с именем DUAL, которая принадлежит схеме SYS. Описание этой таблицы можно получить выполнив третий запрос.

    Описание таблицы даёт интерестный и полезный результат. Вы узнаете какие столбцы таблицы можно выбрать, так как видите их имена. Вы также понимаете природу данных в столбцах, так как отображаются типы данных.

    Обязательные столбцы, которые обязаны хранить данные для каждой строки, можно узнать взглянув на столбец Null? в результате команды DESCRIBE. Т.е. вам гарантируется что для каждой строки в этом столбце будет какое-либо значение. Важно отметить что у Oracle значение NULL – это особое значение, которое указывает на отсутствие данных. Пробелы это не NULL, так как значение пробела присутствует в строке и может иметь некоторую длину, несмотря на то что эти данные не видимы. Пустой строке нет в Oracle.

     

    Возможности команды SELECT

     

    Таблицы реляционных баз данных построены на разделе математики известной как реляционная теория (relational theory). В этом разделе, отношения или таблицы обрабатываются специальным формальным языком называемым реляционная алгебра. В реляционной алгебре используются специальные термины, например: отношения содержат кортежи, у которых есть аттрибуты. А на языке Oracle это звучит как строки состоящие из столбцов хранятся в таблицах. SQL это коммерческая реализация принципов реляционной аглебры. Три концепции из реляционной теории заключают в себе возможности команды SELECT: проекция (projection), выборка (selection) и объединение (joining).

    Проекция отображена в возможности ограничения выбираемых столбцов из таблицы. Когда запрашивается информация из таблицы, вы можете выбрать для просмотра все столбцы. Вы можете выбрать все данные из таблицы HR.DEPARTMENTS с помощью простой команды SELECT – SELECT * FROM HR.DERAPTMENTS. Эта команда вернёт вам DEPARTMENT_ID, DEPARTMENT_NAME, MANAGER_ID и LOCATION_ID для всех записей хранящихся в таблице. Но что если вы хотите список только из имени департамента и менеджера? Тогда вам нужно запросить только эти два столбца из таблицы. Ограничение столбцов и есть проекция.

    Выборка связана с ограничением строк получаемых из таблицы. Обычно не требуется получить все строки из таблицы. В таблицах может храниться много строк и вместо запроса на все строки, выборка позволяет ограничить возвращаемые строки. Например вам нужно найти всех сотрудников которые работают в департаменте с номером 30. С помощью операции выборки вы можете ограничить результат только теми строками где значение DEPARTAMENT_ID равно 30.

    Объединение, это концпеция, связанная с взаимодействием таблиц друг с другом в запросе. Третья нормальная форма представляет собой идею об разделении разных данных в отдельные таблицы для избегания дублирования информации и аномалий при управлении, а также для связывания данных с помощью первичных и внешних ключей (отношения один-к-). Эти отношенияпредоставляют механимз для объединения таблиц между собой. Предположим что нам нужно получить адреса почты для сотрудников кто работает в департаменте продаж. Столбец EMAIL хранится в таблице EMPLOYEES, а DEPARTAMENT_NAME в таблице DEPARTAMENTS. Проекция и выборка используются для получения значение DEPARTAMENT_ID соответствующего значению Sales в названии. Соответсвующие строки из таблицы EMPLOYEE можно присоединить к таблице DEPARTAMENTS основываясь на этом общем значении столбца DEPARTMENT_ID. Столбец EMAIL может быть спроецирован из результата объединения. Команда SELECT математически управляется этими тремя догмами. Неограниченное комбинирование проекций, выборки и присоединения предоставляют возможность выбрать именно требуемые данные из реляционной модели.

     

    Нормализация данных

     

    Процесс моделирования данных в реляционные таблицы называется нормализацией. Обычно рассматриваются три уровня нормализации: первая, вторая и третья нормальные формы. Существуют также более высокие уровни нормализации: четвертая и пятая нормальные формы, но они не используются часто. Возможно использоваться SQL для выборки данных из ненормализованных данных, но обычно это неэффективно и это не то зачем разрабатывался язык SQL. В большинстве случаев, данные хранящиеся в базе данных и используемые с помощью языка SQL должны быть нормализованы к третье нормальной форме.

     

    Tip

    Всегда существует несколько нормализованных моделей для системы. Очень важно использовать наиболее подходящую – если системный анализ будет некорректным, то возможными последствиями будут проблемы с производительностью и хранением данных, а также потребуются гораздо большие усилия для разработки.

     

    Как пример нормализации рассмотрим де-нормализованную таблицу с названием BOOKS, где хранятся данные о книгах, авторах и издательствах, использующую ISBN как первичный ключ. Первичный ключ это аттрибут (или аттрибуты) которые уникально определяют кортеж. В таблице две записи

    2

    Хранение данных в такой таблице может привести к нескольким проблемам. Во-первых,тут существует аномалия вставки: невозможно ввести данных об авторе который ещё не публиковался, потому что нет ISBN для идентификации этой информации. Во-вторых, книга не может быть удалена без потери информации об издательстве: аномалия удаления. В-третьих, если адрес издательства изменяется, необходимо обновить все строки для всех книг этого издательства: аномалия обновления. Тот факт что у книги может быть несколько адресов значит что поле «Author” должно иметь возможность хранить несколько значения, и для поиска конкретного автора необходимо будет просматривать все значения. Также с этой проблемой связана проблема потенциальной необходимости изменять структуру если у книги будет больше авторов чем может поместиться в значении атрибута. И использования места очень неэффективно так как адрес издательства дублируется для строк и вероятность ошибки в заполнении этого поля (так как значение необходимо всегда вводить) высока. Нормализация должна решить все эти проблемы.

    Первая нормальная форма требует удаления повторяющихся групп, в данном примере, наличие нескольких авторов: поместим их в отдельную таблицу с именем AUTHORS. После этого изменения структура данных будет выглядеть так

    Две строки в таблице BOOKS

    3

    И три строки в таблице AUTHORS

    4

    Одна строка в таблице BOOKS теперь связана с двумя строками в таблице AUTHORS. Такое изменение решает аномалию вставки (теперь можно добавлять авторов у которых нет публикаций), проблему поиска книг автора (возможен поиск по одному значению поля NAME в таблице) и проблему максимально возможного количества авторов для одной книги (добавляйте сколько угодно авторов). Это первая нормальная форма – нет повторяющихся групп.

    Вторая нормальная форма требует убрать столбцы из таблицы которые не зависят от первичного ключа. В нашем примере это адрес издательства: адрес зависит от издателя, а не от ISBN книги. Таблица BOOKS и новая таблица PUBLISHERS после этого изменения будут выглядеть так

    5

    6

    Все книги изданные одним издательством будут указывать на одну запись в таблице PUBLISHERS. Это решает проблему хранения адреса несколько раз, и так же аномалию обновления и потенциальные ошибки при повторном вводе значения.

    Третья нормальная форма требует убрать все столбцы которые взаимозависимы. В таблице PUBLISHERS таким аттрибутом будет адрес: улица должна быть в конкретном городе,а город существует в определённом районе. Т.е. адресс должен определяться одним столбцом, а не тремя. Можно заменить три поля одним – кодом адреса, указывающим на отдельную таблицу адресов

    7

    Одним из свойств нормализованных данных которые можно выделить является использование первичных и внешних ключей. Первичный ключ это уникальный идентификатор строки в таблице, им может быть как столбец так и несколько столбцов (составной ключ/composite key). У каждой таблицы должен быть определён первичный ключ. Это требование реляционной парадигмы. Oracle расширяет стандарт: возможно определить таблицу без первичного ключа – хотя это обычно плохая идея и некоторые другие РСУБД не позволяют это сделать.

    Внешний ключ это столбец (или набор столбцов) которые можно использовать для идентификации связанной записи из другой таблицы. Внешний ключ должен совпадать с первичным ключом другой таблицы. Это основа для отношения один-ко-многим. Отношение один-ко-многим это сзять между таблицами, кога много строк из одной таблицы ссылаются на одну строку в другой таблице. Иногда это называется parent-child отношения: один родитель может иметь много наследников. В нашем примере ключами будут

    8

    Эти ключи определяют модель таким образом что у одной книги может быть несколько авторов.

    Доступны разные стандарты для документирования нормализованных стуратур данных, разработанные разными компаниями как формальные методы. В общем, это неважно какой метод кто использует до тех пор пока все кто работает с документацией понимает её. Часть документации всегда включает список аттрибутов составляющих каждую сущность (столбцы таблиц) и диаграмму сущность-связь представляющую собой графическое отображение связей внешних ключей с первичными. Широко используется следующий стандарт

    • Первичный ключ отображается как #
    • Вторичный ключ отображается как \
    • Обязательный столбец обозначается *
    • Необязательный столбец обозначается как o

    Вторая необходимая часть документации модели это диаграмма сущность-связь. Она отображает соединения между таблицами графически.  Для это диаграммы также доступны разные стандарты: на рисунке 9-2 отображена диаграмма сущность-связь используя очень простую нотацию ограниченную отображением отношений один-ко-многим (гусиные лапки) чтобы подчеркнуть какая часть отношений может содержать много значений связанных с одним значением из другого отношения. На рисунке видно что книга может иметь несколько авторов, один издатель может издавать много книг. Диаграмма также указывает что и автом и издатель могут иметь только один адрес. Более сложные нотации могут использоваться для отображение обязательна ли связь или нет, информация которая дублирует информацию из списка столбцов.

    Это очень простой пример нормализации и реально модель не до конца нормализована. Если один автор напишет несколько книг, тогда у нас необходимо будет хранить несколько значений ISBN в таблице авторов. Это будет повторяющаяся группа, которую необходимо вынести в отдельную сущность, чтобы не нарушать первую нормальную форму. При нормализации модели необходимо убедиться что рассмотрены все возможные варианты событий. В реальной системе может быть сотник столбцов и десятки внешних ключей. Построение диграммы сущность-связь для системы с сотнями или тысячами отношений достаточно сложная задача.

    9

     

  • DML и согласованность — Итоги

    DML команды

    • INSERT добавляет строки в таблицу
    • UPDATE изменяет значения в существующих строках
    • DELETE удаляет строки
    • MERGE может комбинировать функционал команд INSERT, UPDATE и DELETE
    • Несмотря на то, что команда TRUNCATE это не DML команда, она удаляет все строки в таблице
    • Команда INSERT может добавлять строки в несколько таблиц
    • Подзапросы могут быть использованы для выбора строк которые необходимо добавить, изменить или удалить
    • Изменения сделанные командами INSERT, UPDATE и DELETE видны только после подтверждения транзакции
    • TRUNCATE удаляет все строки из таблицы
    • Команда TRUNCATE подтверждается сразу после выполнения автоматически: её нельзя отменить

     

    Управление транзакциями

    • Транзакция это логическая единица работы, возможно состоящая из нескольких команд DML
    • Транзакции не видны другим сессиям пока не подтверждены
    • Пока транзакция не подтверждена она может быть отменена
    • Точка сохранения позволяет сессии отменить часть транзакции

     

    Управление данными с помощью команд DML

    • Все команды DML создают данные повтора изменений (redo) и отката (undo)
    • Redo данные хранят все изменения сегментов – как сегментов данных, так и сегментов undo
    • Серверные процессы читают из файлов данных (используя буфер кэш); DBWn записывает данные в файлы данных

     

     

    Объекты PL/SQL

    • Анонимные PL/SQL объекты хранятся на стороне клиента; хранимые объекты хранятся в словаре данных
    • Процедуры и функции могут объединятьяс в пакеты; триггеры не могут входить в пакеты
    • PL/SQL код может выполнять SQL код

     

    Мониторинг и разрешение конфликтов блокировок

    • Уровень блокировки по умолчанию – строка
    • Блокировки необходимы для DML команд и доступны для команды SELECT
    • DML команды требуют исключительную блокировку строк и общую блокировку объектов используемых в команде
    • DDL команды требуют исключительную блокировку объекта
    • Deadlock – и разрешаются автоматически

     

    Undo

    • Все DML команды создают данные undo
    • Данные undo используются для отменты транзакции и изоляции, а также для согласованности чтения и flashback запросов
    • Автоматическое управление undo используя сегменты undo является значением по умолчанию начиная с версии 11g

     

    Транзакции и undo

    • Данные undo всегд хранятся пока транзакция не завершена командой COMMIT или ROLLBACK. Это активные данные undo
    • Данные undo сохраняются после того как они стали неактивными для согласованности чтения долгих запросов; это неустаревшие данные undo
    • Устаревшие данные не нужны для согласованности чтения и могут быть перезаписаны в любое время когда нужно место в сегменте undo

     

    Управление undo

    • Экземпляр использует сегменты undo в одном явно указанном табличном пространтсве undo
    • Другие табличные пространтсва undo могут существовать, но только одно может быть активным
    • Табличное пространтсво undo должно быть достаточно большим чтобы вмещать данные при максимальной нагрузке в течении времени выполнения самого долгого запроса
    • Файлы данных в табличном пространстве undo такие же как и файлы данных обычного табличного пространства
  • Управление Undo

    Управление Undo

     

    Главным достоинством сегментов undo является то что они управляются автоматически, но вы должны установить ограничения в границах которых Oracle будет осуществлять управление. После того как вы рассмотрели объем данных и активность вашей БД вам нужно установить некоторые параметры и определить размеры табличных пространтсв undo.

     

    Ошибки связанные с undo

     

    Принципы очень просты: во первых, всегда должно быть достаточно места для undo чтобы все транзакции могли работать и, во вторых, всегда должно быть достаточно данных undo чтобы запросы выполнились успешно. Первый принцип требует чтобы табличное пространство undo было достаточно большим чтобы накапливать undo данные для худшего сценария. Должно быть выделено достаточно места для хранения данных во время пиковой нагрузки. Обратите внимание что это не значит в момент максимального количества конкурирующих транзакций; во время обычной работы у вас может быть много транзакций, но суммарное количество данных undo которые они сгенерируют будет гораздо меньше чем сгенерирует одна долгая транзакция запускаемая в конце месяца. Второй принцип требует наличие в табличном пространстве места для хранения неустаревших данных которые могут требоваться для согласованности чтения.

    Если транзакции недостаточно места, последний запрос выполнится с ошибкой ORA-30036 “unable to extend segment in undo tablespace”. Запрос будет отменён, но все остальные запросы внутри транзакции останутся выполненными и неподтверждёнными. Алгоритм которы выделяет место для undo сегментов внутри табличного пространтсва undo вызовет такую ошибку только если табличное пространтсво полностью состоит из активных данных.

     

    Exam tip

    Если DML запрос выполняется с ошибкой выделения места, он будет отменен. Остальные запросы транзакции которые уже выполнены успешно остаются без изменений и неподтверждены.

     

    Если запрос обнаруживает что блок данных нужный для запроса был изменен после начала выполнения запроса, серверный процесс возьмёт «старые» данные из сегмента undo. Если в undo сегменте этот блок был переписан, запрос вернёт ошибку ORA-1555 ”snapshot too old”.

    Если табличное пространство undo недостаточно велико – у Oracle есть выбор: позволить транзакции переписать неустаревшие данные и позволить запросу SELECT не выполнится успешно, или позволить запросу SELECT выполнится успешно, а транзакции вернуть ошибку. По умолчанию транзакции имеют больший приоритет: Oracle перезапишет неустаревшие undo.

     

    Параметры для управления undo и гарантия удержания данных (retention guarantee)

     

    Доступно три параметра для управления undo: UNDO_MANAGEMENT, UNDO_TABLESPACE и UNDO_RETENTION.

    У параметра UNDO_MANAGEMENT значения по умолчанию AUTO начиная с версии 11g. Возможно установить это значение в MANUAL, и это приведёт к тому что Oracle не будет использовать сегменты undo. Это позволено для обратной совместимости, и если вы решите использовать это, вам придётся тратить много времени на управление и тюнинг сегментов rollback. Лучше не делайте это. Oracle настоятельно рекомендует использовать значение AUTO и разрешить использование сгементов undo. Этот параметр статический, т.е. если вы измените значение вам нужно перезапустить экземпляр БД. Остальные параметры динамический – их можно изменять во время работы экземпляра.

    Если вы используете UNDO_MANAGEMENT=AUTO то вы должны указать UNDO_TABLESPACE. Этот параметр указывает активное табличное пространство, которое должно было быть создано как UNDO TABLESPACE.  Все сегменты undo будут создаваться и переводиться в режим online автоматически.

    И наконец параметр UNDO_RETENTION, который устанавливается в секундах, не обязательный к выполнению. Этот параметр указывает как долго хранить неактивные undo данные перед тем как обозначить их как устаревшие. Если например самый долгий запрос выполняется тридцать минут, вы можете установить этот параметр в 1800. Oracle постарается хранить все undo данные как минимум 30 минут, и ваш запрос должен всегда выполниться успешно, а не вернуть ошибку ORA-1555. Если вы не установили этот параметр, или установили значение 0, Oracle всё равно будет хранить undo данные так долго, как только возможно. Алгоритм который определяет какие данные устарели всегда будет переписывать самые старые данные; таким образом UNDO_RETENTION всегда имеет максимально допустимое значение от размера табличного пространства.

    Можно настроить параметр UNDO_RETENTION как обязательный, и undo данные всегда будут храниться столько сколько указано. По умолчанию Oracle выставляет приоритет для транзакций, а не запросов. Если размера не хватает на хранение старых данных для запросов или записи новых для транзакций, Oracle отдаст предпочтение транзакции и перезапишет неактивное undo чтобы транзакция работала без ошибки ORA-30036. Другими словами сохранение undo это лишь необязательная задача которую Oracle пытается по возможности выполнять. Однако иногда бывает ситуация когда успешное выполнение запроса важнее чем транзакции. Например запрос на закрытие месяца, когда нужно выполнить долгий запрос, а транзакции могут подождать пару часов, пока отчёт выполняется. Или если вам нужны flashback запросы, которые работают с undo данными.

    Гарантированное удержание данных (guaranteed undo retention), что означает что данные никогда не будут переписаны пока не пройдёт время указанное в UNDO_RETENTION, включается для табличного пространства. Это свойство можно указать во время создания табличного пространтсва или изменить позже. Когда вы активируете табличное пространтсво для которого указано retention guarantee, все запросы будут выполнены успешно если они выполняются быстрее чем значение UNDO_RETENTION; вы никогда не больше не встретите ошибку “snapshot too old”. Обратной стороной медали будет то что транзакции могут не выполниться из-за нехватки места.

    Если параметр UNDO_RETENTION был установлен и файлы данных табличного пространтсва undo используют режим autoextend, то Oracle автоматически будет увеличивать размер файлов данных для хранения undo данных минимум время указанное в UNDO_RETENTION. Таким образом комбинирование autoextending файлов данных и гарантированного хранения undo данных позволяет выполнять успешно и транзакции и запросы – конечно если у вас достаточно дискового пространтсва. Если у вас недостаточно места – попытка увеличить размер файла будет неуспешной.

    У БД может быть одно табличное пространство используемое в обычной работе, где retention guarantee не настроек, и второе для долгих запросов где хранение данных гарантированно.

     

    Оценка размера и мониторинг табличного пространтсва undo

     

    Табличное пространтсво должно быть достаточно большим чтобы хранить undo данные параллельных транзакций в пиковый момент нагрузки, плюс достаточно неустаревших данных для успешного выполнения самого долгого запроса. Также вам возможно придётся добавить места для flashback запросов. Алгоритм прост: расчитать скорость генерации undo при максимальной нагрузке и умножить на длительность самого долгого запроса.

    Представление V$UNDOSTAT расскажет вам то что вам надо знать. Так же доступен помошник в Database Control, который покажет информацию в максимально понятной форме.

    На рисунке 8-8 показан экран управления undo в Database Control. Из домашней страницы перейдите на вкладку Server и затем перейдите по ссылке Automatic Undo Management в разделе Database Configuration.

    2

    На рисунке примера мы видим что табличное пространтсво называется UNDO1 и размер 100 Мб. Хранение undo не гарантировано но файлы данных табличного пространство авторасширяемы. Если вы выбрали авто-расширение для файлов, это гарантирует вам что ваши транзакции всегда выполнятся (пока у вас есть место), но Oracle не будет увеличивать их размер для выполнения UNDO_RETENTION; запрос может вернуть ошибку “snapshot too old”. Как-бы то ни-было, вы не должны рассчитывать на auto-extend; ваше табличное пространство должно быть настроено что быть достаточно большим. Кнопка Change tablespace вызовет команду ALTER SYSTEM для изменения активного табличного пространтсва.

    Дополнительная информация на вкладке System Activity, показанная на рисунке 8-9, рассказывает вам что пиковая геренация undo всегд 1664Кб в минуту, и самый долгий запрос был 25 минут. Отсюда следует что минимальный размер табличного пространтсва undo будет 1664*25=40265 Кб, что всего лишь 40 Мб. Елси текущий размер меньше, это оторазится в секции помошника Undo. Пока что не было ошибок транзакций, и ошибок запросов вызванных недостатком места или перезаписью данных undo.

     

    1

     

    Создание и управление табличных пространтсв undo

     

    С точки зрения управления файлами, табличное пространство undo такое же как другие табличные пространтсва: файлы можно добавлять, изменять размер, включать, выключать, перемещать и переименовывать. Но вы не можете указать свойства хранения: не можете указать метод управления пространтсвом сегментов, или uniform extent size. Для создания табличного пространства undo используется ключевое слово UNDO

     

    CREATE UNDO TABLESPACE tablespace_name

    DATAFILE datafile_name SIZE size

    [ RETENTION NOGUARANTEE | GUARANTEE ] ;

     

    По умолчанию табличное пространство создаётся RETENTION NOGUARANTEE. Это можно или указать явно при создании, либо изменить позднее выполнив

     

    ALTER TABLESPACE tablespace_name retention [ GUARANTEE | NOGUARANTEE ] ;

     

    Exam tip

    Пока вы не укажете явно при создании, файлы данных табличного пространтсва undo не будут авто-расширяемы. Но если вы создавали базу данных используя DBCA, то будет включено авто-расширение файлов и максимальный размер файлов будет неограничен. Автоматическое расширение может быть включено или отключено в любое время, как для любого файла данных.

     

    Невозможно создать сегменты в табличном пространстве undo, кроме тех сегментов undo которые будут созданы автоматически. Вначале будет группа из десяти сегментов undo которые создаются при создании табличного пространтсва. Затем буду т создаваться дополнительные сегменты если в базе будет больше чем десять параллельных транзакций. Oracle следит за количество параллельных транзакций и создаёт сегменты при необходимости.

    Неважно сколько у вас табличных пространств undo в базе данных, грубо говоря, только одна будет использоваться в определённый момент. Сегменты undo в актвном табличном пространстве имеют статус online (т.е. доступны для использования); а сегменты в других табличных пространствах будут иметь статус offline, т.е. то что они не могут использоваться. Если табличное пространтсво undo изменяется, все сегменты в старом табличном пространтсве будут выключаться, а сегменты нового табличного пространтсва будут включены. Но бывает два исключения, это

    RAC база данных. В каждом экземпляре БД должно быть своё табличное пространтсво undo. Это можно контролировать установив разное значение параметра UNDO_TABLESPACE для каждого экземпляра. Каждый экземпляр управляет статусом своих сегментов undo

    Если табличное пространтсво undo изменяется путём указания нового значения UNDO_TABLESPACE, то любые сегменты в предыдущем табличном пространстве связанные с активной транзакцией будут online пока транзакция не закончит работу.

  • Транзакции и данные отката

    Когда начинается транзакция, Oracle назначает ей один (и только один) сегмент отката. Любоая транзакция может охраняться одним и только одним сегментом отката – невозможно распределять данные отката сгенерированные одной транзакцией между несколькими сегментами отката. Это не проблема, так как сегменты отката не имеют фиксированного размера. То есть если транзакции необходимо больше места, Oracle автоматически добавит экстент для сегмента и транзакция продолжится. Несколько транзакций могут использовать один сегмент отката, но в обычной ситуации такого не должно происходить. Для rollback сегментов обычной проблемой настройки производительности была оценка сколько сегментов необходимо чтобы исключить пересечение данных транзакций внутри сегмента и не создавать слишком много чтобы не использовать место впустую. Одним из преимуществ undo является то что Oracle будет автоматически создавать новые сегменты по запросу чтобы транзакции не использовали по возможности одинаковые сегменты undo. Если Oracle обнаруживает что необходимо увеличить существующий undo сегмент или создать новый из-за высокой нагрузки, он сделает это автоматически, однако после того как эти сегменты не нужны (или им не нужно так много места) Oracle удалит ненужные сегменты и укоротит существующие.

     

    Exam tip

    Транзакции не могут использовать несколько undo сегментов, но один сегмент может поддерживать несколько транзакций

     

    Так как транзакция обновляет блоки данных таблицы или индекса, информация необходимая для отмены этих изменений записывается в блоки назначенного сегмента undo. Все это происходит в буфере кэша базы данных. Oracle гарантирует атомарность: вся информация undo хранится до завершения транзакции. Если необходимо то DBWn запишет изменённые блоки undo в сегменты undo в файлах данных. По умолчанию Oracle не гарантирует согласованность теста ACID. Oracle гарантирует согласованность с таким уточнением, что если запрос выполнится успешно – результат будет содержать данные какими они были на момент начала запроса – но не гарантируется что запрос будет выполнен успешно. Это значит что undo данные можно разделить на катеогрии. Рабочие (active) данные отката – это данные которые могут потребоваться для отмены активных транзакций. Эти данные никогда не будут перезаписаны, пока транзакция не будет завершена. С другой стороны устаревшие (expired) данные это данные завершённых транзакций, которые Oracle не обязан больше хранить. Эти данные могут быть перезаписына если Oracle требуется место для записи данных другой активной транзакции. Неустаревшие (unexpired) данные – это не активные данные, но и не устаревшие: транзакция завершены, но данные undo могут требоваться для согласованного чтения, если выполняются какие-то длительные запросы. Oracle старается не перезаписывать неустаревшие данные по возможности.

     

    Exam tip

    Активные данные undo никогда не могут быть перезаписаны: устаревшие данные могут быть перезаписаны. Неустаревшие данные могут быть перезаписаны, но только при условии недостаточности места

     

    Тот факт что undo данные становиятся неактивными после подтверждения транзакции означает что сегменты undo используются по-кругу. В итоге все табличное пространтсво заполнено данным undo, и когда начинается новая транзакция или активная транзакция создаёт новые данные undo, сегмент undo проверяет есть ли старые ненужные данные и они перезаписываются новыми – конечно если страные данные это не часть какой-то длинной незавершённой транзакции, в этом случае сегмент будет автоматически увеличен.

    В случае использования старых rollback сегментов, которыми необходимо управлять вручную, приходилось контролировать какие транзакции используют какие сегменты. Иногда даже приходилось создавать отдельные сегменты именно для одной длинной транзакции. Автоматически управляемые сегменты undo избавляют вас от необходимости следить за всем этим, так как вы больше не должны контролировать процесс использования сегментов отката транзакциями. Oracle автоматически проконтролирует ситуацию лучше чем человек когда-либо сможет, однако если вы всё же хотите высянить какой сегмент назначен какой транзакции вы можете использовать представления V$TRANSACTION, V$SESSION и DBA_ROLLBACK_SEGS. На основании данных из этих представлений вы можете построить картину активности транзакция в вашей БД: сколько транзакций активно, кто их запустил, какие сегменты undo используются, когда транзакция начала работу и сколько блоков данных undo сгенерировано каждой транзакцией. В представление V$ROLLSTAT так же есть информация о размерах сегментов.

    На рисунке 8-7 показан запрос для просмотра текущих транзакций. Первый запрос показывает текущие транзакции. На рисунке мы видим что активны две транзакции. Транзакции Джона назначен сегмент с SEGMENT_ID=7 и использовано 277 блоков данных. Транзакция Скотта гораздо меньше и ей назначен сегмент 2. Второй запрос показывает информацию о сегментах. Размер каждого сегмента будет зависит от размера данных undo сгенерированных транзакциями. Столбец для объединения информации с DBA_ROLLBACK_SEGS называется USN (USN=SEGMENT_ID).

    1

     

     

  • Обзор данных отката

    Данные отката (undo data) это информация необходимя для отмены любой команды DML. Часто можно встретить понятие rollback data, но старайтесь избегать использования этого термина. В старых версиях Oracle undo data и rollback data были взаимозаменяемы, но начиная с версии 9i они стали разными: их назначение одинаково но управление ими различно. Когда транзакция изменяет данные, версия данных до обновления записывается в rollback сегмента или в undo сегмент. Разница огромная. Сегменты rollback всё ещё могут существовать в БД версии 11g, но начиная с версии 9i Oracle рекомендует использовать undo сегменты – rollback сегменты существуют только для обратной совместимости. Отмена транзакции означает использование данных из сегмента undo для создания образа данных, какими они были до транзакции. Это обычно делается автоматически для прохождения ACID теста, но возможность исользования flashback запросов показывает мощь механизма undo позволяя получать данные из БД такими какими они были какое-то время назад. И конечно любой пользователь может использовать команду ROLLBACK для отмены DML команд которые были выполнены но не подтверждены.

    ACID тест требует, во первых, сохранения исходного состояния данных в таком виде, чтобы его можно было восстановить путём отмены неподтвержденных транзакций – неважно автоматически в случае ошибки или по запросу команды ROLLBACK. Такой вид отмены постоянный и доступный для всех пользователей.  Во вторых, для согласованности, база данных должна иметь возможность предоставить данные по запросу в том виде, в каком они были на момент начала запроса. Серверный процесс выполняющий запрос будет использовать undo сегменты для создания согласованного образа (read-consistent image) блоков используемых в запросе, если они изменились после начала запроса. Этот тип отмены изменений временный и видимый только той сессии которая выполняет запрос. В третьих, сегменты undo также используются для изоляции транзакций. Это самый сложные способ использования данных undo. Принцип изоляции гласит что транзакции не могут зависить от любой другой незавершённой транзакции. Как результат такого правила, даже в мультипользовательской базе данных в которой выполняется много транзакций одновременно, конечный результат должен быть таким, как будто бы транзакции выполнялись одна за другой. Использование данных undo в сочетании с механизмом блокировок гаранитурует изоляцию транзакций: невозможность несовместимых транзакций. Даже если несколько транзакций работали параллельно, принцип изоляции требует чтобы конечный результат был таким, как будто транзакции выполнялись последовательно.

     

    Exam tip

    Использование сегментов undo несовместимо с использование сегментов rollback: может быть либо одно либо другое в зависимости от настроек параметра UNDO_MANAGEMENT

  • Обнаружение и разрешение конфликтов блокировок

    В любой многопользовательской среде неизбежно ситуация, когда два пользователя захотят работать с одними и теми же данными в одно и то же время. База данных должна обеспечивать отсутствие такой возможности. Принцип изоляции из ACID теста гласит что база данных должна гарантировать что сессии не должны видеть результаты выполнения транзакций других сессий до тех пор, пока транзакция не завершена. Для обеспечения такого результата БД должна упорядочить параллельный доступ к данным; т.е. убедиться, что даже если сессии затребовали доступ к одним и тем же строкам, в реальности запросы выстраиваются в очередь и ждут своей очереди.

    Упорядочивание доступа происходит за счёт работы механизма табличных и строчных блокировок.  Блокировка в Oracle происходит полностью автоматически. Грубо говоря, проблемы возникают только если программа пытается взаимодействовать с механизмом блокировок с помощью плохо написанного кода, или если бизнес аналитики и бизнес-модель разработана неправильно где сессии будут пересекаться.

     

    Общие и исключительные блокировки

     

    Стандартный уровень блокировок в Oracle гарантирует максимальный уровень параллелизма. Это значит что если сессия обновляет одну строку – блокируется одна строка, ничего больше. Более того, строка блокируется только для изменения – остальные сессии могут считывать эту строку. Блокировка существует пока транзакция не завершена, либо COMMIT либо ROLLBACK. Это исключительная (exclusive) блокировка: первая сессия затребовала блокировку строки на изменение, остальные сессии которые хотят заблокировать строку для изменения должны ждать. Доступ для чтения разрешён – несмотря на то что строка изменяется сессией заблокировавшей строку, операции чтения будут использовать данные отката чтобы гарантировать недоступность данных неподтверждённых транзакций.

    Только одна сессия может блокировать строку или таблицу исключительной блокировкой – но общие (shared) блокировки могут накладываться на один объект многими сессиями. Нет никакого смысла использовать общую блокировку для строки, так как единственной целью блокировки стрки это получение уникального доступа к данным для изменения. Общие блокировки накладываются на всё таблицу, и многие сессии могут наложить общую блокировку на одну и ту же таблицу. Общие блокировки нужны для того, чтобы предотвратить исключительную блокировку таблицы другими сессииями: вы не можете получить исключительную блокировку если уже существует общая блокировка. Эксклюзивная блокировка таблицы нужна для выполнения DDL команд. Вы не можете выполнить запрос которые изменяет объект (к примеру удалить столбец из таблицы) если хотя бы одна другая сессия заблокировала таблицу общей блокировкой.

    Для выполнения DML команда над строками, сессия должна получить исключительные блокировки всех строк которые будут изменяться и общую блокировку для таблицы. Если другая сессия уже наложила исключительную блокировку на строки, сессия будет висеть пока блокировки не будут убраны командой COMMIT или ROLLBACK. Если другая сессия заблокировала таблицу общей блокировкой но исключительная блокировка наложена на другие строки – то всё в порядке оба запроса могут работать. Исключительная блокировка для таблицы может быть, но по умолчанию механизм блокировок не блокирует всю таблицу пока это не необходимо для DDL команды.

    Все DML команды требуют минимум две блокировки: исключительная блокировка строки которая изменяется и общая блокировка для таблицы содержащей строку. Исключительная блокировка предотвращает взаимодействие других сессий с изменяемой строкой  а общая блокировка предотвращает другие сессии от изменения таблицы с помощью DDL команды. Эти блокировки запрашиваются автоматически. Если DML запрос не может получить необходимые блокировки – сессия будет висеть до момента получения этих блокировок.

    Для выполнения DDL команды – необходимо исключительная блокировка всего объекта. Эта блокировка не может быть получена пока не завершены все DML транзакции к таблице и не освобождена исключительные блокировки строк и общие блокировки таблицы. Исключительная блокировка необходимая для DDL команды запрашивается автоматически, но если нельзя заблокировать объект в текущий момент – обычно потому что другие сессии наложили общую блокировку – то запрос прекратит выполнение с ошибкой вместо ожидания.

     

    Механизм размещения в очереди

     

    Запросы на блокировку помещаются в очередь. Если сессия запросила блокировку и не может получить её так как другая сессия уже заблокировала строку или объект, сессия будет ждать. Может случить что несколько сессий ждут доступа для одной и той же строки или объекта – в этом случае, Oracle будет отслеживать порядок в котором сессии запрашивали блокировку. Когда сессия заблокировавшая объек или строку освобождает его – блокировка разрешается следующей сессии и так далее. Это называется механизм размещения в очереди (enqueue mechanism).

    Если вы не хотите чтобы сессия ждала в очереди если нет возможности заблокировать объект, то единственным способом избежать этого будет использование WAIT или NOWAIT директивы в команде SELECT … FOR UPDATE. Обычный SELECT всегда выполнится успешно так как SELECT не требует каких-либо блокировок – но DML команда будет висеть. Команда SELECT… FOR UPDATE вернёт набор строк и заблокирует их исключительной блокировкой. Если строки уже заблокированы – команда будет ждать в очереди пока не освободятся блокировки, как обычная DML команда. Для того чтобы избежать зависания сессии можно использовать SELECT… FOR UPDATE NOWAIT или SELECT… FOR UPDATE WAIT <n> где n это количетсво секунд ожидания. После получения блокировок с помощью команды SELECT FOR UPDATE вы можете выполнять DML команды без возможности зависания сессии.

     

    TIP

    Возможно добавить директиву SKIP LOCKED к команде SELECT FOR UPDATE, тогда запрос вернёт только те строки которые не заблокированы другими сессиями. Эта команда существовала и раньше но поддерживается только с версии 11g

     

    Конкуренция блокировок

     

    Когда сессия запрашивает блокировку для строки или объекта и не может её получить потому что объекты уже заблокированы другой сессией – сессия зависает. Это конкуренция блокировок, и она может плохо сказыватьяс на производительности базы данных так как все сессии в очереди ожидают блокировки. Некоторые блокировки могут быть необходимыми: природа приложения предполагает доступ разными пользователями к одним и тем же данным в один и тот же момент времени в результате работы. Некоторые же параллельные блокировки могут быть вызваны неправильно написанной программой.

    Oracle предоставляет способ для обнаружения конкурирующих блокировок и также возможность разрешить проблему конкуренции в случае необходимости. Отдельным видом конкурирующих транзакций является deadlock. В случае возникновения таких ситуаций БД устраняет их автоматически.

     

    Причины конкурирующих транзакций

     

    Иногда бывает что бизнес-пользователям необходимо изменять данные в одних и тех же строках одновременно. Если это тормозит производительность системы, единственных выходом будет разработка новой бизнес-модели и новых бизнес-процессов. Но несмотря на то, что часть конкурирующих блокировок это правильное поведение системы – иногда конкуренция возникает из-за плохо разработанного приложения, что усугубляет проблему.

    Длительные транзакции всегда будут вызывать проблемы. Типичным примером является случай, когда пользователь обновляет строку и не подтверждает транзакцию. Возможно пользователь даже ушёл на обед и не подтвердил транзакцию. Вы не сможете контролировать это если пользователи работают с помощью таких инструментов как SQL *Plus, но этого никогда не должно происходить в хорошо продуманном приложении. Программа должна учитывать что блокировка должна запрашиваться непосредственно перед изменением данных и освобождаться немедленно после завершения работы.

    Некоторые программы запрашивают больше блокировок чем им необходимо. Например в некоторых программах для разработки всегда используется SELECT.. FOR UPDATE чтобы избежать необходимости перечитывать данные и проверять их на изменения. Некоторые инструменты для разработки не используют блокировку строки: если пользователь хочет обновить всего одну строку – компонент запрашивает блокировку для нескольких десятков или даже сотен строк. Если ваша программа написана с использованием таких компонентов – база данных Oracle будет именно то что вы сказали ей делать: блокировть много строк вместо одной, что не необходимо с точки зрения бизнес-логики.

     

    Обнаружение и разрешение проблем вызванных конкурирующими транзакциями

     

    Существуют представления в которых хранится информация о блокировках в базе данных, но это один из тех случаев когда даже очень опытные администраторы обычно предпочитают использовать инструменты с графическим интерфейсом. Чтобы попасть в окно управления блокировками в Database Control перейдите на вкладку Performance из домашней страницы а затем перейдите по ссылке Instance Lock в секции Additional Monitoring. На рисунке 8-6 отображено окно Instance Locks, с выбранной секцией Blocking Locks. Может быть любое количество блокировок в базе данных, но нас интересут только запросы на блокировки которые не могут быть выполнены (сессии висят). Такие блокировки известны как заблокированные блокировки (bBlocking locks).

    На рисунке 8-6 видны две проблемы. Сессия с номером 116 подключенная к аккаунту SCOTT заблокировала одну или более строк в таблице HR.EMPLOYEES. Эта сессия не висит – она работает в обычном режиме. Но сессия 129, подключенная как пользователь MPHO заблокирована – она ждёт освобождения блокировок сессией 116. Сессия 129 висит в данный момент и продолжит работу когда сессия 116 освободит блокировки выполнив команду ROLLBACK или COMMIT. Вторая проблема хуже: пользователь JON блокирует две сессии – ISAAC и ROOP.

    1

     

    Конкуренция блокировок это обычное последствие одновременного доступа разных пользователей к одним и тем же данным. Эта проблема может усиливаться из-за плохого приложения, но в принципе конкуренция блокировок это часть нормальной работы базы данных. Поэтому DBA не может решить эту проблему полностью – он может только указать что существует проблема, и предложить учитывать эту информацию при проектировании системы: разработке структур данных и процессов.

    Если блокировки становятся проблемой, как на рисунке 8-6, то необходимо изучить причину. Database Control может предоставить необходимую информацию. Нажав на значения в столбец SQL ID вы сможете увидеть SQL запрос, выполнение которого вызвало конкурирующую блокировку. Столбец “ROWID” можно использовать чтобы найти конкретную строку за которую конкурируют сессии. Вы не можете посмотреть строку в этом окне Database Control но вы можете использовать значение и выполнять запросы в отдельной сессии (которая не требует блокировок). Когда запросы и данные известны, можно обсудить решение проблемы с программистами и бизнес-аналитиками.

    В экстренных случаях, DBA может разрешить конкретную ситуацию – отключив сессию, или сессии которые задерживают много блокировок слишком долго. Когда сессия отключается принудительно – все блокировки вызванные этой сессией освобождаются и транзакция отменяется. Заблокированные сессии смогут продолжать работу. Для отключения сессии можно использовать Database Control или команду ALTER SYSTEM KILL SESSION. В нашем примере если мы решим отключить пользователя SCOTT, можно выбрать эту строку и нажать кнопку KILL SESSION.

     

    Deadlock

     

    Возможно возникновение ситуации, когда две сессии блокируют друг друга таким образом что обе будут висеть вечно, каждая будет ожидать освобождения блокировок другой. Это называется deadlock. Deadlock-и это не проблема DBA: они могут быть вызваны только плохой архитектурой системы и разрешаются автоматически базой данных. Информация о возникновении deadlock-ов записываетя в системный журнал, с подробным описание в файле трассировки – частью обычного мониторинга базы данных является проверка на возникновение deadlock-ов и предоставление разработчиками подробной информации при каких обстоятельствах это произошло.

    Если возникает deadlock – обе сессии зависнут, но лишь на короткое время. Одна из сессий обнаружит возникновение deadlock-а и произойдёт отмена запроса вызывающего проблему с ошибкой “ORA-00060 Deadlock detected”. Это сообщение должно отслеживаться программистами.

    Вы должны понимать что deadlock-и возникают только по вине неправильно спроектированной программы. Код пытается выполнить что-то, что логически невозможно. Хорошо написанное приложени всегда вызывает блокировки последовательно таким образом, чтобы исключить возникновение deadlock-ов или будет проверять наличие несовместимых блокировок перед тем как их запрашивать.

  • Обзор и администрирование PL/SQL объектов

    PL/SQL это язык третьего уровня которые работает внутри БД. Вы может использовать его для получения и обработки данных с использованием SQL вместе с использованием конструкций функуионального программирования такие как IF…THEN…ELSE и циклов такие как FOR или WHILE. Код программы PL/SQL может храниться на пользовательской машине и отсылаться на сервер для выполнения или хранится внутри БД как именованный блок кода.

     

    Exam tip

    PL/SQL всегда выполняется внутри БД, вне зависимости от того где он хранится. Java может работать как на пользовательской машине так и на стороне БД.

     

    Хранимый и анонимный код PL/SQL

     

    PL/SQL выполняется на стороне БД но он может храниться как на клиентской стороне так и на стороне сервера. PL/SQL код можно также вводить из командной строки. Хранимый PL/SQL загрудается в базу данных и хранится в словаре данных как именованный объект. Когда он сохраняется в БД – он компилируется: процесс компиляции проверяет синтаксические ошибки и ошибки связанные с объектами данных к которым обращается код. Это помогает экономить время когда код выполняется и программисты должны убрать ошибки в момент компиляции, чтобы пользователи не сталкивались с ними. Код который хранится удалённо или код вводимый в командной строке называется анонимным PL/SQL. Он компилируется динамически что сказывается на производительности и появляется возможность непредвиденных ошибок.

    На рисунке 8-5 показаны примеры выполнения анонимного PL/SQL блока и созданиеи выполнение хранимой процедуры.

    Анонимный блок создаёт переменную с именем INCREASE с помощью команды DECLARE и устанавливает значение в 10. Затем функциональный код (между BEGIN и END) использует переменную для SQL запроса который обновляет значение столбца в таблице. На втором примере создаётся процедура с именем INC_SAL, хранимая в словаре данных. Она принимает численные аргумент с именем INCREASE и использует его в команде SQL. Затем процедура вызывается с помощью команды EXECUTE и указанием значения для аргумента.

    Эти примеры очень простые но они показывают что анонимный блок выполняется единожды и должен быть скомпилирован во время выполнения, а хранимый PL/SQL может быть заранее скомпилирован и затем выполняться много раз.

    1

     

    Объекты PL/SQL

     

    Часто используется пять типов PL/SQL объектов: процедуры, функции, пакеты, тело пакета, триггер.

    Все они являются объектами схемы и хранятся в словаре данных. Процедуры и функции это подпрограммы обычно предназначенные для выполнения последовательных инструкций. Пакеты это коллекции процедур и функций собранных вместе для более лёгкой управляемости. Триггеры нельзя поместить в пакет: они ассоциируются с таблицами и выполняются в момент выполнения определённой DML команды к этой таблице.

     

    Процедуры и функции

     

    Процедура это блок кода который выполняет определённые действия. Он может определяться с параметрами (или без параметров). Эти параметры заменяются на значения когда процедура вызывается. Параметры могут быть входными (IN) что обозначает что они используются для передачи данных в процедуру или выходными (OUT) что значит что эти параметры изменяются во время выполнения процедуры и затем новые значения возвращаются процедурой. Параметры также могут быть IN-OUT что значит что они используются и как входные и как выходные одновременно. Внутри процедуры можно определить переменные, которые в отличие от параметров видны только внутри процедуры. Для запуска процедуры можно вызвать её из PL/SQL кода или выполнить команду EXECUTE.

    Функции подобны процедурам, но у них не бывает OUT параметов и их нельзя вызывать с помощью команды EXECUTE. Они возвращают одно значение с помощью команды RETURN.

    Всё что может сделать функция – может сделать и процедура. Функции обычно используются для относительно простых операций: небольшой участок кода который будет использоваться много раз. Процедуры используются для разделения кода на модули и могут содержать длинную и сложную обработку.

     

    Пакеты

     

    Путём группировки связанных процедур и функций программисты могут создавать пакеты. Пакет состоит из двух объектов: спецификации и тела. Спецификация перечисляет процедуры и функции доступные для вызова вместе с их параметрами и их типами данных. Так же в спецификации можно определить переменные которые будут доступны для всех процедур и функций внутри пакета. Тело пакета содержит PL/SQL код: код который создаёт процедуры и функции. Для создания спецификации пакета используется команда CREATE PACKAGE. Например

    2

    Затем для создания тела пакета используется команда CREATE OR REPLACE PACKAGE BODY для создания функций и процедур пакета.

    Доступно несколько сотен стандартных пакетов после установки Oracle. Для вызова процедуры из пакета вы должны указать имя процедуры и префикс – имя пакета. Например

     

    exec  numbers.odd_even(5);

     

    Такая команда запустить процедуры ODD_EVEN из пакета NUMBERS. Пакет должен существовать в схеме текущего аккаунта или придётся указать явно имя схемы перед именем пакета. Также у пользователя должны быть права EXECUTE для пакета.

     

    Триггеры (triggers)

     

    Триггеры это определённый тип объектов PL/SQL которые нельзя вызвать вручную. Триггеры запускаются (срабатывают) автоматически когда выполняется определённое действие: событие триггеры (triggering event). Доступны разные типы событий и для многих из них можно указать время выполнения триггера: до или после события. Так же возможно определить триггеры для одного события с разным временем срабатывания. Триггеры DML, которые срабатывают когда строки добавляются, изменяются или удаляются можно настроить на запуск для каждой затронутой командой строки, или на запуск для всей команды.

    У всех триггеров одно общее свойство: их выполнение никак не контрлируется пользователем кто выполнил событие. Пользователь может даже не знать что выполнялся какой-либо триггер.

    В таблице ниже описаны часто используемые события триггеров

    3

    Для команды SELECT нет триггера но fine-grained auditing (лабораторная работа №6) может быть использовано для достижения схожего эффекта.

    Триггеры часто используются для

    Аудита действий пользователей – триггер может записывать все детали кто и что сделал и записывать данные в таблицу аудита

    Выполнения сложных изменений – изменения одной строки могут требовать дополнительных действий. Триггер может сделать это автоматически

    Безопасности – триггер может проверять например IP-адресс клиента или программу из которой выполняется запрос или любые другие факторы для проверки допустимых для конкретной сессии действий

    Проверки сложных ограничений – действия над таблицей должны проверять данные в других таблицах

     

    Exam tip

    Невозможно запустить триггер никаким другим образом кроме как выполнив определённое действия приводящее к заданному событию

  • Управление транзакциями

    Концепция транзакции лежит в основе реляционной парадигмы. Транзакция состоит из одной или нескольких DML команд и следующей командой или ROLLBACK или COMMIT. Возможно использовать команду SAVEPOINT для определённого управления внутри транзакции. Перед рассмотрением синтаксиса необходимо рассмотреть концепцию транзакций. Связанная с этой темой это тема согласованного чтения; это реализуется автоматически на уровне Oracle сервера, но некоторые программисты могут управлять им с помощью SELECT команд.

     

    Транзакции БД

    Механизм Oracle для обеспечения транзакционной целостности основан на сочетании сегментов отмены изменений и файла журнала логов: этот механизм бесспорно лучший из всех созданных на сегодняшний день и полностью удовлетворяет международным стандартам обработки данных. Производители других БД реализуют стандарт своими собственными другими способами. Вкратец, любая реляционная база данных должна удовлетворять тесту ACID: должны быть гарантированы атомарность (A – atomicity), согласованность (C – consistency), изолированность (I – isolation) и долговечность (D – durability).

     

    Aтомарность

     

    Принцип атомарности гласит что либо все части транзакции должны быть выполнены успешны либо ни одна из них. Например если бизнес-аналитик утвердил правило что при смене зарплаты сотрудника обязательно изменяется уровень сотрудника то ваша атомарная транзакция будет сосять из двух частей. БД должна гарантировать что будут применены либо оба изменения, либо ни одного. Если только одно изменения будет успешно то у вас появится сотрудник чья зарплата несовместима с его уровнем: повреждение данных в терминах бизнеса. Если что-нибудь (вообще что-нибудь) пошло не так до подтверждения транзакции, БД должна гарантировать что вся работа совершённая до этого момента от начала транзакции будет отменена: это должно работать автоматически. Несмотря на то что атомарность транзакции звучит как что-то маленькое – транзакции могут быть долгими и очень важными. Рассмотрим другой пример, в бухгалтерской книге не может быть данных на пол-месяца Августа и пол-месяца Сентября: закрытие месяца с точки зрения бизнеса одна атомарная транзакция, которая может обрабатывать миллионы строк и тысячи таблицы и работать несколько часов (или отменяться если что-то пошло не так). Отмена транзакции может быть ручной (выполнив команду ROLLBACK) но она должна быть автоматической и неотменяемой в случае ошибки.

     

    Согласованность

     

    Принцип согласованности данных гласит что результат запроса должен быть согласован с состояним базы данных на момент старта работы запроса. Преставим простой запрос которые считает среднее значение столбца в таблице. Если таблица большая, это займёт достаточно долгое время для прохода по всем строкам таблицы. Если другие пользователи в это время обновляют данные пока запрос выполняется, должен ли запрос брать новые значения или старые? Должен ли результат запроса учитывать строки которые были добавлены или не учитывать строки которые были удалены? Принцип согласованности требует чтобы БД гарантировала что любые изменения после старта запроса не были видны для этого запроса; запрос должен вернуть среднее значение столбца на момент когда запрос был запущен, вне зависимости от того как долго длился запрос и какие изменения были над данными. Оракл гарантирует что если запрос выполнен успешно – результат будет согласованным. Как бы там ни было, если администратор базы данных не настроил базу данных соотвествующим образом, запрос может не выполнится: возникнет знаменитая ошибка “ORA-1555 snapshot too old”. Раньше было очень сложно решить такие ошибки, но в последних версиях администратор легко может решать эти ситуации.

     

    Изолированность

     

    Принцип изолированности гласит что незаконченная (неподтверждённая транзакция) должна быть невидима для остального мира. Пока транзакция в процессе только сессия которая выполняет эту транзакцию видит зименения. Все остальные сессии должны видеть неизменённые данные. Почему так? Во первых, транзакция может целиком не выполниться до конца (помним про принцип атомарности и согласованности) и поэтому никто не должен видеть изменения которые могут быть отменены. Во вторых во время действия транзакции данные (в терминах бизнеса) бессвязные: для нашего примера обновления зарплаты будет существовать промежуток времени когда зарплата изменена, а уровень ещё нет. Изолированность транзакций требудет чтобы база данных прятала текущие транзакции от других пользователей: они будут видеть данные до изменений пока транзакция выполняется, а затем сразу будут видеть все изменения как согласованный набор данных. Oracle гарантирует изолированность транзакций: нет способа для сессии (отличной от той что делает изменения) увидеть неподтверждённые данные. Чтение неподтверждённых данных (известное как грязное чтение dirty read) не позволяется Oracle (несмотря на то что некоторые другие БД позволяют).

     

    Долговечность

     

    Принцип долговечности указывает на то, что если транзакция успешно завершена, то должно быть невозможно потерять эти данные. Во время работы транзакции принцип изолированности требует чтобы никто кроме сессии выполняющей изменения не видел их. Но как только транзакция успешно завершила работу, изменения должны стать доступны для всех и база данных должна гарантировать что они не будут потеряны. Oracle выполняет это требование путём записывания всех векторов изменений в файлы логов перед тем как изменения подтверждены. Применив этот логи изменений к резервным копиям, всегда возможно повторить любые изменения которые были выполнены в момент остановки или повреждения базы данных. Конечно данные могут быть потеряны из-за ошибок пользователей, таких как выполнение неверных DML запросов или удаление таблиц. Но с точки зрения Oracle и администратора базы данных, такие события тоже транзакции: согласно принципу долговечности их нельзя отменить.

     

    Выполнение SQL запросов

     

    Весь язык SQL состоит из около дюжины команд. Сейчас нас интересуют команды: SELECT, INSERT, UPDATE и DELETE.

     

    Выполнение команды SELECT

     

    Команда SELECT получает данные. Выполнение команды SELECT это процесс состоящий из нескольких этапов: серверный процесс выполняющий запрос проверит существует ли необходимые блоки данных в памяти, в буфере кэша. Если они там, то выполнение может продолжаться, иначе серверный процесс должен найти данные на диске и скопировать их в буфер кэша.

     

    EXAM TIP

    Always remember that server processes read blocks from datafiles into the database buffer cache, DBWn writes blocks from the database buffer cache to the datafiles.

     

    Когда блоки с нужными для выполнения запроса данными находятся в кэш буфере любые дополнительные процессы (такие как сортировка и аггрегирование) продолжаются в PGA сессии. Когда выполнение завершено, результат возвращается пользовательскому процессу.

    Как это связано с тестом ACID? Для согласованности, если запрос обнаружит что блок данных изменился с момента старта запроса, серверный процесс найдёт сегмента отката (отмены изменений или сегмент undo) соответствующий этому изменению, найдёт старую версию данных и (для текущего запроса) отменит изменение. Таким образом изменения которые произошли после начала запроса будут не видны. Похожим образом гарантируется изолированность транзакций, несмотря на то что изолированность основана и на подтверждённых изменениях. Честно говоря, если данные необходимые для отмены изменений не существуют больше в сегменте отката – этот механизм не сработает. Отсюда и следует ошибка “snapshot too old”.

    На рисунке 8-4 показан путь обработки запроса SELECT

    1

    Шаг 1 это передача пользовательского запроса от пользовательского процесса к серверному. Серверный процесс просматривает буфер кэш на наличие нужных блоков и если они в буфере то переходит к шагу4. Если нет то шаг 2 находит блоки в файлах данных и шаг 3 копирует данные в буфер. Шаг 4 передает данные сервеному процессу где может быть дополнительная обработка перед тем как шаг 5 вернёт результат запроса пользовательскому процессу.

     

    Выполнение команды UPDATE

     

    Для любой команды DML необходимо работать с блоками данных и блоками отката (undo blocks), а также создавать лог изменений (redo): A,C и I принципы теста ACIDS требуют создания данных отката; D требует создание данных повтора изменений (redo).

    Exam tip

    Undo не противоположна redo! Redo защищает все изменения блоков, вне зависимости это изменения блока таблицы, индекса или сегмента отката. Для redo — undo сегмент такой же сегмент как таблцы и все изменения должны быть долговечны (durable)

     

    Первый шаг при выполнении DML команды такой же как и при выполнении команды SELECT: необходимые блоки должны быть найдены в кэф буфере или скопированы с файлов данных в буфер. Единственное отличие это то что дополнительно требуется пустой (или устаревший – expired) блок отката. Затем выполнение становится сложнее чем при команде SELECT.

    Вначале блокировки должны быть указаны для все строк и соотвествующих индексов которые будут задействованы в процессе.

    Потом создаются данные redo: серверный процесс записывае в логи буфера вектора изменений которые будут применены к данным. Redo данные создаются и для изменений блока данных и для изменений блока отката: если столбец в строке будет обновлен то rowid и новое значение записывается в буфер лога (изменение которое будет применено к блоку таблицы), а также старое значение столбца (изменение для блока отката). Если столбец это часть ключа индекса – то изменения в индексе тоже будут записаны в буфер лога, вместе с изменениями которые будут сделаны в блоке отката для защиты изменений индекса.

    После того как все redo данные созданы, обновляются данные в буфер кэше: блок данных обновляется на новую версию с измененным столбцом, а старая версия записывается в блок отката. С этого момента до подтверждения транзакции, все запросы от других сессий обращающиеся к этой строке будут перенаправлены на блок отката. Только сессия которая делает UPDATE будет видеть актуальную версию строки а блоке таблицы. Такой же принцип применяется для всех связанных индексов.

     

    Выполнение команд INSERT и DELETE

     

    Концептуально INSERT и DELETE управляются в той же манере как и UPDATE. Вначале происходит поиск нужных блоков в буфере и если их нет то они копируются в память.

    Redo создается точно так же: все вектора изменений которые будут применены к данным и блокам отката вначале записываются в буфер лога. Для команды INSERT вектор изменений блока таблицы (и возможно блоков индекса) это байты которые составляют новую строку (и возможно новый ключ индекса). Вектор для блока отката это rowid новой строки. Для команды DELETE вектор для блока отката это вся строка.

    Ключевым отличием между командами INSERT и UPDATE является количество данных для отката. Когда строка добавляется единственными данными для отката будет запись rowid в блок отката, потому что для отмены команды INSERT единственная информация нужная Oracle это rowid строки и может быть создана команда

    delete from table_name where rowid=rowd_id_of_new_row;

    Выполнение этой команды отменит изменение.

    Для команды DELETE вся строка (которая может быть несколько килобайт) должна быть записана в блок undo, и тогда удаление может быть отменено при необходимости путём генерации запроса который заново добавил полностью строку в таблицу.

     

    Начало и конец транзакции

     

    Сессия начинает транзакция в момент когда она выполняет любую DML команду. Транзакция продолжается сколько угодно следующих DML команд пока сессия не выполнит команду ROLLBACK или COMMIT. Только подтвеждённые изменения станут гарантированными и будут доступны для других сессий. Невозможно начать транзакцию внутри транзакции. Стандарт SQL не разрешает пользователям начать транзакцию, а затем начать новую перед завершение первой. Это можно сделать используя PL/SQL (язык Oracle третьего поколеняи), но не стандартным SQL.

    Командами управления транзакциями являются команды COMMIT, ROLLBACK и SAVEPOINT. Также могут возникнуть другие обстоятельства помимо явного вызовая команды COMMIT или ROLLBACK которые немедленно прекращают транзакцию

    • Выполнение DDL или DCL команды
    • Завершение польховательского процесса (к примеру пользователь вышел из программы SQL *Plus или SQL Developer)
    • Клиентская сессия «умерла»
    • Проблемы в системе

    Если пользователь выполняет DDL команду (CREATE, ALTER или DROP) иди DCL команду (GRANT или REVOKE) то активная транзакция (если она сущесвтует) будет подтверждена. Так происходит потому что команды DDL и DCL сами являются транзакциями. Так как в SQL невозможно создать вложенные транзакции, если у пользователя уже выполнялась какая либо транзакция, все команды пользователя будут подтверждены вместе с командой DDL или DCL.

    Если вы начали транзакцию выполнив DML запроса, а затем закрыли программу без явного указания COMMIT или ROLLBACK до выхода, транзакция будет прекращена – но прекращена с подтверждением или отменой целиком зависит от программы. У разных программ может быть разное поведение в зависимости от того как вы закончили работу в программе. Например в Windows обычно можно выйти из программы выбрав пункты меню File – Exit или нажав на крестик в правом верхнем углу. Программист мог обработать по разному эти способы завершения и в первом случае указать COMMIT, а во втором ROLLBACK. В любом случае это будет контролируемый выход.

    Если клиентская сессия отказывает по какой-либо причине – база данных всагда отменит транзакцию. Такие отказы могут быть по разным причинам: пользовательский процесс мог быть «убит» диспетчером, проблемы с сетью или поломка пользовательской машины. В любом случае не было явно указана команда COMMIT или ROLLBACK и БД нужно решить что случилось. В таком случае сессия «убивается» и активная транзакция отменяется. И точно так-же база данных ведёт в себя в случае проблем на стороне сервера. Если база данных была закрыта аварийно то при следующем старте все транзакции которые были начаты но явно не завершены будут отменены.

     

    Управление транзакциями: COMMIT, ROLLBACK, SAVEPOINT и SELECT FOR UPDATE

     

    Oracle начинает транзакцию в момент запуска первой DML команды. Транзакция длится до вызова команды ROLLBACK или COMMIT. Команда SAVEPOINT не является частью SQL стандарта и в реальности является легким способом для программиста чтобы отменить изменения частично в обратном порядке.

     

    COMMIT

     

    Выполнение команды COMMIT это тот момент когда многие люди (и даже некоторые администраторы БД) показывают непонимание архитектуры Oracle. Когда вы выполняете COMMIT всё что происходит физически это LGWR записывает буфер логов на диск. DBWn не делает абсолютно ничего. Это одно из самых важных свойств Oracle для достижения высокой производительность БД.

     

    Exam tip

    Что делает DBWn в момент выполнения команды COMMIT? Ответ: абсолютно ничего

     

    Чтобы сделать транзакцию долговечной всё что нужно это записать изменения которые были сделаны в процессе транзакции на диск: нет необходимости в актуальных данных на диске. Если изменения записаны, в виде многих копий логов изменений на диске, то даже в случае повреждения базы все транзакции могут быт повторены восстановив резеврную копию данных до ошибки и применив изменения из логов. На данный момент надо понимать тот факт что COMMIT всего лишь очищает буфер лога на диск и помечает транзакцию как выполненную. Вот почему транзакции в которой были задействованы миллионы обновлений в тысячах файлов в течение нескольких часов могут подветрждаться за долю секунды. Так как LGWR записывает логи практически в режиме реального времени, то виртуально все изменения транзакции уже записаны на диск. Когда вы выполняете COMMIT, LGWR тут же записывает лог на диск: ваша сессия будет ожидать пока запись не закончится. Время задержки будет равно времени которое занимает запись последних данных из буфера логов, что обычно занимает несколько миллисекунд. Потом ваша сессия может продолжать работу и все остальные сессии не будут перенаправлятьяс на данные в сегменте отката при обращении к обновлённым данным, если только принцип согласованности не требует этого. Вектора изменений, записываемыe в лог повтора изменений, это все изменения: применяемых и к блокам данных (таблиц и индексов) и к блокам отката.

     

    EXAM TIP

    Лог redo включает все изменения: применяемые к сегментам данным и к сегментам undo для потдвержденных и неподтвержденных транзакций

     

    Самое непонятное это то что redo записывается LGWR в файлы будет содержать и подтвержденные и неподтвержденные транзакции. Даже больше, в любой момент DBWn может записать а может и не записать измененные блоки сегментов данных или сегментов отката в файлы данных для подтверждённых и неподтверждённых транзакций. То есть ваша БД на диске противоречива: файлы данных могут хранить данные неподтверждённых транзакций и в них могут отсутствовать подтверждённые изменения. Но в любой момент, в случае проблемы, в файле логов на диске достаточно информации чтобы повторить подтверждённые транзакции которые пропущены в файлах данных (используя изменения для блоков данных) и восстановить сегменты отката (используя изменения блоков отката) нужные для отмены всех неподтверждённых транзакций которые записаны в файлы данных.

     

    Exam tip

    Лбая DDL команда, а также GRANT или REVOKE подтвердят текущую транзакцию

     

    ROLLBACK

     

    Пока транзакция в процессе, Oracle хранит образ данных до начала транзакции. Этот образ используется другими сессиями которые обращаются к данным участвующим в транзакции. Также он используется для отменты транзакции автоматически если что-то пойдёт не так или сессия отменит транзакцию.

    Синтаксис для отмены транзакции

     

    ROLLBACK [TO SAVEPOINT savepoint];

     

    Состояние данных перед отменой транзакции содержит изменения, но информация нужная для отмены этих изменений доступна. Эта информация используется другими сессиями для выполнения принципа изолированности. ROLLBACK транзакции отменит все изменения восстановив образ данных до начала транзакции: все добавленные строки будут удалены, все удалённые строки восстановлены, все строки в которых менялись значения вернутся к исходному состоянию. Другие сессии даже не будут знать что что-то происходило, они никогда не видели изменений. А сессия которая инициировала транзакцию после отмены будет видеть данные такими какими они были до начала транзакции.

    SAVEPOINT

     

    Точка сохранения позволяет программистам устанавливать флаг в транзакции которые затем можно использовать для контроля эффекта отмены транзакции. Вместо отмены всей транзакции и её завершения, становится возможным отменить изменения сделанные после конкретного флага но оставить изменения сделанные до этого флага. Действие транзакции в этот момент продолжается: транзакция не подтверждена, всё ещё можно отменить транзакцию целиком и изменения не видны для других сессий.

    Синтаксис команды

     

    SAVEPOINT savepoint

     

    Такая команда создаёт точку в транзакции которая может быть использована в дальнейшем в команде ROLLBACK. На следующей таблице видно количество строк в таблице видимое разным сессиям во время работы транзакции в разные моменты времени. Используемая таблица назвается TAB и у неё один столбец

    2

     

    В примере с выполнены две транзакции: первая завершена командой COMMIT а вторая ROLLBACK. Видно что использование точек сохранения влияет только внутри транзакции для той сессии которая инициировала транзакцию: вторая сессия не видит ничего что не подтверждено.

     

    SELECT FOR UPDATE

     

    Последняя команда для управления транзакциями это SELECT FOR UPDATE. Oracle, по умолчанию, предоставляет наивысший уровень параллелизма: чтение данных не блокирует запись, запись не блокирует изменение. Другими словами нет проблемы если одна сессия пытается считать данные которые другая сессия изменяет и наоборот. Но иногда вам может понадобиться изменить такое поведение и предотвратить возможность изменения данных которые считаны сессией.

    Типичное поведение приложений это выборка данных с помощью команды SELECT, отображение данных пользователю для просмотра и возможность изменения этих данных. Так как Oracle поддерживает параллельную работу пользователей то ничто не мешает другому пользователю получить те же данные. Если обе сессии попробует сделать какие-либо изменения, то могут возникнуть странные ситуации. Следующий пример показывает такую ситуацию

    3

    Вот что увидит первый пользователь (прелположим что используется SQL *Plus)

    4

    Такой результат немного смущает пользователя. Чтобы решить эту проблему можно заблокировать строки которые вернул запрос

     

    select * from regions for update;

     

    Директива FOR UPDATE приведёт к блокировке таблиц которые возвращает запрос. Другие сессии не смогут изменить данные и таким образом последующие изменения будут успешны: другие сессии не смогут изменить данные. То есть у одной сессии будет согласованное чтение данных, но ценой за это будет то, что другие сессии «зависнут» если они попытаются изменить данные которые заблокированы (другие сессии могут читать эти данные).

    Блокировка строк вызванная командой FOR UPDATE будет длиться пока сессия не выполнит команду COMMIT или ROLLBACK. Команду завершения транзакции необходимо выполнить даже если вы не запускали каких-либо DML команд.

     

    Так называемый «авто-коммит»

     

    Чтоб завершить обзор как обрабатывается управление транзакциями надо рассеять все сомнения о так называемом “auto-commit” или неявном подтверждении (implicit commit). Вы будете часто слышать что Oracle автоматически подтвердит. Первый случай это предыдущий случай когда вы выполнили команду DDL, другая ситуация когда пользователь вышел из программы такой как SQL *Plus.

    На самом деле всё очень просто. Не существует такого понятия как авто-коммит. Когда вы выполняете DDL команду, то работает обычный COMMIT которые встроен в команду DDL. Но что проиходит когда вы выходите из программы? Если вы используете SQL Plus в Windows и выполняете команду DML а затем команду EXIT (EXIT это команду SQL *Plus а не SQL), ваша транзакция будет подтверждена. Это потому что разработчики SQL *Plus встроили вызов команды COMMIT в команду EXIT. Если же вы нажмёте на красный крест в правом верхнем углу – то произойдёт вызов команды ROLLBACK. Так происходит потому что опять же разработчики SQL *Plus запрограммировали такое поведение программы. В другой операционной системе поведение программы SQL Plus может быть другим, единственный способ узнать это – это протестировать программу (или прочитать исходный код что в случае программы SQL Plus невозможно если вы не работаете в Oracle надо этой программой).

    В SQL *Plus есть команда SET AUTOCOMMIT ON. Вызов этой команды указывает SQL *Plus на то как обрабатывать пользовательские запросы: SQL *Plus добавит вызов команды COMMIT после любой DML команды. Таким образом все запросы будут подтверждаться как только они выполнены. Но опять же всё это происходит полностью на стороне пользовательского процесса; у базы данных нет никакого авто-коммита, и все долго-работающие изменения будут изолированы от других сессий пока запрос не выполнится успешно. Даже в таком случае если вы запустите долгий запрос на выполнение, потом к примеру завершите пользовательский процесс через диспетчер задач то PMON обнаружит сессию «призрак» и отменит транзакцию.

  • DML команды

    Данные в реляционных базах данных управляются с помощью DML (Data Manipulation Language) комманд. Эти команды это INSERT, UPDATE, DELETE и (в последних версиях SQL) MERGE. В этой главе обсуждается что происходит в памяти и на диске когда выполняются команды DML – момент когда новые данные записываются на в блоки сегмента таблицы или индекса и старые данные записываются в блоки сегментов отмены изменений. В основе этих команд лежит ACID тест, которые должна проходить любая реляционная БД. Управление транзакциями с помощью команд COMMIT и ROLLBACK которые ассоциируются с DML командами также будет рассмотрено в этой главе. А также в этой главе описывается параллельный доступ к данным и уровни блокировки.

     

    Строго говоря существует пять DML команд

    • SELECT
    • INSERT
    • UPDATE
    • DELETE
    • MERGE

    На практике профессионалы в области баз данных SELECT обычно не рассматривают как часть DML. Обычно SELECT рассматривается отдельно и это становится понятно когда вы увидите что следующие пять глав выделены для описания только команды SELECT. Команда MERGE тоже часто не рассматривается, не потому что это не чистая команды управления данными, а потому что результат выполнения этой команды можно достичь используя другие команды. MERGE можно рассматривать как ярлык для вызова команд INSERT и DELETE или UPDATE в зависмости от каких-либо условий. Команда часто рассматриваемая вместе с DML это команды TRUNCATE. На самом деле это DDL команда, но так как эффект для пользователей такой же как и от команды DELETE (несмотря на то что реализация абсолютно разная) то команда TRUNCATE удовлетворяет параметрам DML команд.

    Команда INSERT

    Oracle хранит данные в виде строк в таблицах. Таблица наполняется  строками (так же как страна наполнена людьми) несколькими способами, но самый частый используемый метод это команда INSERT. SQL — это язык ориантированные на работу с наборами данных, и таким образом одна комманда может вилять на одну строку либо на набор строк. Отсюда следует что команда INSERT может добавить одну строку в одну таблицу или много строк в много таблиц. Базовая версия запроса добавляет всего одну строку, но сложные запросы могут добавлять несколько строк в несколько таблиц.

     

    TIP

    There are much faster techniques than INSERT for populating a table with large numbers of rows. These are the SQL*Loader utility, which can upload data from files produced by an external feeder system, and Data Pump, which can transfer data in bulk from one Oracle database to another, either via disk files or through a network link.

     

    EXAM TIP

    An INSERT command can insert one row, with column values specified in the command, or a set of rows created by a SELECT statement.

     

    Простейшая форма команды INSERT добавляет одну строку в таблицу используя значения указанные в команде. Синтаксис такого запроса

     

    INSERT INTO table [(column [,column…])] VALUES (value [,value…]);

     

    Примеры

     

    insert into hr.regions values (10,’Great Britain’);

    insert into hr.regions (region_name, region_id) values (‘Australasia’,11);

    insert into hr.regions (region_id) values (12);

    insert into hr.regions values (13,null);

     

    Первая из команд указывает значения для обоих столбцов таблицы REGIONS. Если у таблицы есть третий столбец то запрос выполнится неуспешно так как команда использует позиционное обозначение (positional notation). В команде не указывается в какой столбец необходимо вставить конкретное значение, запрос рассматривает позицию значений, их порядок в команде. Когда БД получает запрос использущий позиционное обозначение она будет сопостовлять порядок значений со порядком определения столбцов при создании. Запрос выполнится неуспешно если порядок будет неверный: БД попробует вставить данные, но типы данных столбцов разные.

    Второй запрос указывает и столбцы и значения которые использовать для столбцов. Обратите внимание что теперь порядок определения столбцов в таблице не важен – важен порядок столбцов и значений в запросе.

    Третий пример указывает один столбец и одно значение. Для всех остальных столцов будет использоваться значение NULL. Запрос выполнится неуспешно если столбец REGION_NAME обязательный (not null). Четвертый пример приведёт к такому же результату как и третий, но так как не были указаны столбцы в запросе – необходимо указать значения (даже NULL) явно для всех столбцов.

     

    TIP

    It is often considered good practice not to rely on positional notation and instead always to list the columns. This is more work but makes the code self-documenting (always a good idea!) and also makes the code more resilient against table structure changes. For instance, if a column is added to a table, all the INSERT statements that rely on positional notation will fail until they are rewritten to include a NULL for the new column. INSERT code that names the columns will continue to run.

     

    Для вставки нескольких строк одним запросом значения для строк должны возвращаться запросом. Синтаксис такой команды

     

    INSERT INTO table [column [, column…] ] subquery;INSERT INTO table [column [, column…] ] subquery;

     

    Обратите внимание что такой синтаксис не использует ключевое слово VALUES. Если список столбцов пропущен то подзапрос должен возвращаться значения для каждого столбца таблицы. Для копирование всех строк из одной таблицы в другую если у таблиц одинаковые столбцы то команда для такой операции будет вида

     

    insert into regions_copy select * from regions;

     

    Такой запрос предполагает что таблица regions_copy уже существует. Подзапрос SELECT считывает все строки из таблицы-источника (REGIONS) и команда INSERT записывает все строки в таблицу-цель (REGIONS_COPY)

    EXAM TIP

    Any SELECT statement, specified as a subquery, can be used as the source of rows passed to an INSERT. This enables insertion of many rows. Alternatively, using the VALUES clause will insert one row. The values can be literals or prompted for as substitution variables.

     

    В завершение рассмотрения команды INSERT необходимо упомянуть что возможно вставить строки в несколько таблиц одним запросом. Такие запросы не входят в базовый курс но для полноты картины рассмотрим пример

     

    insert all

    when 1=1 then

    into emp_no_name (department_id,job_id,salary,commission_pct,hire_date)

    values (department_id,job_id,salary,commission_pct,hire_date)

    when department_id <> 80 then

    into emp_non_sales (employee_id,department_id,salary,hire_date)

    values (employee_id,department_id,salary,hire_date)

    when department_id = 80 then

    into emp_sales (employee_id,salary,commission_pct,hire_date)

    values (employee_id,salary,commission_pct,hire_date)

    select employee_id,department_id,job_id,salary,commission_pct,hire_date

    from employees where hire_date > sysdate — 30;

     

    Чтобы понять этот запрос, начинаем читать с конца. Подзапрос считывает строки из таблица EMPLOYEES где дата приёма на работу не раньше чем 30 дней назад (сотрудники нанятые за последние 30 дней). Затем возвращаемся наверх. Ключевое слово ALL обозначает что каждая строка из подзапроса рассматривается для доавления во все таблицы, не только в первую где выполняется условие. Первое условие 1=1, которое всегда возвращает значение TRUE, т.е. все строки запишутся в таблицу emp_no_name. Это копия таблицы EMPLOYOEES в которой нет столбцов для персональных данных. Затем рассматривается условие DEPARTMENT_ID<>80, т.е. создадутся строки в таблице EMP_NON_SALES для каждой строки из подзапроса где DEPARTAMENT_ID<>80; для этой таблицы нет столбца COMMISION_PCT. И третье условие создаст строки в таблице EMP_SALES для всех сотрудников у которых DEPARTAMENT_ID=80; в этой таблице не нужен столбец DEPARTMENT_ID так как у всех записей этой таблицы предполагается одно значение DEPARTAMENT_ID.

    Это простой пример мультитабличной вставки, но главное понимать что с помощью такого запроса будет выполнен только один подзапрос и будет только один цикл прохода по строкам, но можно вставить данные  во многие таблицы-цели. Таким образом можно существенно снижать нагрузку с БД.

    Команда UPDATE

    Команда UPDATE используется для изменения строк которые уже существуют – строки которые были созданы с помощью команды INSERT или возможно другими инструментами такими как Data Pump. Как и другие SQL команды, команда UPDATE может влиять на одну строку или набор строк. Размер набора данных обновляемым командой UPDATE определяется условием WHERE, точно таким же образом как и набор строк получаемый командой SELECT. Синтаксис идентичныйю Все обновляемые строки будут находиться в одной таблице; невозможно одной командой UPDATE обновлить данные в нескольких таблицах.

    Когда обновляются данные команда UPDATE указывает какие столбцы набора строк обновлять. Необязательно обновлять все столбцы строки. Если обновляемые столбец уже хранит значение, оно будет заменено на новое указанное в команде UPDATE. Если в столбец не было значения – т.е. было значение NULL – то столбец будет обновлен на новое значение.

    Обычное использование UPDATE это получение одной строки и обновление одного или нескольких столбцов в этой строке. Строка получается используя условие WHERE по первичному ключу, уникальному идентификатору которые гарантирует что только одна строка будет получена. Затем обновляются столбцы которые не являются столбцами первичного ключа. Обычно значение первичного ключа не изменяется. Жизненный цикл строки начинается когда она добавляется, затем может происходить несколько изменений до тех пор пока строка не удаляется и жизненный цикл не заканчивается. Во время жизни строки обычно первичный ключ не изменяется.

    Для обновления набора строк используется менее строгое условие WHERE. Для обновления всех строк в таблице просто не указывается условие. Такое поведение команды немного смущает когда команда без условия WHERE выполняется по ошибке. Если вы выбираете строки не по строгому равенству значения первичного ключа то вы можете обновить несколько строк а не одну. Если же вы полностью убираете условие WHERE то будет обновлена вся таблица – возможно миллионы строк всего лишь выполнением одного запроса – когда вы хотели обновить всего одну строку.

     

    EXAM TIP

    One UPDATE statement can change rows in only one table, but it can change any number of rows in that table.

     

    Команда UPDATE должна соблюдать все ограничения наложенные на таблицу, так же как и команда INSERT. Например невозможно обновить значение столбца с ограничением обязательности (not null) на значение NULL или обновить первичный ключ на неуникальное значение. Базовый синтаксис команды UPDATE

     

    UPDATE table SET column=value [,column=value…] [WHERE condition];

     

    Более сложная форма команды может использовать подразпросы для значений столбцов и для условия WHERE. На рисунке 8-1 показаны различные запросы выполненные в SQL *Plus.

    88

    Первый пример самый простой. Значение одного столбца одной строки устанавливается в значение-литерал. Так как в условии WHERE используется значение первичного ключа, то это гарантирует что обновится максимум одна строка. Если не будут найдены строка удовлетворяющая этому значению ключа то не обновится ни одна строка.

    Второй пример показывает использование арифметической операции и существующего столбца для калькуляции нового значения и выборка строк для обновления происходит не по первичному ключу. Если выборка осуществляется ен по значению первичного ключа, или используются не предикаты равенства (такие как BETWEEN) то количество строк которые будут обновлены может быть больше чем один. Если условие WHERE полность пропущно – то обновление применится ко всем строкам таблицы.

    Третий пример на рисунке 8-1 использует подзапрос для определения набора данных для обновления и запрос на ввода значения переменных используемых в подзапросе. В данном примере подзапрос (строки 3 и 4) вернёт всех сотрудников название департамента которых содержит подстроку IT и увеличит их зарплату на 10% (к сожалению такое редко случается в реальном мире).

    Также возможно использовать подзапрос для определения значения используемого для обновления столбца, как показано в четвертом примере. В нашем примере один сотрудник (условие равенства первичного ключа в строке 5) переводится в департамент с идентификатором 80, и затем подзапрос (строки 3-4) устанавливает процент комиссии на минимальное значение для этого отдела.

    Синтаксис для команды UPDATE использующей подзапросы

     

    UPDATE table

    SET column=[subquery] [,column=subquery…]

    WHERE column = (subquery) [AND column=subquery…] ;

     

    Существует жёсткое ограничение на результат возвращаемый подзапросом для определения значения: подзапрос должен возвращать скалярное значение. Скалярное значение это одно значение (одна строка, один столбец) необходимого типа данных. Если подзапрос вернёт не скалярное значение запрос не выполнится. Рассмотрим два примера

     

    update employees

    set salary=(select salary from employees where employee_id=206);

    update employees

    set salary=(select salary from employees where last_name=’Abel’);

     

    Первые пример использует предикат равенства по первичному ключу и запрос всегда выполнится успешно. Даже если запрос не вернёт ни одну строку (если нет сотрудника с номером 206) запрос вернёт скалярное значение: NULL. В этом случае у всех сотрудников зарплата станет NULL – что может быть не совсем верно с точки зрения качества данных, но с точки зрения SQL здесь нет ошибки. Второй запрос использует предикат равенства для поля LAST_NAME, что не гарантирует уникальность. Запрос выполнится успешно если существует только один сотрудник с таким именем, но если в таблице больше чем одна строка с таким значение запрос вернёт ошибку “ORA-01427: single-row subquery returns more than one row.” Для надёжного кода неважно состоянии данных, важно убедиться что подзапросы всегда возвращают скалярное значение.

     

    TIP

    A common fix for making sure that queries are scalar is to use MAX or MIN. This version of the statement will always succeed:

    update employees set salary=(select max(salary) from employees where last_name=’Abel’);

    However, just because it will work, doesn’t necessarily mean that it does what is wanted.

     

    Подзапросы в условии WHERE тоже должны возвращать скалярное значение если используется предикат равенства или предикат отношения > или <. Если используется предикат вхождения (IN) то подзапрос может возвращать набор строк. К примерму

     

    update employees

    set salary=10000

    where department_id in (select department_id from departments where department_name like ‘%IT%’);

     

    Результатом этого запроса будет обновление значения зарплаты всем сотрудникам название отдела которых содержит подстроку IT. Но несмотря на то что подзапрос может возвращать в таких случаях несколько строк – он всё равно должен возвращать один столбец.

     

    EXAM TIP

    The subqueries used to SET column values must be scalar subqueries. The subqueries used to select the rows must also be scalar, unless they use the IN predicate.

    Команда DELETE

    Ранее добавленные строки можно удалить из таблицы используя команду DELETE. Эта команда удалит одну или несколько строк из таблицы в зависимости от условия в секции WHERE. Если условие WHERE пропущено то все строки будут удалены из таблицы.

     

    TIP

    There are no “warning” prompts for any SQL commands. If you instruct the database to delete a million rows, it will do so. Immediately. There is none of that “Are you sure?” business that some environments offer.

     

    Удаление столбцов происходит по принципу либо всё либо ничего. Нельзя указать столбец в команде DELETE. Когда строка добавляется в таблицу вы можете указать столбцы для заполнения. Когда строка обновляется вы можете выбрать столбцы для обновления. Но удаление происходит для всей строки – единственным выбором является какие строки удалять. Это делает команду DELETE легче чем другие команды с точки зрения синтаксиса. Синтаксис команды DELETE

     

    DELETE FROM table [WHERE condition];

     

    Это простейшая команда DML, особенно если условие WHERE будет пропущено. В этом случае все строки будут удалены. Единственным усложнением команды может быть добавление условия. К примеру условия равенства/подобия литералу

     

    delete from employees where employee_id=206;

    delete from employees where last_name like ‘S%’;

    delete from employees where department_id=&Which_department;

    delete from employees where department_id is null;

     

    Первый запрос идентифицирует строку по первичному ключу. Одна строка будет удалена – или одна или ни одной, если заданное значение ключа не найдено в таблице. Второй запрос использует предикат подобия что может привести к удалению многих строк: будут удалены все сотрудники фамилия которых начинается с буквы S. Третий запрос запросит вводи значения для переменной в запросе и все сотрудники департамента будут удалены. Последний запрос удалит всех сотрудников у которых не назначен департамент (значение департамента NULL).

     

    Условием может быть также подзапрос

     

    delete from employees where department_id in

    (select department_id from departments where location_id in

    (select location_id from locations where country_id in

    (select country_id from countries where region_id in

    (select region_id from regions where region_name=’Europe’)

    )

    )

    )

     

    Этот пример испоьлзует подзапрос для выбора строк который использует географическое дерево (другие подзапросы) для удаления всех сотрудников департаменты которых базируются в Европе. Ограничение на количество строк возвращаемых подзапросом такое же как и для команды UPDATE: если условие базируется на предикате равенства, результат подзапроса должен быть скарялным значением, если используется IN то запрос может возвращать несколько строк.

    Если команда DELETE не удаляет ни одной строки – это не рассматривается как ошибка. Команда вернёт сообщение “0 rows deleted’ вместо сообщения об ошибки посколько команды выполнена успешна – просто не были найдены строки для удаления.

    Для удаления все строк из таблицы существует два варианта: использовать команду DELETE или команду TRUNCATE. DELETE менее кардинальная посколько удаление можно отменить когда очистку (TRUNCATE) нельзя. Также команда DELETE более управляемая так как можно использовать условие WHERE а команда TRUNCATE всегда удаляет все строки из таблицы. Но команда DELETE выполняется гораздо более медленно и загружает БД. Команда TRUNCATE выполняется практически мгновенно и без нагрузки на БД.

    Команда TRUNCATE

    Команда TRUNCATE это не команда DML – это команда DDL. Разница огромная. Когда DML команды работают с данными, они добавляют, изменяют или удаляют данные как часть транзакции. Рассмотрим транзакции чуть позже, пока же скажем что транзакции можно котролировать в том смысле, что изменения можно подветрждать и отменять. Это очень полезное свойство работы с данными, но его реализация заставляет БД делать много дополнительной работы которая не видна пользователю. DDL команды не управляются пользовательскими транзакциями (несмотря на то что в БД они выполняются как транзакции – но разработчик не может управлять ими), и у вас нет выбора подтвердить изменения или отменить их. Когда команда выполнена – изменения вступили в силу. Но по сравнению с DML командами – DDL команды очень быстрые.

     

    EXAM TIP

    Transactions, consisting of INSERT, UPDATE, and DELETE (or even MERGE) commands, can be made permanent (with a COMMIT) or reversed (with a ROLLBACK). A TRUNCATE command, like any other DDL command, is immediately permanent: it can never be reversed.

     

    С точки зрения пользователя, TRUNCATE таблицы тоже самое что и DELETE всех строк. Но удаление может занять какое-то время (возможно несколько часов если достаточно много строк в таблице), а TRUNCATE отработает мгновенно вне зависимости от количества строк в таблице.

     

    TIP

    DDL commands, such as TRUNCATE, will fail if there is any DML command active on the table. A transaction will block the DDL command until the DML command is terminated with a COMMIT or a ROLLBACK.

     

    EXAM TIP

    TRUNCATE completely empties the table. There is no concept of row selection, as there is with a DELETE.

     

    Одной из частей определения таблицы, которое хранится в словаре данных, является физическое местоположение. Когда таблица создаётся, выделяется место, фиксированного размера в файлах данных БД. Это место известное нам как экстент, выделяется и свободно для записи. Затем, когда строки добавляются в таблицу, экстент заполняется. Когда первый экстент заполнен, другие экстенты будут выделяться для таблицы автоматически. Таким образом таблица состоит из одного или нескольких экстентов в которых хранятся строки. Словарь данных отслеживает как выделенные экстенты так и как много выделенного для таблицы пространства использовано. Вводится понятие верхней границы (high water mark). Верхняя граница это последняя позиция в последнем экстенте которая когда либо использовалась для хранения данных. Все пространство до верхней границы когда либо использовалось для хранения данных, а всё пространство после никогда не использовалось для хранения данных. Обратите внимание что вполне возможно что будет много свободного места до верхней границы в текущий момент; это возможно из-за удаления строк командой DELETE. Добавление строк в таблицу поднимает верхную границу. Удаление строк оставляет верхнюю границу на той же позиции – но пространство используемое удаляемыми строками становится доступным для записи новых строк.

    Команда TRUNCATE обнуляет верхнюю границу. В словаре данных позиция верхней границы смещается на начало первого экстента. Так как Oracle считает что строки после верхней границы не могут существовать то эффект от этого равнозначен удалению всех строк из таблицы. Таблица очищается и остается пустой пока последующие добавления строк не обновят значение верхней границы. Таким способом одна DDL команда которая фактически делает простое обновление в словаре данных может уничтожить миллионы строк в таблице.

    Синтаксис команды TRUNCATE

     

    TRUNCATE TABLE table;

     

    На рисунке 8-2 показано как выбрать команду TRUNCATE в SQL Developer, но также эту команду можно выполнить и из SQL* Plus и из другого инструмента.

    89

    Команда MERGE

    Часто возникает ситуация когда вам необходимо взять набор данных (источник) и интегрировать его в существующую таблицу (цель). Если строка источника уже существует в таблице-цели, вы можете хотеть обновить строку в таблице-цели, или удалить старую строку и вставить новую или вы хотите вообще не трогать такие строки. Если строка источника не существует в таблице-цели, вы хотите добавить такую строку. Команда MERGE позволяет сделать это. MERGE работает с наборами данных, для каждой строки источника пытается найти уже существующую строку в таблице-цели. Если совпадение не найдено – строка будет добавлена; если строка найдена то она может быть обновлена. Начиная с версии 10g найденная строка в таблице-цели может быть даже удалена после нахождения совпадения и обновления.

    Команда MERGE не делает ничего такого что было бы невозможно сделать командами DELETE, INSERT и UPDATE – но только она может сделать это за один проход данных. Альтернативой команде MERGE будет три прохода данных, по одному для каждой команды.

    Источником для команды MERGE может быть таблица или запрос. Условие для нахождения совпадения аналогично условию WHERE. Секция которая отвечает за обновление или добавление данных аналогично соответствующей команде INSERT или UPDATE. Получается что команда MERGE самая сложная из DML команд (сложно не согласиться) и самая мощная (что можно оспорить). Использование команды MERGE не входит в данный курс но для полноты картины рассмотрим простой пример

     

    merge into employees e

    using new_employees n on (e.employee_id = n.employee_id)

    when matched then

    update set e.salary=n.salary

    when not matched then

    insert (employee_id,last_name,salary)

    values (n.employee_id,n.last_name,n.salary);

     

    Данный запрос использует таблицу NEW_EMPLOYEES для обновления или добавления данных в таблицу EMPLOYEES. Команда пройдёт по данным таблицы NEW_EMPLOYEES и для каждой строки этой таблицы попробует найти строку в таблице EMPLOYEES сооветствующую заданному условию. Если строка найдена значение поля SALARY будет обновлено на новое значение из таблицы NEW_EMPLOYEES. Если строка не найдена одна новая строка будет добавлена.

     

    Неуспешное выполнение DML команд

     

    Запрос может выполниться неуспешно по многим причинам, включая следующие

    Ошибка в синтаксисе

    Ссылка на несуществующий объект или столбец

    Недостаток прав

    Нарушение ограничений

    Проблемы с доступным местом

     

    На рисунке 8-3 отображены несколько попыток выполнения запросов в SQL *Plus. Пользователь подключается к аккаунту SUE используя пароль sue (хороший пример плохой безопасности БД) и выполняет запросы к таблице employees. Первый запрос выполняется с ошибкой из-за обычной опечатки корректно указанной SQL *Plus. Обратите внимание что SQL *Plus никогда не будет исправлять ошибки такого плана, даже если достоверно известно что именно вы хотели написать. Возможно другие инструменты могут автоматически изменять ошибки.

    90

    Второй запрос был выполнен неуспешно с ошибкой о том что объект не существует. Это произошло потому что таблица находится не в схеме SUE, а в схеме HR. Исправив это третий запрос был выполнен успешно – но только он. Значение переданное в условии WHERE это строка ’21-APR-00’, но поле HIREDATE определено как дата, а не строка. Для выполнения запроса БД попробовала преобразовать строку в дату. В последнем запросе такое преобразование не смогло отработать, так как строка-параметр была европейского формата данных, а база настроена на американский формат: преобразовать 21 в месяц не получилось. Запрос был бы выполнен успешно если бы строка была ‘04/21/2000’.

    Даже если команда синтаксически верна и объекты используемые в запросе существуют, запрос все равно может быть выполнен неуспешно из-за нехватки прав. Если пользователь попробует выполнить запрос к объектам на которые у него нет соотвествующих прав, то БД вернёт ошибку аналогичной той, которая быда бы возвращена если бы объект не существовал. Для пользователя у которого нет прав к объекту – объект не существует.

    Ошибки вызванные нехваткой прав являются случаем когда команды SELECT и DML могут возвращать разные результаты: для пользователя возможно установить права просмотра данных, но не изменения (добавления, удаления). Такое распределение достаточно часто распространено. А иногда бывают случаи когда у пользователя есть права добавления строк, которые он не может просматривать, и что хуже всего даже удалять строки которые он не может ни видеть ни изменять.

    Нарушение ограничений также может привести к выполнению DML команды с ошибкой. Например команда INSERT может добавлять несколько строк в таблицу и для каждой строки БД будет проверять существует ли уже такое значение первичного ключа. Это проверяется для каждой строки. И может быть что первые несколько строк (или первые несколько миллионов строк) уже добавлены без проблем, а затем команда доходит до строки со значением-дубликатом. В этот момент будет возвращена ошибка и запрос будет выполнен неуспешно. Ошибка запустит отмену добавления всех уже добавленных строк. Такое поведение стандартно для всех команд SQL: либо запрос выполнен успешно целиком, либо не выполнен. Отмена выполненных изменение это rollback.

    Если запрос выполнен неуспешно из-за проблем со свободным место – результат такой же. Часть запроса может быть выполнена успешно до того как БД стало не хватать места и эта часть будет автоматически отменена в момент возникновения ошибки. Отмена частично выполненного запроса нагружает БД. Отмена запроса принуждает БД сделать много работы и обычно занимает не меньше времени чем само выполнение запроса до ошибки (а иногда и дольше).

  • DDL и объекты схемы — Итоги

    Объекты БД

    • Некоторые объекты содержат данные, главные это таблицы и индексы.
    • Программные объекты такие как хранимые процедуры и функции это исполняемый код
    • Представления и синонимы это объекты которые предоставляют доступ к другим объектам
    • Талблица это двумерная структура данных, хранящая строки с определёнными столбцами
    • Таблица существует в схеме. Имя схема с именем таблицы организуют уникальный идентификатор

     

    Типы данных

    • Самые часто используемые типы данных это VARCHAR2, NUMBER и DATE
    • Существует много других типов данных

     

    Создание простой таблицы

    • Таблицы могут создаваться из ничего или используя подзапрос
    • После создания столбцы могут добавляться, изменяться и удаляться
    • Определение столбца может включать значение по умолчанию

     

    Создание и использование временных таблиц

    • Строки во временной таблице доступны только для сессии которая их добавила
    • DML надо временными таблицами не генерируют данных для отмены изменений
    • Временные таблицы существуют только в PGA сессии или во временных сегментах
    • Временная таблица может хранить данные всё время жизни сессии или только время действия транзакции, в зависимости от того как она была создана

     

    Ограничения

    • Ограничения могут определяться в момент создания таблицы и добавляться позже
    • Ограничения могут определяться в строке определения столбца или после определения столбцов
    • Ограничения табличного-уровня могут быть более гибко настраиваемы чем ограничения создаваемые в строке определения столбца
    • Таблица может иметь только один первичный ключ но много ограничений уникальности
    • Превичные ключ функционально равен ограничению уникальности вместе с ограничением обязательности
    • Ограничение уникальности не предотвращает от возможности вставки нескольки строк со значением NULL
    • Внешний ключ определяет отношения между таблицами

     

    Индексы

    • Индексы необходимы для работы ограничений уникальности и первичных ключей
    • Значени NULL не влючается в B* Tree индекс, но включается в bitmap индекс
    • B* Tree индексы подходят для столбцов с высокой мощностьб, битмап индексы – для столбцов с маленькой мощностью
    • B* Tree индекс может быть уникальным или неуникальным, что определяет возможность хранить дубликаты в значении ключа
    • Bitmap индексы могут быть составными, основанными на функции, и сортированными; B* Tree индексы в добавок к этим свойствам так же ещё могут быть уникальными, сжатыми и обратными

     

    Представления

    • Простые представления используют одну (базовую или детальную) таблицу и не используют ни функции ни аггрегацию
    • Сложные представления основаны на команде SELECT вне зависимости от сложности запроса
    • Представления это объекты схемы. Для использования представления из другой схемы, имя представления должно предваряться именем схемы
    • К представлениям можно писать запросы как будто это таблицы
    • Предстваления можно объединять с другими представлениями или таблицами, их можно аггрегивароть и в некоторых случаях использовать для DML команд
    • Представления существуют только как конструкции в словаре данных. Когда вы выполняете запрос к представлению запрос-основа всегда выполняется

     

    Синонимы

    • Синонимы это псевдоним для представления или таблицы
    • Частные синонимы это объекты схемы; общие синонимы существуют вне пользовательской схемы и могут использоваться без указания схемы в уникальном идентификаторе
    • Синонимы используют тоже пространство имен что и представления и таблицы

     

    Сиквенсы

    • Сиквенсы генерируют уникльные значения – до тех пор пока MAXVALUE или MINVALUE и CYCLE не указаны
    • Увеличение значения сиквенса не может подтверждаться или отменяться
    • Любая сессия может увеличить значение сиквенса путём запроса следующего значения. Также возможно получить текущее (последнее использованное) значение для текущей сессии но не последнее сгенерированное значение.