Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
BBD_Shpory.doc
Скачиваний:
11
Добавлен:
26.09.2019
Размер:
13.1 Mб
Скачать

34. Построение запросов для ввода, удаления и изменения значений полей. Вставка результата запроса в таблицу.

Ввод, удаление и изменение значений полей

Эти команды образуют подраздел SQL, называемый DML (Data Manipulation Language):

INSERT (вставить), UPDATE (обновить), DELETE (удалить).

Еще их называют update command- команды обновления.

Ввод значений:

INSERT INTO <имя таблицы>

VALUES (<значение 1 поля>, <значение 2 поля>, …)

INSERT INTO Sales people

VALUES (1001, ‘Hoffman’, ‘London’, .12);

Если бы требовалось ввести данные только в указанные столбцы в таблице, то нужно было бы написать:

I NSERT INTO Sales people (snum, sname, city, comm)

В остальные- значения по умолчанию (NULL и т.п.)

Вставка результатов запроса

I

Комиссионные

NSERT INTO London staff

SELECT *

FROM Sales people

WHERE city = ‘London’;

Перед выполнением этого Statement’а таблица London staff должна быть создана (с помощью команды CREATE TABLE).

Таблица должна соответствовать результатам запроса.

Исключение (удаление) строк из таблицы

Если написать DELETE FROM Sales people, то таблица окажется пустой (совсем ее удалить можно командой DROP TABLE).

Обычно нужно удалить лишь некоторые записи с использованием предиката:

DELETE FROM Sales people

WHERE snum = 1003; или

… WHERE city = ‘London’;

Обновление

Пример:

UPDATE Customers

SET rating = 200; (имя и новое значение обновляемого поля)

Обычно также включается условие:

Например:

WHERE city = ‘London’;

SET- это команда, а не предикат.

35. Создание, изменение и удаление таблиц. Понятие представления (View).

Создание таблицы CREATE TABLE <имя таблицы>

(<имя столбца><тип данных>[(<размер>)],

<имя столбца><тип данных>[(<размер>)], …);

Создание индекса CREATE INDEX <имя индекса> ON

<имя таблицы> (<имя столбца> [,<имя столбца>]…];

Удаление индекса DROP INDEX <имя индекса>

Изменение таблицы ALTER TABLE <имя таблицы>

ADD <имя столбца>

(не стандартная, но <тип данных><размер>;

широко применяема)

Исключение таблицы DROP TABLE <имя таблицы>

Расширенный синтаксис:

CREATE TABLE <имя таблицы> (<имя столбца><тип данных><ограничение на столбец>, <имя столбца><тип данных><ограничение на столбец>…<ограничение на таблицу>[<имя столбца>[,<имя столбца>…])…);

Пример ограничений: NOT NULL,

NOT NULL UNIQUE, NOT NULL PRIMARY KEY, CHECK (условие)

Пример ограничения на таблицу:

UNIQUE (snum, odate)

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

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

Представления сравнивают с окном, через которое просматриваются данные в реальных (базовых) таблицах. Можно сравнить с кадрированием 1 фотографии.

П ример:

CREATE VIEW Londonstaff

A S SELECT *

FROM Salespeople

WHERE city = ‘London’;

Затем можно ссылаться как на таблицу

SELECT *

FROM Londonstaff;

Представление обновляется автоматически при изменении базовых таблиц.

Обновление представлений

Допустим, мы имеем представление:

CREATE VIEW Salesown

AS SELECT snum, sname, city

FROM Salespeople;

По сути, оно просто ограничивает доступ к таблице Salespeople тремя полями.

Это представление можно модифицировать командами обновления DML. Следует понимать, что при этом модификации воздействуют только на лежащую в его основе таблицу:

UPDATE Salesown

SET city = ‘Palo Alto’

WHERE snum = 1004;

Групповые представления

Это представления, которые в своем запросе содержат GROUP BY.

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

Вместо сложного запроса можно сначала сконструировать представление:

CREATE VIEW Total for day

AS SELECT odate, COUNT (DISTINCT cnum),

COUNT (DISTINCT cnum), COUNT (onum), AVG (amt),

SUM (amt)

FROM Orders

GROUP BY odate;

Теперь можно получить необходимую информацию с помощью простейших запросов:

SELECT * (здесь просто указывать что конкретно)

FROM Total for day;

То есть идея здесь подобна идее подпрограммы в языке программирования.

Представления и соединения (не путать с объединениями UNION).

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

CREATE VIEW Nameorders

AS SELECT onum, amt, a.snum, sname, cname

FROM Orders a, Customers b, Sales people c

WHERE a.cnum = b.cnum

AND a.snum = c.snum;

Теперь можно выбрать все заказы покупателя или продавца, например (для продавца):

SELECT *

FROM Nameorders

WHERE sname = ‘Ivanov’;

