Скачать 272.18 Kb.
|
Категории SQL
DMLК этой категории относятся средства SQL, предназначенные для манипулирования данными, то есть, записями в таблицах. Примеры будут приведены на образцовой базе Northwind, которую можно загрузить с: http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=23654 Общая информацияSQL является общепринятым языком реляционных систем, поэтому в большой (хотя и не полной) мере соответствует манипуляционному аспекту реляционной модели данных. В SQL можно найти средства, реализующие некоторые операции реляционной алгебры, а также средства, более соответствующие реляционному исчислению. Также некоторые возможности SQL не являются реляционными (например, выражение ORDER BY), но здесь на этом вопросе останавливаться не будем. Подобно реляционной алгебре, в которой все операции работают с отношениями и возвращают тоже отношения, рассматриваемые DML-операторы также работают с отношениями и возвращают отношения. Отношения в SQL представляются в табличной форме и состоят из записей (records), также называемых строками (rows) и столбцов (columns), также называемых атрибутами. Каждый столбец имеет название и тип данных. В реляционной модели строки называются кортежами, а столбцы только атрибутами. На рис.1 показан результат выполнения запроса, выбирающего все строки из таблицы Region. Выборка осуществляется командой SELECT, которая отображает отношение, указанное после инструкции FROM.В данном случае этим отношением является содержимое таблицы Region, но им также может являться более сложное выражение, состоящее из объединений разных таблиц, фильтрации записей, группировок или вложенных подзапросов. Рис. 1. Результат выборки всех строк из таблицы Region Назначение операторов DML
Поясним работу DML операторов на примерах. Запросы на выборку данныхВыборка с фильтрацией (селекцией) и проекциейДля выборки данных используется команда SELECT. Простейший синтаксис команды можно описать шаблоном: SELECT <�список атрибутов> -- Здесь задаётся проекция FROM < выражение, возвращающее отношение > WHERE <�условие фильтрации> -- Здесь задаётся селекция Пример 1. Выбрать клиентов, проживающих в городе «London». SELECT * FROM Customers WHERE City = 'London' В данном примере «*» означает, что будут выбраны все атрибуты из выражения “FROM”. Само выражение состоит из одной таблицы Customers. Из результата выражения “FROM” выбираются только записи, удовлетворяющие условию, заданному после ключевого слова WHERE. Пример 2. Выбрать имя, адрес, город и страну всех клиентов, чей телефонный номер начинается на «(21)». SELECT ContactName, Address, City, Country FROM Customers WHERE Phone LIKE '(21)%' Пример 3. Выбрать список городов, в которых проживают клиенты из Франции, упорядоченный по алфавиту. SELECT City FROM Customers WHERE Country = 'France' ORDER BY City Упорядочить результаты запроса позволяет ключевое слово ORDER BY, после которого перечисляются атрибуты, по которым происходит сортировка. Поскольку клиентов, проживающих во Франции, 11, запрос вывел 11 записей, несмотря на то, что некоторые названия городов совпадают. Чтобы исключить дубликаты, можно использовать ключевое слово DISTINCT. Пример 4. SELECT DISTINCT City FROM Customers WHERE Country = 'France' ORDER BY City Запросы с соединениемSQL позволяет в одном запросе объединять данные из нескольких таблиц (и вообще произвольных отношений, например, подзапросов). Ключевой операцией при этом является соединение (JOIN), которое логически представляет собой декартово произведение, отфильтрованное по некоторым условиям. Пример 5. Декартово произведение двух таблиц. Выбрать все сочетания регионов и территорий SELECT * FROM Region, Territories В таблице Region 4 записи, в таблице Territories – 53. При выполнении произведения запрос вернул 4*53=212 записей, то есть все возможные сочетания регионов и территорий. Произведение в SQL можно получить просто перечислив таблицы (отношения) через запятую. Также можно использовать альтернативный синтаксис используя CROSS JOIN: SELECT * FROM Region CROSS JOIN Territories Пример 6. Естественное соединение (NATURAL JOIN) В декартовом произведении мало практической пользы, если только нам действительно не надо перечислить все сочетания кортежей из двух отношений (что бывает не очень часто). Однако произведение используется в качестве основы для самого распространённого типа соединений – естественного соединения. Покажем его на примере запроса, который должен вывести территории с указанием регионов, к которым территории относятся. Для выполнения такого запроса необходимо из всех сочетаний «регион-территория» (пример 5) отобрать те, в которых RegionID у территории и RegionID у региона совпадают. SELECT * FROM Region, Territories WHERE Region.RegionID = Territories.RegionID В результате получим список территорий, где можно увидеть не только RegionID, но и RegionDescription, соответствующий региону этой территории. Соединение, в котором условием селекции является равенство атрибутов с одинаковым названием (в других интерпретациях – равенство атрибутов, связанных ссылкой внешнего ключа) называется естественным (NATURAL JOIN). Transact-SQL не поддерживает естественное соединение напрямую, поэтому надо явно писать условие соединения. Может быть удобен альтернативный синтаксис через INNER JOIN … ON: SELECT * FROM Region INNER JOIN Territories ON Region.RegionID = Territories.RegionID Перед и после INNER JOIN указываются таблицы, которые необходимо соединить, условие соединения пишется далее после слова ON. Такой синтаксис может быть более удобен, если соединений много. Тогда каждое условие соединения будет располагаться в тексте запроса рядом с соединяемыми таблицами, и его нельзя будет случайно забыть или удалить при добавлении новых соединений. Также блок селекции WHERE освобождается от лишних однотипных условий, и там остаётся место только для фильтров, применяемых после выполнения соединений. Алгоритм, который использует СУБД для выполнения соединений не зависит от используемого синтаксиса. СУБД проанализирует оба приведённых в этом примере запроса, и для них в итоге построится одинаковый план выполнения. Пример 7. Выбрать из базы сотрудников (фамилию и имя) и названия связанных с ними территорий для всех территорий, относящихся к региону «Western». Запрос потребует выполнения нескольких естественных соединений с последующей селекцией. Условие запроса, как видно из схемы БД, потребует соединения четырёх таблиц. Запрос примет следующий вид: SELECT DISTINCT FirstName, LastName, TerritoryDescription FROM Employees INNER JOIN EmployeeTerritories ON Employees.EmployeeID = EmployeeTerritories.EmployeeID INNER JOIN Territories ON EmployeeTerritories.TerritoryID = Territories.TerritoryID INNER JOIN Region ON Region.RegionID = Territories.RegionID WHERE Region.RegionDescription = 'Western' Для улучшения читабельности и сокращения длины запросов можно внутри запроса для названий таблиц (и вообще любых подзапросов) задать псевдонимы. Псевдоним можно использовать вместо имени таблицы внутри этого запроса. Также псевдонимы приходится использовать, если в соединениях некоторые таблицы встречаются более одного раза, чтобы иметь возможность различить разные вхождения этой таблицы в запрос. SELECT DISTINCT FirstName, LastName, TerritoryDescription FROM Employees e INNER JOIN EmployeeTerritories et ON e.EmployeeID = et.EmployeeID INNER JOIN Territories t ON et.TerritoryID = t.TerritoryID INNER JOIN Region r ON r.RegionID = t.RegionID WHERE r.RegionDescription = 'Western' Псевдоним указывается сразу после объявления таблицы, к которой планируется использовать псевдоним. После объявления псевдонима ссылаться на таблицу можно только по имени псевдонима, а не по оригинальному имени таблицы. Запросы с группировкойSQL позволяет формулировать запросы, рассчитывающие агрегатные значения по группам записей в отношениях. Например, можно написать запрос, который сгруппирует продажи по товарам (в одну группу попадут записи о продажах, относящиеся к одному товару) и выведет сумму выручки по каждому товару (т.е. по каждой полученной группе). По каждой группе в запросе с группировкой должна в итоге сформироваться только одна запись, поэтому отображать такой запрос может только атрибуты, по которым происходит группировка (поскольку значения такого атрибута одинаковы для всех записей внутри группы), либо значения агрегатных функций по атрибутам, значения которых могут различаться внутри группы. Список основных агрегатных функций:
Синтаксис команды SELECT с использованием группировки. SELECT a, b, SUM(c) –- список атрибутов (можно указывть только атрибуты, -- перечисленные в GROUP BY и агрегатные функции FROM T1 –- отношение, которое является исходным для группировки -- в качестве T1 может выступать любое выражение, которое -- обычно используется в разделе FROM -- (можно включать соединения нескольких таблиц и подзапросы) WHERE T1.e = 123 -- условие, по которому фильтруется -- результат выражения из FROM до группировки GROUP BY a, b -- атрибуты из выражения из FROM-WHERE, по которым производится -- группировка. В одну группу попадают записи из результата -- выражения FROM-WHERE, имеющие совпадающие значения этих атрибутов HAVING a > 0 AND AVG(c) < 10 –- условие, по которому фильтруется результат -- после группировки. Можно указывть только атрибуты, -- перечисленные в GROUP BY и агрегатные функции ORDER BY SUM(c) –- сортировка результата после группировки Пример 8. Вывести количество поставщиков (suppliers) по странам Для наглядности сначала посмотрим на список всех поставщиков в базе данных Northwind. SELECT CompanyName, ContactName, Fax, Country FROM Suppliers ORDER BY Country Нужный нам запрос, выводящий список стран с количеством поставщиков из этой страны будет выглядеть так. SELECT Country, COUNT(*) as Number FROM Suppliers GROUP BY Country ORDER BY Number DESC Инструкция ORDER BY … DESC в данном случае использована для упорядочивания списка по убыванию количества поставщиков. Пример 9. Вывести количество поставщиков по странам, учитывая только тех поставщиков, у которых есть факс. SELECT Country, COUNT(*) as Number FROM Suppliers WHERE Fax IS NOT NULL GROUP BY Country ORDER BY Number DESC Поскольку условие WHERE применяется до группировки, это повлияло на количество поставщиков в группах. Пример 10. Вывести количество поставщиков по странам, учитывая только тех поставщиков, у которых есть факс. Вывести только те страны, в которых поставщиков больше одного. SELECT Country, COUNT(*) as Number FROM Suppliers WHERE Fax IS NOT NULL GROUP BY Country HAVING COUNT(*) > 1 ORDER BY Number DESC Условие HAVING фильтрует записи после группировки, поэтому оно оставило только группы, в которых количество поставщиков более одного. Пример 11. Вывести список поставщиков с количеством поставляемых продуктов. Учитывать только продукты, поставка которых возможна (атрибут Discontinued = 0). Вывести только поставщиков из Австралии, Франции, США и Канады. SELECT s.SupplierID, s.CompanyName, s.Country, COUNT(*) FROM Suppliers s INNER JOIN Products p ON s.SupplierID = p.SupplierID WHERE p.Discontinued = 0 GROUP BY s.SupplierID, s.CompanyName, s.Country HAVING s.Country IN ('Australia', 'France', 'USA', 'Canada') ORDER BY COUNT(*) DESC Поскольку для атрибута с количеством товаров (COUNT (*)) не указан псевдоним, столбец в результирующей выдаче не имеет имени. Примечание: в данном случае условие в HAVING может быть перенесено в блок FROM…WHERE, так как и в таком случае поставщики из ненужных стран будут исключены, но ещё до группировки. Пример 11. Вывести количество поставщиков SELECT COUNT(*) FROM Suppliers Если агрегатные функции использованы в блоке SELECT, но отсутствует GROUP BY, то весь результат, возвращаемый FROM, рассматривается как одна группа и агрегаты считают значения по этой единственной группе. Пример 12. Вывести количество стран, из которых в базе есть поставщики. Интуитивный запрос SELECT COUNT(Country) FROM Suppliers вернёт количество записей в таблице Suppliers (то есть, 29). Это происходит по той причине, что (из соображений производительности) результаты запросов по умолчанию могут выводить дубликаты. Например, запрос SELECT Country FROM Suppliers вернёт список: Несмотря на то, что операция проекции в реляционной алгебре исключает дубликаты кортежей, результат запроса SQL может содержать дубликаты (в этом одно из отличий чистой реляционной модели от модели, используемой в SQL). По этой причине подсчёт строк, даже с указанием атрибута Country, для таблицы Suppliers вернёт 29. Нужно явно указать, что мы хотим подсчитать только уникальные значения Country. SELECT COUNT(DISTINCT Country) FROM Suppliers Добавление данныхДля добавления данных в таблицы (и, в общем случае, в представления) используется команда INSERT. Одно выражение, использующее INSERT, может добавить данные только в одну (указанную) таблицу. Но возможно добавление множества записей одной командой. Пример 12. Вставить в таблицу Categories новую категорию товаров ‘Alcohols’ Содержимое таблицы до выполнения вставки. SELECT * FROM Categories Добавление новой записи. INSERT INTO Categories( CategoryName, -- перечисляем атрибуты [Description] ) VALUES ( 'Alcohols', -- перечисляем значения атрибутов в том же порядке 'Vodka, Whiskey, Cognac, Tequila etc' ) SELECT @@IDENTITY –- смотрим, какое значение автоинкрементного поля сгенерировалось SELECT * FROM Categories –- смотрим, что в таблице Поскольку в таблице Categories первичный ключ CategoryID указан как автоинкрементное поле (IDENTITY), то явно задать его значение нельзя — оно генерируется сервером БД. Глобальная переменная @@IDENTITY позволяет узнать, какое значение было сгенерировано после выполнения последней инструкции. Последний запрос выводит данные таблицы после вставки. Видно, что для нашей новой записи значение автоинкрементного поля действительно равно 9 (это же значение вернул SELECT @@IDENTITY), а атрибут Picture, не указанный в списке атрибутов в команде INSERT, получил значение NULL. Пример 13. Сопоставить работнику с EmployeeID=1 все территории с регионом Southern (добавить сопоставления, не удалять существующие). Сопоставление работников и территорий хранится в таблице EmployeeTerritories. Для сопоставления территории работнику необходимо вставить запись в эту таблицу, в которой будет указано, к какому работнику относится какая территория (вставляются, разумеется, значения соответствующих внешних ключей). Выведем исходный список территорий, сопоставленных работнику (EmployeeID=1). SELECT e.EmployeeID, e.LastName, t.TerritoryDescription, r.RegionDescription FROM Employees e JOIN EmployeeTerritories et ON e.EmployeeID=et.EmployeeID JOIN Territories t ON et.TerritoryID=t.TerritoryID JOIN Region r ON t.RegionID=r.RegionID WHERE e.EmployeeID=1 Команда INSERT может добавлять записи не только по одной, но сразу вставить результат запроса. Поэтому выполнить наш запрос можно одной командой, которая сразу вставит все записи одним запросом: INSERT INTO EmployeeTerritories(EmployeeID, TerritoryID) SELECT 1, TerritoryID FROM Territories t JOIN Region r ON t.RegionID=r.RegionID WHERE r.RegionDescription LIKE 'Southern%' Список территорий работника (EmployeeID=1) после добавления: Удаление данныхДля удаления строк таблиц используется команда DELETE. Эта команда удаляет записи из одной (указанной) таблицы, но одной командой может быть удалено сразу множество записей. Примечание: если удаляются записи, на которые ссылаются через внешний ключ другие записи, то ссылающиеся записи будут также удалены, если для этого внешнего ключа настроено каскадное удаление (CASCADE DELETE), либо значения этих внешних ключей установятся в NULL при настроенном каскадном удалении типа SET NULL. Если же каскадное удаление не установлено, запрос на удаление не выполнится, как нарушающий ссылочную целостность. Пример 14. Удалить все записи из таблицы OrderDetails DELETE OrderDetails Пример 15. Удалить все продукты стоимостью более 40 DELETE FROM Products WHERE UnitPrice > 40 Пример 16. Удалить для сотрудника (EmployeeID=1) сопоставления с территориями региона Southern Предположим, что база данных находится в состоянии после выполнения запроса из примера 13 и сотруднику (EmployeeID=1) сопоставлены следующие территории: Таким образом, корректно составленный запрос должен удалить 8 записей из 10. Запрос, удаляющий все сопоставления с указанными условиями выглядит следующим образом. DELETE EmployeeTerritories --SELECT EmployeeTerritories.* FROM EmployeeTerritories JOIN Territories t ON EmployeeTerritories.TerritoryID = t.TerritoryID JOIN Region r ON t.RegionID = r.RegionID WHERE EmployeeTerritories.EmployeeID = 1 AND r.RegionDescription LIKE 'Southern%' Команде DELETE явно указывается из какой таблицы будут удаляться записи, а в разделе FROM формулируется запрос, который указывает, какие именно записи будут удалены. Если не запускать этот запрос, а вместо DELETE написать SELECT * (строчка, закомментированная в примере), то можно вывести записи, которые должны быть удалены соответствующей командой DELETE. Таким способом удобно проверить заранее что будет удалено, чтобы случайно не удалить по ошибке лишние записи. Имя таблицы, из которой удаляются записи, тоже может быть указано как псевдоним: DELETE et --SELECT et.* FROM EmployeeTerritories et JOIN Territories t ON et.TerritoryID=t.TerritoryID JOIN Region r ON t.RegionID=r.RegionID WHERE et.EmployeeID = 1 AND r.RegionDescription LIKE 'Southern%' Обновление данныхЗаписи в таблицах обновляются командой UPDATE. Пример 17. Установить для всех записей таблицы Categories значение атрибута Description равное ‘No description’ UPDATE Categories SET [Description] = 'No description' Пример 18. Изменить значение страны поставщика на ‘United Kingdom’, если оно было равно ‘UK’ Посмотрим на состояние таблицы Suppliers (поставщики) до выполнения изменений. Для краткости выведем первых 10 поставщиков, упорядоченных по названию страны с конца алфавита. SELECT TOP 10 SupplierID, CompanyName, Country FROM Suppliers ORDER BY Country DESC Очевидно, что все поставщики из страны ‘UK’ попали в результат запроса и всего их 2. Запрос на обновление: UPDATE Suppliers SET Country = 'United Kingdom' WHERE Country = 'UK' Проверяем, что в таблице Suppliers: Пример 19. Установить цену продажи всех продуктов в заказах клиента с CustomerID = ‘COMMI’ равными базовым ценам минус 10%, а значение скидки для них в 0,1 Посмотрим, какие цены установлены на товары в заказах COMMI изначально. SELECT o.CustomerID, ProductName, od.UnitPrice AS OrderPrice, od.Discount, p.UnitPrice FROM [Order Details] od JOIN Products p ON od.ProductID = p.ProductID JOIN Orders o ON o.OrderID = od.OrderID WHERE CustomerID = 'COMMI' Атрибут OrderPrice в запросе показывает цену товара в заказе (которую нужно изменить), атрибут UnitPrice – базовую цену, указанную в таблице Products. Запрос, обновляющий цены в заказе. UPDATE od SET UnitPrice = 0.9 * p.UnitPrice, Discount = 0.1 FROM [Order Details] od JOIN Products p ON od.ProductID = p.ProductID JOIN Orders o ON o.OrderID = od.OrderID WHERE CustomerID = 'COMMI' DDLData Definition Language используется для изменения схемы БД. Для этого используются инструкции CREATE (создание объекта схемы БД), ALTER (изменение объекта схемы БД) и DROP (удаление объекта схемы). После инструкции идёт тип объекта (DATABASE, TABLE, VIEW, PROCEDURE, FUNCTION и другие). Для каждого типа объектов синтаксис команды свой собственный. Работа с таблицами Пример 1. Создание таблицы Region CREATE TABLE Region ( RegionID INT PRIMARY KEY, RegionDescription NCHAR(50) NOT NULL ) При создании таблицы указывается имя таблицы и в круглых скобках список атрибутов с их типами и признаком NULL/NOT NULL. Около атрибута-первичного ключа указывается PRIMARY KEY. Пример 2. Создание таблицы Territories, связанной с ранее созданной таблицей Region внешним ключом. CREATE TABLE Territories ( TerritoryID NVARCHAR(20) PRIMARY KEY, TerritoryDescription NCHAR(50) NOT NULL, RegionID INT NOT NULL REFERENCES Region (RegionID) ) Для атрибута-внешнего ключа при помощи ключевого слова REFERENCES указывается таблица и атрибут первичного ключа, на который ссылается внешний ключ. Пример 3. Добавление ограничения внешнего ключа. Допустим, что мы создали таблицу Territories, не отметив атрибут RegionID как внешний ключ: CREATE TABLE Territories ( TerritoryID NVARCHAR(20) PRIMARY KEY, TerritoryDescription NCHAR(50) NOT NULL, RegionID INT NOT NULL ) Для того, чтобы между существующими таблицами создать связь по внешнему ключу, необходимо добавить ограничение (CONSTRAINT) внешнего ключа в таблицу с внешним ключом: ALTER TABLE Territories ADD CONSTRAINT FK_Territories_Region FOREIGN KEY(RegionID) REFERENCES Region (RegionID) После выполнения этого запроса обычный атрибут Territories.RegionID станет внешним ключом на атрибут Region.RegionID. Используя синтаксис с добавлением ограничения, нам пришлось явно указывать имя этого ограничения (FK_Territories_Region). В примере 2 ограничение, конечно, тоже создаётся, но его имя сервер генерирует самостоятельно. Пример 4. Удаление таблицы Territories DROP TABLE Territories Пример 5. Добавление нового атрибута. Предположим, что в ранее созданную таблицу Territories нам понадобилось добавить атрибут TerritoryArea типа FLOAT для хранения площади территории. ALTER TABLE Territories ADD TerritoryArea FLOAT NOT NULL Пример 6. Изменение свойств атрибута. Допустим, после добавления атрибута TerritoryArea нам захотелось исправить тип FLOAT на DECIMAL(9,3), а значения этого атрибута сделать необязательными (NULL вместо NOT NULL). ALTER TABLE Territories ALTER COLUMN TerritoryArea DECIMAL(9,3) NULL ALTER COLUMN внутри инструкции ALTER TABLE переопределяет тип атрибута. Пример 7. Удалить атрибут TerritoryArea из таблицы Territories ALTER TABLE Territories DROP COLUMN TerritoryArea |
Инструкция по установке и эксплуатации столешниц из древесного массива. Область применения Область применения: столешницы, ступени, подоконники, барные и административные стойки, подстолья в ванную комнату |
Рабочей программы учебной дисциплины «Основы философии» Область применения программы Область применения программы. Программа учебной дисциплины является частью программы подготовки специалистов среднего звена в соответствии... |
||
Инструкция по применению Область применения – стоматология. Для профессионального применения в условиях лпу |
Расшифровка. 9 класс Знаки, обозначающие правила техники безопасности при выполнении химических опытов, и их расшифровка |
||
Расшифровка символов, нанесенных на триммер Внимание! Тщательно изучите последующие указания. Внимательно ознакомьтесь с элементами управления триммера и правилами надлежащего... |
Руководство администратора наименование утверждаемого документа Оглавление... Развитие информационно-аналитического обеспечения лицензионной деятельности в Российской Федерации |
||
1 Область применения Перечень национальных стандартов и сводов правил, утвержденный распоряжением Правительства РФ от 21 июня 2010 г. N 1047-р, которые... |
Назначение и область применения ппр |
||
1 Назначение и область применения Должностной инструкции |
Решением Ученого совета спбПУ Область применения |
||
Технологический регламент Область применения свай, погружаемых методом вдавливания |
Приложение №2 Назначение и область применения: размещение гарантийной бригады на территории в/ч п/п 23944-2 |
||
1. Область применения О введении в действие "Санитарных правил эксплуатации метрополитенов. Сп 1337-03" |
Как запитать аккумуляторный шуроповерт от электрической сети? Все зависит от применения сменных головок – битов. Область применения шуроповерта также очень широка: им пользуются сборщики мебели,... |
||
1. область применения Рд 22-28-37-02 Требования к организации и проведению работ по монтажу (демонтажу) грузоподъемных кранов |
1. Область применения Государственный комитет Российской Федерации по строительству и жилищно-коммунальному комплексу постановляет |
Поиск |