SQL, или язык структурированных запросов, - на сегодняшний день наиболее важный из языков манипулирования реляционными данными. Он рекомендован Американским национальным институтом стандартов (ANSI) в качестве стандартного языка манипулирования реляционными базами данных и используется как язык доступа к данным многими коммерческими СУБД, включая DB2, SQL/DS, Oracle, INGRES, SYBASE, SQL Server, dBase for Windows, Paradox, Microsoft Access и многие другие. Благодаря своей популярности SQL стал стандартным языком для обмена информацией между компьютерами. Поскольку существует версия SQL, которая может работать почти на любом компьютере и операционной системе, компьютерные системы способны обмениваться данными, передавая друг другу запросы и ответы на языке SQL.
Разработка SQL начиналась в середине 70-х годов прошлого века в исследовательском центре IBM в Сан-Хосе, и изначально язык носил название SEQUEL (сиквел). Было выпущено несколько версий SEQUEL, и в 1980 году продукт был переименован в SQL. С тех пор, помимо IBM, многие производители присоединились к разработке программных продуктов для SQL. Институт ANSI взял на себя работу по поддержке SQL и периодически публикует обновленные версии стандарта SQL. В этой главе обсуждается ядро SQL в том виде, как оно описано в стандарте ANSI 1992 г., который часто обозначают как SQL92[1]. Последняя версия стандарта, SQL3, содержит расширения языка для объектно-ориентированного программирования.
Конструкции и выражения в конкретной реализации SQL (например, в Oracle или SQL Server) могут немного отличаться от ANSI-стандарта. Частично это обусловлено тем, что многие коммерческие СУБД были разработаны до того, как появилось соглашение о стандарте, а также тем, что производители закладывали в свои продукты дополнительные возможности с целью получить преимущество в конкурентной борьбе. Исходя из рыночной перспективы, одной лишь поддержки стандарта ANSI порою считалось недостаточно для обеспечения привлекательности продукта.
Команды языка SQL могут использоваться интерактивно как язык запросов, а также могут быть встроены в прикладные программы. Таким образом, SQL не является языком программирования (как, например, COBOL); он скорее представляет собой подъязык данных (data sublanguage) или язык доступа к данным (data access language), встраиваемый в другие языки.
В этой лекции представлены интерактивные операторы SQL, которые, будучи встроенными в прикладные программы, требуют настройки и модификации. Здесь рассматриваются операторы манипулирования данными и операторы определения данных.
SQL - это язык, ориентированный на преобразования, который принимает на входе одно или несколько отношений и выдает на выходе одно отношение Результат каждого SQL-запроса представляет собой отношение; даже если результатом является отдельное число, это число считается отношением, у которого одна строка и один столбец. Таким образом, подобно реляционной алгебре, язык SQL является замкнутым.
Операторы языка SQL используются во всех интерактивных интерпретаторах языка SQL (Informix-SQL, SQL-Plus, SQL-Query и др.). Для каждого инструмента характерны определенные особенности использования SQL, которые описаны в соответствующей документации.
Формат записи операторов SQL свободный. Можно писать все подряд на одной строке, один оператор на нескольких строках, ключевые слова в операторах можно разделять произвольным количеством пробелов и комментариев. Никакими значками (типа ;) операторы разделять не нужно. Окончание операторов определяется по контексту.
Примечание. Если вы записываете утверждения SQL не в программе, а в среде интерпретатора, то разделять операторы точкой с запятой (;) необходимо.
Весь набор ключевых слов языка SQL зарезервирован, их нельзя занимать для других целей.
Интерпретатору языка безразлично, прописными или строчными буквами пишутся операторы. Он их не различает.
Комментарии обозначаются знаками { комментарий } или знаком -- (два знака минус) до конца строки.
SQL содержит 4 группы операторов:
Ø операторы описания данных: CREATE, DROP, ALTER и др.
Ø операторы задания прав доступа в БД: GRANT / REVOKE , LOCK/UNLOCK, SET LOCK MODE
Ø операторы защиты, восстановления данных и прочие операторы.
Ø операторы манипуляции данными: INSERT, DELETE-, SELECT, UPDATE и др.
Их обзор предлагается ниже.
Операторы описания данных предназначены для описания (создания), изменения описания и уничтожения объектов БД.
В SQL различаются следующие виды объектов:
• база данных (database);
• таблица (table);
• столбец (column);
• индекс (index);
• вид (view);
• синоним (synonym).
Каждый объект имеет собственное имя - идентификатор. Каждый объект имеет владельца, т. е. того пользователя, который его создал. Имя объекта можно уточнять с помощью имени его владельца (owner-name) в такой форме: Irina.tablel
Ниже приводятся примеры использования всех операторов описания данных. Полный же их синтаксис можно найти в "Кратком справочнике по SQL".
CREATE DATABASE primer
В любой момент времени вы можете иметь доступ к объектам только одной, ТЕКУЩЕЙ (CURRENT) базы данных. Оператор DATABASE делает новую БД текущей, закрывая при этом доступ к объектам предыдущей текущей БД. Оператор CLOSE DATABASE просто закрывает текущую БД.
Создаются таблицы kadr и fn, содержащие столбцы разных типов:
CREATE TABLE kadr (
Num INT,
tabnom SERIAL,
fio CHAR(20) UNIQUE,
zp MONEY(16,2),
birth DATE,
datf DATETIME year TO minute)
CREATE TABLE fn ( num int, namec char(20))
В уже существующей таблице мы можем поменять тип столбца, добавить новый, уничтожить старый:
ALTER TABLE kadr ADD (place CHAR(20) BEFORE zp), DROP(birth) ALTER TABLE items MODIFY (manu_code char(4))
Изменение структуры таблицы приводит к физическому преобразованию данных в ней. Если изменен тип столбца, то данные в нем преобразуются в новый тип, и если это невозможно осуществить, то оператор ALTER завершается с кодом ошибки, а таблица остается неизменной.
View-виртуальная таблица базируется на существующих таблицах:
CREATE VIEW vtable AS SELECT tabnom, fio, birth FROM kadr WHERE zp< 1000
# создано view-псевдотаблица из трех столбцов, содержащая строки из таблицы kadr, в которых зарплата (zp) меньше 1000 рублей.
Виртуальная таблица ведет себя точно так же, как настоящая таблица, только место на диске под нее не отводится, поскольку данные, лежащие в ней, на самом деле хранятся в таблице, на которую этот view указывает.
Индекс - дополнительная структура к столбцам таблицы, необходимость в котором продиктована возможностью ускорения поиска значений в столбце:
CREATE UNIQUE INDEX indx ON kadr (tabnom)
# создан индекс для столбца tabnom из таблицы kadr. Индекс уникальный, значит, в столбце не могут появиться одинаковые значения.
Мы можем физически упорядочить таблицу в соответствии с индексом. В кластеризованной таблице SELECT работает значительно быстрее:
ALTER INDEX indx TO CLUSTER
Имена столбцов в разных таблицах могут совпадать. Если в каком-либо операторе SQL упоминаются два столбца с одинаковыми названиями, то их нужно уточнять именами таблиц, их содержащих. Перед именем любого объекта можно (а иногда и необходимо) указать имя его владельца - входное имя пользователя, который создал этот объект:
kadr.num # столбец num из таблицы kadr
fn.num # столбец num из таблицы fn
ivanov.tablei .n1 # столбец п1 из таблицы tablei, владельцем которой является ivanow irina.table1.n1 # столбец п1 из другой (!) таблицы - таблицы table 1, владельцем которой является irina
Синоним для имени таблицы используется для сокращения записи.
CREATE SYNONYM q1 FOR ivanov.tablei .n1
Теперь повсюду можно (хотя и не обязательно) вместо имени ivanov.table1.n1 использовать имя q1.
Естественно, что любой созданный в БД объект можно уничтожить. Надо только помнить, что операторы описания данных не откатываются назад, а потому если вы уничтожили таблицу, или базу данных то это уже необратимо.
DROP VIEW vtable # Уничтожается только view. С данными - в таблицах, на которых он базировался ничего не происходит.
DROP TABLE kadr # уничтожает таблицу вместе с данными.
DROP INDEX indx
DROP SYNONYM q1
DROP DATABASE primer # уничтожает базу вместе со всеми данными и системным журналом
Выдавать и отнимать права доступа к таблице может владелец таблицы, Администратор Базы Данных (имеющий DBA-права), а также пользователь, которому было выдано право определять права (Оператором GRANT WITH GRANT OPTIONS):
REVOKE ALL ON customer FROM PUBLIC GRANT ALL ON customer TO ivanov, petrov WITH GRANT OPTION
GRANT UPDATE(fname,lname,company, sity),SELECT ON customer TO PUBLIC
REVOKE CONNECT FROM sidorov, root REVOKE DBA FROM ivanov
Отобрать у вас права DBA (если вы, конечно, им являетесь) может только другой DBA.
На время транзакции (т. е. проводки) все измененные строки автоматически блокируются системой от изменения (но не от просмотра). Вы можете явно закрыть на замок (lock) всю таблицу целиком, тогда система не будет блокировать строки по отдельности. Вы можете блокировать таблицу целиком не только от изменения, но и от просмотра:
BEGIN WORK LOCK TABLE kadr
UNLOCK TABLE kadr
LOCK TABLE kadr EXCLUSIVE
Если ваш оператор пытается сделать запись в блокированную другим пользователем строку, то оператор завершается по ошибке. Вы можете установить для своей программы режим "Ждать разблокирования строк":
SET LOCK MODE TO WAIT
В БД, не имеющей системного журнала, невозможно выполнение транзакций и восстановление до текущей контрольной точки.
Тем не менее, наличие системного журнала у БД вызывает заметный рост накладных расходов и замедление работы запросов. К тому же при активной работе с базой системный журнал быстро "разбухает". За ним нужно следить и периодически очищать его:
BEGIN WORK # начать транзакцию
# операторы
IF все нормально THEN COMMIT WORK
ELSE ROLLBACK WORK END IF
Если во время транзакции программа аварийно завершилась, то сервер БД автоматически сделает откат назад, к состоянию БД до начала выполнения транзакции; по сути то же, что всегда делает оператор ROLLBACK.
Следующая группа операторов предназначена для манипулирования данными в таблицах. В нее входят операторы выбора (SELECT) строк из таблицы (или таблиц), уничтожения (DELETE) строк в таблице, вставки (INSERT) строк и изменения (UPDATE) значений в существующих в таблице строках.
Оператор DELETE
Уничтожить в таблице kadr все строки, в которых номер подразделения равен 3, а фамилия кончается на буквы "ин":
DELETE FROM kadr WHERE num=3 AND fio MATCHES "*ин"
В результате из списков будут вычеркнуты работники 3-го отдела "Галкин", "Малкин", "Малинин" и т. п.
А этот оператор уничтожит ВСЕ строки в таблице kadr, владельцем которой является irina, но не саму таблицу:
DELETE FROM irina.kadr.
Оператор SELECT
Первый пример находит в таблице kadr строку, в которой столбец tabnum=34. Из этой строки берутся только 3 указанных столбца.
Второй пример выбирает ВСЕ строки из таблицы fn и все столбцы:
Третий пример выбирает фамилии работников из таблицы "кадры", а названия подразделений, в которых они работают, из таблицы fn.
SELECT fio, place, zp FROM kadr WHERE tabnom=34
SELECT * FROM fn
SELECT kadr.fio, fn.namec WHERE kadr.num=fn.num
Оператор INSERT может вставить в таблицу одну строку, если используется в форме INSERT INTO VALUES, а может вставить в таблицу целый набор строк, выбранных подзапросом SELECT из другой таблицы:
INSERT INTO kadr VALUES (4,0,Тромыко",1000,"10/25/1976",NULL)
INSERT INTO customer VALUES (ps_customer.*)
# ps_customer -переменная типа RECORD - аналог структуры в
# языке С. Этот оператор вставляет значения элементов записи
# ps_customer в соответствующие поля таблицы customer
INSERT INTO kadr (tabnom, fio, num, place)
SELECT 0 , fio, 4, place FROM kadrold
WHERE num=3 AND fio IS NOT NULL
# последний оператор вставляет сразу несколько строк
Если мы хотим, чтобы при вставлении строки в столбец типа SERIAL автоматически заносилось очередное значение счетчика, нужно вставлять в этот столбец константу 0.
Если не во все столбцы вставляемой строки вносится значение (как это сделано в третьем операторе), то незаполненные столбцы заполняются значением NULL.
В операторах DELETE, UPDATE, SELECT может присутствовать WHERE-предложение, в котором можно задать условия на строки, требующие обработки (соответственно уничтожить, изменить или выбрать).
Оператор UPDATE
Меняет значения столбцов в строках, удовлетворяющих WHERE-условию:
UPDATE kadr SET fio="lvanov" WHERE тю="Иванов"
UPDATE fn1 SET nam_otd[1,4]=namec[5,8] WHERE
num BETWEEN 3 AND 5 OR namec IN ("ректорат","бухгалтерия")
В таблице fnl в подразделениях номер 3, 4, 5, а также в ректорате и бухгалтерии первые 4 символа в имени подразделения будут заменены на подстроку поля namec из той же строки.
Предложение WHERE
Предложение WHERE может присутствовать в любом из операторов DELETE, UPDATE, SELECT, когда нужно задать условия на строки, которые требуется обработать (соответственно уничтожить, изменить или выбрать). Рассмотрим структуру и примеры использования предложения WHERE.
В предложении WHERE пишется логическое условие, которое получается соединением с помощью логических операторов AND, OR и NOT элементарных сравнений типа:
выражение1 < выражение2,
выражение1 >= выражение2 и т. п.,
а также элементарных сравнений специального вида:
column-name IS [NOT] NULL
выраж [NOT] BETWEEN выраж1 AND выраж2 выраж [NOT] IN (выраж1 ,... [,...])
Можно выяснить, подходит ли символьная строка под определенный шаблон или нет. Для этого используются 2 операции сравнения по шаблону - LIKE и MATCHES:
симв-выражение MATCHES "шаблон"
симв-выражение LIKE "шаблон"
LIKE имеет более простой шаблон. В нем используются только 2 спецсимвола: "%" замещает произвольное количество символов, "_" замещает ровно 1 символ. Все остальные символы в шаблоне обозначают сами себя. Если мы хотим включить в шаблон "%" или "_", отменив их специальный смысл, то перед ними надо поставить ESC-символ (по умолчанию это "\"). Допустим, нам нужно выбрать из таблицы table7 все строки, в которых символьный столбец stringl содержит символ "+", а предпоследняя буква в нем - S. Оператор выборки будет выглядеть так: SELECT * FROM table7 WHERE stringl LIKE "%+%S_"
MATCHES использует такие спецсимволы шаблона, как: *, ?, [, ], ^, -.
* - заменяет любое количество символов;
? - заменяет один любой символ;
[...] - заменяет 1 символ из перечисленных в скобках, возможны указания "от и до" (-) и "не" (Л);
[аbН] - любой из символов a, b, H;
[^d-z] - любой символ, исключая d, e, f, g,..., у, z;
\ - отменяет спецсмысл спецсимволов *,?,[,].
Если вы хотите воспользоваться спецсимволами как обычными, примените escape-char. Если escape-char="\", то \? обозначает просто символ ?, \* обозначает просто символ *, \\ обозначает просто символ \ . Зато знак кавычки (") внутри шаблона нужно обозначать двумя кавычками ("").
Выбрать все данные о заказчиках, в названиях компаний которых вторая буква не лежит в интервале от G до L, а третья буква с:
SELECT * FROM customer WHERE company МАТСЕS”?[^G-L]c*"
Если вы хотите:
сравнить выражение с результатом другого SELECT-оператора:
выраж_сравн {ALL | [ANY | SOME]} (SELECT-statement)
определить, принадлежит ли выражение результатам другого SELECT-оператора:
выраж JNOT] IN (SELECT-statement)
выяснить, выбрал ли хоть что-нибудь другой SELECT-оператор:
_[NOT] EXISTS (SELECT-statement) то применяйте условия с подзапросом.
Условия с подзапросом
SELECT fio FROM kadr WHERE zp=(SELECT MAX(zp) FROM kadr)
Здесь подзапрос возвращает единственное значение - максимальное значение зарплаты. А внешний SELECT-оператор находит фамилии обладателей такой зарплаты:
SELECT fio, kod, org FROM zar WHERE den is not NULL and
city in (SELECT city FROM regiony WHERE region="West")
Здесь запрос выводит данные о руководителях, получивших финансирование и работающих в регионе с условным названием West:
SELECT order_num,stock_rHjm,manu_code, totaLprice FROM items x WHERE totaLprice > (SELECT 2*M IN (totaLprice)
FROM items WHERE order_num=x.order_num)
Этот запрос (используя связанный подзапрос) выводит список всех изделий, чья общая цена не менее чем в 2 раза превосходит минимальную цену изделий, перечисленных в этом же заказе.
Вы можете соединять любое количество вышеперечисленных условий вместе, используя логические операторы NOT, AND, OR.
Расширенные функции оператора SELECT
Предложения INTO, INTO TEMP, FROM. Выбрать все строки (нет предложения WHERE) из таблицы kadr, взять в них все столбцы (вместо переселения столбцов стоит *), оставить только различные строки (ключевое слово UNIQUE) и поместить результат во временную таблицу (INTO TEMP) x, которая будет при этом создана с такими же столбцами, что и у kadr:
SELECT UNIQUE * FROM kadry INTO TEMP x
Выбирать можно из нескольких таблиц. При этом берутся все возможные комбинации строк из первой таблицы со второй. Предположим, что в таблице tab1 6 строк, а в tab2 - 7 строк. Результат нижеприведенного примера - таблица, содержащая 3 столбца и 7*6=42 строки:
SELECT tabl .a-tab2.b, tabl .a, tab2.b FROM tabl, tab2
Результирующую таблицу можно использовать по-разному: ее можно «закачать» (INTO TEMP) во временную таблицу, ее можно отдать на обработку другому оператору (если выборку осуществлял подзапрос), для нее можно создать курсор ("буфер" с указателем на текущую строку), а можно положить её (INTO) в простую программную переменную (если выбрано не более одной строки).
Выбранные строки можно упорядочить по возрастанию (убыванию) значения в столбце (столбцах):
SELECT a,b,c,d+e FROM tabl ORDER BY b,c
SELECT a,b,c,d+e FROM tabl ORDER BY 2,3
В предложении ORDER BY вместо имени столбца можно указывать его порядковый номер в списке выборки (select-list). Вышеприведенные операторы эквивалентны.
Поместить значения из столбцов в переменные (поскольку lname используется и как имя переменной, и как имя столбца, то имя столбца предваряется знаком @:
SELECT customer_num, @lname,city INTO cnum,lname,town FROM customer
Агрегатные функции
К выбранным строкам можно применять агрегатные функции COUNT(*) - количество, MAX(column) и MIN(column) - максимальное и минимальное значение в столбце, SUM(column) - сумма всех значений в столбце, AVG(column) - среднее значение в столбце.
Поместить в переменную num количество строк в таблице orders, в которых столбец customernum равен 101:
SELECT COUNTO INTO num FROM orders WHERE customer_num=101
Пример с использованием соединения таблиц. Находится среднее значение зарплаты, превосходящей 3000 (столбец zp принадлежит одной из таблиц), при условии совпадения столбцов place в двух таблицах:
SELECT AVG (zp) FROM table"! ,table2 WHERE tablei .place=table2.place and zp>3000
Группировка GROUP BY
Группировка используется для сброса группы (строк) в одну.
Результат запроса содержит одну строку для каждого множества строк, удовлетворяющих WHERE-предложению и содержащих одно и то же значение в указанном столбце:
SELECT place, COUNTf), AVG(zp) FROM kadr GROUP BY place
Получить количество работающих и их среднюю зарплату по каждому месту:
SELECT place, COUNT(*), AVG(zp) FROM kadr GROUP BY 1
Эквивалентная запись
Предложение
HAVING накладывает дополнительные условия на группу:
SELECT order_num, AVG(totaLpriece) FROM items
GROUP BY order_num HAVING COUNTf) > 2 I
Этот
запрос возвращает номера заказов и среднее значение total_price
в заявках для всех заказов, имеющих не менее двух заявок.
Внешнее соединение таблиц
Строки из таблицы, присоединенной внешним образом (на внешнее соединение указывает ключевое слово OUTER), будут выбираться, несмотря! на то, удовлетворяют ли они условиям WHERE предложения или нет. В некоторых случаях это полезно, когда у вас есть главная и вспомогательная таблица и данные из главной таблицы вам нужно получить в любом случае. Пример внешнего соединения:
SELECT company, order_num FROM customer с, OUTER orders о
WHERE c.customer_num=o customer_num
Запрос находит названия компаний и номера заказов, которые они послали. Если же компания заказов не присылала, то ее название все равно будет выбрано, а номер заказа в этой строке будет равен NULL. (А если бы мы запустили запрос без параметра OUTER, то названия этих компаний вообще не попали бы в выборку - SQL для Informix.)
Сложные примеры манипуляции данными
Операторы манипуляции данными - самая мощная составляющая SQL.
В следующем примере ликвидируются одинаковые строки в таблице kadr.
select unique * from kadr into temp kd delete from kadr where 1=1 Insert into kadr select * from kd ^rop table kd
В следующем примере информация в строках изменяется по значению ключа.
• Таблица b содержит (kl int, pole char(20)), причем все kl различны.
• В таблице kadr заменить kadr.place на b.pole в строках, где kadr.tabnom=b .kl:
SELECT b.kl, b.pole, num, place, zp, birth
FROM kadr, b WHERE kadr.tabnom=b.kl into temp kd
DELETE FROM kadr WHERE tabnom in (SELECT kl FROM b)
INSERT INTO kadr SELECT * FROM kd
DROP TABLE kd
Ту же самую операцию можно проделать с помощью одного оператора UPDATE, использующего подзапрос:
UPDATE kadr SET
place=(select pole from b where kadr.tabnom=b.kl) WHERE tabnom IN (select kl from b)
В следующем примере информация в строках изменяется по значению ключа при выполнении условий, наложенных на меняемые строки:
Таблица newtable______ Таблица oldtable
fio har_________cen fio ... har_______ ... cen
John способный $300 John бездарный $600
Piter коммунист______ … __________ ______
Bob хороший____$25 Piter демократ $45
Bob плохой $15 Ronny плохой_____ ______
В таблице oldtable хранятся сведения о сотрудниках. На основе последних исследований была составлена таблица newtable, с поправками к содержанию oldtable.
Строчка будет подменяться, если за новую информацию о сотруднике в таблице newtable заплачено больше, чем за хранящуюся в oldtable:
UPDATE oldtable SET
(har,cen)=( (SELECT har.cen FROM newtable WHERE oldtable.fio=newtable.fio)) * WHERE fio IN (SELECT fio FROM newtable) AND
cen < (SELECT cen FROM newtable WHERE oldtable.fio=newtable.fio);
Поскольку чистый SQL не является алгоритмическим языком, т. е. не содержит в себе операторов IF-THEN-ELSE, DO WHILE, FOR, CASE и т. д., его с самого начала возникновения пытались расширить, чтобы полу- I чить возможность писать на нем простейшие программы.
В настоящее время имеются 3 наиболее распространенные версии процедурных расширений языка SQL:
Ø версия фирмы Oracle под названием PL/SQL, которая входит во все без исключения версии Oracle и является основным инструментом создания приложений под Oracle;
Ø версия Informix и ряда других фирм, получившая название языка 4-го поколения 4GL;
Ø последняя по времени появления версия, ориентированная на Java, или ужe скорее симбиоз Java+SQL, получившая условное название JavaSQL.
Язык SQL, созданный более четверти века тому назад, превратился в общепризнанный универсальный инструмент для управления данными. Во многих отношениях появление Java стало практичным и вездесущим средством обогащения этой инфраструктуры семантикой произвольного уровня сложности, которым может быть только универсальный объектно-ориентированный язык программирования. Подобная логика по самой своей природе является распределенной, ее легко развернуть на любом уровне архитектуры сетевых вычислений.
Сочетание получивших широкое распространение серверов СУБД SQL-типа и Java-логики позволит превратить реляционные системы в серверы обработки информации универсального типа, без которых трудно себе представить информационную архитектуру будущего.
Скачано с www.znanio.ru
[1] International Standards Organization Publication ISO/IEC 9075 1992, Database Language SQL
Материалы на данной страницы взяты из открытых источников либо размещены пользователем в соответствии с договором-офертой сайта. Вы можете сообщить о нарушении.