В соединении могут участвовать комбинации представлений и таблиц. Например, чтобы увидеть заказы ‘Petrov’а и его комиссионные: выражение

SELECT a.sname, cname, amt*comm

FROM Nameorders a, Sales people b

WHERE a.sname = ‘Petrov’

AND b.snum = a.snum;

Представления и подзапросы

Представления также могут использовать подзапросы, включая связанные подзапросы. Рассмотрим сложный пример: допустим, что компания платит премию продавцу, который имеет покупателя с наибольшим количеством заказов на заданную дату.

CREATE VIEW EliteS

AS SELECT b.odate, a.snum, a.sname

FROM Salespeople a, Orders b

WHERE a.snum = b.snum

AND b.amt = (SELECT MAX (amt)

FROM Orders c

WHERE c.odate = b.odate);

Теперь предположим, что вознаграждение должен получить тот продавец, который имел наибольшее количество заказов, по крайней мере, 10 раз, то информацию можно получить, основываясь на первом представлении:

CREATE VIEW Bonus

AS SELECT DISTINCT snum, sname

FROM EliteS a считает число строк

W HERE 10< = (SELECT COUNT (*)

FROM EliteS b

WHERE a.snum = b.snum);

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

SELECT *

FROM Bonus;

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

Ограничения представлений

Есть несколько аспектов области запросов, не укладывающихся в рамки определения представления: единственное представление должно базироваться на единственном запросе: UNION и UNION ALL недопустимы.

Нельзя использовать ORDER BY, поскольку выходные данные для запроса, формирующего представления, должны быть неупорядоченными по определению

Удаление представлений

Синтаксис сходен с удалением таблиц:

DROP VIEW <имя представления>

Изменение значений с помощью представлений

Речь идет о применении группы команд DML:

INSERT, UPDATE, DELETE.

Использование команд DML в представлениях является опосредованным способом применения их для таблиц, на которых базируется запрос представления.

Пример:

CREATE VIEW Citymatgh (custcity, salescity) ???????????????????????

AS SELECT DISTINCT a.city, b.city

FROM Customer a, Sales people b

WHERE a.snum = b.snum;

На выходе может быть строка London London - возникает вопрос, к какой паре продавцов в исходной таблицах отнести удаление такой строки?

Это пример представления только для чтения - в него нельзя вносить изменения.

36-37. Определение транзакции. Операторы SQL для обработки транзакций. Свойства транзакции и уровни изолированности. Особенности выполнения транзакций в распределённых БД. Двухфазовая фиксация.

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

Никакая СУБД не обладает внутренней возможностью установить, какие именно изменения должны быть восприняты как единое целое, образующее одну логическую транзакцию. Следовательно, должен существовать метод, позволяющий указывать границы каждой транзакции извне, со стороны пользователя. В большинстве языков манипулирования данными для указания границ отдельных транзакций используются операторы BEGIN TRANSACTION, COMMIT и ROLLBACK.

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

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

Существуют некоторые свойства, которыми должна обладать любая транзакция.

Атомарность – это свойство типа «все или ничего». Любая транзакция представляет собой неделимую единицу работы, которая может быть либо выполнена вся целиком, либо не выполнена вовсе.

Согласованность. Каждая транзакция должна переводить базу данных из одного согласованного состояния в другое согласованное состояние.

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

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

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

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

Первый уровень - отсутствие потерянных изменений. Например, транзакция 1 изменяет объект базы данных A (увеличивает значение поля равного 50 на 100). До завершения транзакции 1 транзакция 2 также изменяет объект A (уменьшает значение того же поля равного 50 на 10). После выполнения обеих транзакций значение поля должно быть равно 140. Транзакции начинаются практически одновременно и каждая из них считывает значение 50. Затем транзакция 1 увеличивает значение на 100 и записывает результат равный значению 150. Далее транзакция 2 уменьшает свою копию значения 50 на 10 и записывает результат, перекрывая результат предыдущего обновления. В результате значение поля становится равно 40 вместо 140. Чтобы избежать такой ситуации необходимо запретить чтение исходного значения до завершения транзакции 1. Отсутствие потерянных изменений является минимальным требованием к СУБД по части синхронизации параллельно выполняемых транзакций.

Второй уровень - отсутствие чтения "грязных данных". Например, транзакция 1 изменяет объект базы данных A. Параллельно с этим транзакция 2 читает объект A. Поскольку операция изменения еще не завершена, транзакция 2 видит несогласованные "грязные" данные, существующие до выполнения транзакции 1. В результате внесение изменений транзакцией 2, после завершения транзакции 1 может быть отвернуто из-за нарушения немедленно проверяемых ограничений целостности. Чтобы избежать ситуации чтения "грязных" данных, до завершения транзакции 1, изменяющей объект A, никакая другая транзакция не должна читать объект A.

Третий уровень - отсутствие неповторяющихся чтений. Рассмотрим следующий пример. Транзакция 1 читает объект базы данных A. До завершения транзакции 1 транзакция 2 изменяет объект A и успешно завершается оператором COMMIT. Транзакция 1 повторно читает объект A и видит его измененное состояние. Чтобы избежать неповторяющихся чтений, до завершения транзакции 1 никакая другая транзакция не должна изменять объект A. В большинстве систем это является максимальным требованием к синхронизации транзакций.

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

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

Механизм блокировок разрешает проблемы, связанные с доступом нескольких пользователей (программ) к одним и тем же данным. Однако его применение связано с существенным замедлением обработки транзакций, вызванным необходимостью ожидания, когда освободятся данные, захваченные конкурирующей транзакцией. Можно попытаться минимизировать вызванный этим ущерб, локализуя фрагменты данных, захватываемые транзакцией. Так, СУБД может блокировать всю базу данных целиком (очевидно, что это неприемлемый вариант), таблицу базы данных, часть таблицы, отдельную строку. Современные СУБД используют в большинстве блокировки на уровне частей таблиц (страниц) и/или на уровне записей.

При блокировке на уровне страниц СУБД захватывает для выполнения транзакции некоторый фрагмент таблицы, запрещая доступ к нему (на время выполнения транзакции) конкурирующим транзакциям. Последние, могут захватить другие страницы той же таблицы. Так как размер страниц обычно невелик (2-4 Кб), то время ожидания транзакций, конкурирующих за доступ к страницам таблицы, оказывается приемлемым даже для режима оперативного доступа к базе данных.

Если СУБД реализована таким образом, что может захватывать для выполнения транзакции отдельные строки таблицы, то скорость обработки транзакции существенно повышается. Блокировка на уровне записей (строк) позволяет добиться максимальной производительности за счет того, что захватываемый объект (запись) является минимальной структурной единицей базы данных.

Транзакции могут попасть в тупиковую ситуацию - состояние неразрешимой взаимоблокировки. Оно иллюстрируется простейшей ситуацией. Транзакция A обновляет таблицу Заказ, блокируя некоторую ее страницу (для определенности - страницу C). В то же время транзакция B обновляет таблицу Товар, блокируя страницу D таблицы. Далее, транзакция A пытается обновить данные на странице D таблицы Товар (но, поскольку транзакция B еще не завершена, транзакция A переводится в состояние ожидания того момента, когда транзакция B освободит захваченную ею страницу). В этот же момент транзакция B пытается обновить данные на странице C таблицы Заказ. Сделать этого она не может, потому что страница захвачена транзакцией A и не освобождена, так как последняя находится в состоянии ожидания. Транзакция B также переводится в состояния ожидания. Налицо ситуация взаимоблокировки транзакций, которая может продолжаться бесконечно, если СУБД не предпримет специальные меры.

Для их предотвращения СУБД периодически проверяет блокировки, установленные активными транзакциями. Если СУБД обнаруживает взаимоблокировки, она выбирает одну из транзакций, вызвавшую ситуацию взаимоблокировки, и прерывает ее. Это освобождает данные для внесения изменений конкурирующей транзакцией, разрешая тупиковую ситуацию. Программа, которая инициировала прерванную транзакцию, получает сообщение об ошибке.

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

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

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

Для этого в современных СУБД предусмотрен так называемый протокол двухфазовой (или двухфазной) фиксации транзакций. Название отражает тот факт, что фиксация распределенной транзакции выполняется в две фазы.

Фаза 1 начинается, когда при обработке транзакции встретился оператор COMMIT. Сервер распределенной БД (или компонент СУБД, отвечающий за обработку распределенных транзакций) направляет уведомление "подготовиться к фиксации" всем серверам локальных БД, выполняющим распределенную транзакцию. Если все серверы приготовились к фиксации (то есть откликнулись на уведомление и отклик был получен), сервер распределенной БД принимает решение о фиксации. Серверы локальных БД остаются в состоянии готовности и ожидают от него команды "зафиксировать". Если хотя бы один из серверов не откликнулся на уведомление в силу каких-либо причин, будь то аппаратная или программная ошибка, то сервер распределенной БД откатывает локальные транзакции на всех узлах, включая даже те, которые подготовились к фиксации и оповестили его об этом.

Ф аза 2 - сервер распределенной БД направляет команду "зафиксировать" всем узлам, затронутым транзакцией, и гарантирует, что транзакции на них будут зафиксированы. Если связь с локальной базой данных потеряна в интервал времени между моментом, когда сервер распределенной БД принимает решение о фиксации транзакции, и моментом, когда сервер локальной БД подчиняется его команде, то сервер распределенной БД продолжает попытки завершить транзакцию, пока связь не будет восстановлена.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]