Основи на съвременните бази данни Предговор


Лекция 15. Език SQL. Средства за манипулиране на данните



страница11/17
Дата17.08.2018
Размер1.71 Mb.
#80209
1   ...   7   8   9   10   11   12   13   14   ...   17

Лекция 15. Език SQL. Средства за манипулиране на данните

15.1. Структура на заявките


За да се даде по-точна структура на заявките в стандарта SQL/89, трябва да се започне със сводка синтактичните правила:

::=

[]

::=

| UNION [ALL]



::=

| ()



::=

(SELECT [ALL | DISTINCT] )



INTO



::=

(SELECT [ALL | DISTINCT]





::=

[]

[]

[]

Езикът допуска три типа синтактични конструкции, започващи с ключовата дума SELECT: спецификация на курсор (cursor specification), оператор за избор (select statement) и подзаявка (subquery). Основа за всички тях е синтактичната конструкция "табличен израз (table expression)". Семантиката на табличния израз се състои в това, че на основата на последователното прилагане на разделите from, where, group by и having от зададените в раздела from таблици се построява нова резултираща таблица, редът на следване на редовете на която не е определен и сред редовете на която може да дубликати (т.е. в общия случай таблицата-резултат на табличен израз е мултимножество от редове). По съществ именно структурата на табличния израз най-пълно характеризира структурата на заявките в езика SQL/89. Ще разгледаме структурата и смисъла на разделите на табличния израз, но първо ще обсъдим трите споменати конструкции, включващи таблични изрази.

15.1.1. Спецификация на курсор

Най-обща е конструкцията "спецификация на курсор". Курсорът е понятие на езика SQL, позволяващо чрез набор специални оператори да се получи поредов достъп до резултата от заявката към БД. Към табличните изрази, участващи в спецификацията на курсора, не се предявяват ограничения. Както се вижда от сводката на синтактичните правила, при определяне спецификацията на курсор се използват три допълнителни конструкции: спецификация на заявка, израз на заявките и раздел ORDER BY.

Спецификация на заявка

В спецификацията на заявка се задава списък на извадката (списък с аритметичните изрази над значенията на стълбовете на резултата на табличния израз и константите). В резултат от прилагането на списъка на избора към резултата на табличния израз се извършва построяване на нова таблица, съдържаща същия брой редове, но най-общо друг брой стълбове, съдържащи резултатите от изчислението на съответните аритметични изрази от списъка на извадката. Освен това, в спецификацията на заявка може да се съдържат ключовите думи ALL или DISTINCT. При наличие на ключовата дума DISTINCT от таблицата, получена с прилагане на списъка на извадката към резултата от табличния израз, се премахват редовете-дубликати; при указание ALL (или просто при отсъствие на DISTINCT) премахването на редовете-дубликати не се извършва.



Израз на заявките

Изразът на заявките е израз, строящ се по указани синтактични правила на основата на спецификациите на заявките. Единствената операция, която е разрешено да се използува в изразите на заявките, е операция UNION (обединение на таблици) с възможна разновидност UNION ALL. Към таблиците-операнди на израза на заявките се предявява изискването всички те да съдържат един и същи брой стълбове, и съответствуващите стълбове на всички операнди трябва да бъдат от един и същи тип. Изразът на заявките се изчислява отляво надясно с отчитане на скобите. При изпълнението на операция UNION се извършва обикновено теоретико-множествено обединение на операндите, т.е. от резултиращата таблица се изтриват дубликатите. При изпълнение на операцията UNION ALL се образува резултираща таблица, в която могат да се съдържат редове-дубликати.



Раздел ORDER BY

Накрая, раздел ORDER BY позволява да се установи желания ред на преглеждане на резултата от израза на заявките. Синтаксисът на ORDER BY е следният:



::=

ORDER BY

[{,}...]

::=

{ | }

[ASC | DESC]

Както се вижда от тези синтактични правила, фактически се задава списъка на стълбовете на резултата от израза на заявките, и за всеки стълб се посочва редът на преглеждане на редовете на резултата в зависимост от стойностите на този стълб (ASC - по нарастване (подразбиране), DESC - по намаляване). Стълбовете може да се задават с имената им тогава и само тогава, когато (1) изразът на заявките не съдържа операция UNION или UNION ALL и (2) в списъка на избора в спецификацията на заявката на този стълб съответствува аритметичен израз, състоящ се само от името стълбеца. Във всички останали случаи в раздела ORDER BY трябва да се указва поредния номер на стълбеца в таблицата-резултат от израза на заявките.


15.1.2. Оператор за избор

Операторът за избор е отделен оператор на езика SQL/89, позволяващ да се получи резултат от заявка в приложна програма без привличане на курсор. Затова операторът за избор има синтаксис, различаващ се от синтаксиса на спецификацията на курсор, и при неговото изпълнение възникват ограничения върху резултата от табличния израз. Фактически, и едното, и другото се диктува от спецификата на оператора за избор както на един отделен оператор на SQL: при неговото изпълнение резултатът трябва да бъде поставен в променливи на приложната програма. Затова в оператора се появява раздел INTO, съдържащ списък на променливи от приложната програма, и възниква ограничението, резултиращата таблица да съдържа не повече от един ред. Съответно, резултатът от базовия табличен израз трябва да съдържа не повече от един ред, ако операторът за избор не съдържа спецификация DISTINCT, и таблицата, получена чрез прилагане на списъка за избор към резултата от табличния израз, не трябва да съдържа повече от един несъвпадащи редове, ако спецификацията DISTINCT е зададена.

Забележка: В диалекта на SQL на СУБД Oracle се поддържа разширен вариант на оператора за избор, резултатът на който не е задължително да е таблица от един ред. Такова разширение не се поддържа нито в SQL/89, нито в SQL/92.


15.1.3. Подзаявка

Накрая, последната конструкция на SQL/89, която може да съдържа таблични изрази, - това е подзаявката, т.е. заявка, която може да се включва в предиката на условието за избор на оператор на SQL. В SQL/89 към подзаявките се прилага ограничението, резултиращата таблица да съдържа точно един стълбец. Затова в синтактичните правила, определящи подзаявка, вместо списък на извадката се указва "израз, изчисляващ стойност", т.е. аритметичен израз. Ще отбележим че, тъй като подзаявката винаги е вложена в някакъв друго оператор на SQL, то в качеството константи в аритметичен израз за избор и в логическите изрази на разделите WHERE и HAVING може да се използват сатойностите на стълбовете на текущите редове на таблиците, участвуващи в (под)заявките от по-външно ниво.

15.2. Табличен израз


Стандартът SQL/89 препоръчва да се разглежда изчислението на табличен израз като последователно прилагане на разделите FROM, WHERE, GROUP BY и HAVING към таблиците, зададени в списъка FROM. Разделът FROM има следния синтаксис:

::=

FROM

({,

}...]

::=

[]
15.2.1. Раздел FROM

Резултатът от изпълнението на раздела FROM представлява разширено декартово произведение на таблиците, зададени в списъка на таблиците на раздела FROM. Разширеното декартово произведение (разширено, защото в качеството на операнди и резултат се допускат мултимножества) в стандарта се определя по следния начин:

"Разширеното произведение R е мултимножество от всички редове такива, че r представлява конкатенация на редовете от всички идентифицирани таблици в този ред, в който те са идентифицирани. Мощността на R е произведение от мощностите на идентифицираните таблици. Поредният номер на стълбеца в R е n+s, където n е поредният номер на порадащия стълб в именуваната таблица T, а s е сума от степените на всички таблици, идентифицирани преди T в раздела FROM".

Както се вижда от синтаксиса, до името на таблица може да се указва още едно име "correlation name". Фактически, това е някакъв синоним на име на таблица, който може да се използва в другите раздели на табличния израз за указател към реда именно на това вхождение на таблицата.

Ако табличен израз съдържа само раздел FROM (това е единственият задължителен раздел на табличния израз), то резултатът на табличния израз съвпада с резултата от раздела FROM.


15.2.2. Раздел WHERE

Ако в табличен израз присъствува раздел WHERE, то следващия, който се изчислява е той. Синтаксисът на раздела WHERE е следният:

::= WHERE

::=

( OR



::=

( AND



::= [NOT]

::=
| ()

Изчисляването на раздела WHERE се извършва по следните правила: Нека R е резултатът от изчислението на раздела FROM. Тогава условието за търсене се прилага към всички редове на R, и резултатът от раздела WHERE представлява таблица, състояща се от тези редове на R, за които резултатът от изчислението на условието за търсене е true. Ако условието за избор включва подзаявки, то всяка подзаявка се изчислява за всеки кортеж на таблицата R (в стандарта се използува терминът "effectively" в този смисъл, че резултатът трябва да бъде такъв, както ако всяка подзаявка действително се изчислява отново за всеки кортеж на R).

Ще отбележим, че тъй като SQL/89 допуска наличие в базата от данни на неопределени стойности, то изчисляването на условието за търсене се извършва не в булева, а в тризначна логика със стойности true, false и unknown (неизвестно). За всеки предикат е известно, в какви ситуации той може да поражда значението unknown. Булевите операции AND, OR и NOT работят в тризначна логика по следния начин:

true AND unknown = unknown

unknown AND true = unknown

unknown AND unknown = unknown

true OR unknown = true

unknown OR true = true

unknown OR unknown = unknown

NOT unknown = unknown

Сред предикатите на условието за търсене в съответствие с SQL/89 може да са следните предикати: предикат за сравнение, предикат between, предикат in, предикат like, предикат null, предикат с квантор и предикат exists. Ще отбележим, че във всички реализации на SQL на ефективността на изпълнението на заявка съществено влияе наличието в условието за търсене на прости предикати за сравнение (предикати, задаващи сравнение на стълб от таблицата с константа). Наличието на такива предикати позволява на СУБД да използва индекси при изпълнението на заявката, т.е. да избягва пълното преглеждане на таблица. Макар по принцип езикът SQL да позволява на потребителите да не се грижат за конкретния набор предикати в условието за избор (само те да са синтактически и семантически правилни), при реалното използване на SQL-ориентирани СУБД такива технически детайли си струва да се имат предвид.

Предикат за сравнение

Синтаксисът на предиката за сравнение се определя по следните правила:



::=

{ | }



::=

= | <> | < | > | <= | >=

Чрез "<>" се обозначава операция "неравенство". Аритметичните изрази на лявата и дясната части на предиката за сравнение се строят по общите правила за построяване на аритметични изрази и могат да включват в общия случай имена на стълбове на таблици от раздела FROM и константи. Типовете данни на аритметичните изрази трябва да бъдат сравними (например, ако типът на стълба нa таблица A е от тип символен низ, то предикатът "a = 5" е недопустим).

Ако десният операнд на операцията за сравнение се задава с подзаявка, то допълнителното ограничение е това, че мощността на резултата на подзаявката трябва да бъде не по-голяма от единица. Ако поне един от операндите на операция за сравнение има неопределено значение, или ако десният операнд представлява подзаявка с празен резултат, то значението на предиката за сравнение е равно на unknown.

Ще отбележим, че стойността на аритметичния израз не е определен, ако в неговото изчисление участвува поне едно неопределено значение. Още една важна забележка от стандарта SQL/89: в контекста на GROUP BY, DISTINCT и ORDER BY неопределената стойност играе ролята на специален вид определена стойност, т.е. възможно е, например, образуването на група редове, значението на указания стълб на които е неопределено. За осигуряване на преносимост на приложните програми трябва внимателно да се оценява спецификата на работата с неопределени значения в конкретната СУБД.

Предикат between

Предикатът between има следния синтаксис:



::=

[NOT] BETWEEN AND

Резултатът на "x BETWEEN y AND z" е същият, както резултата на "x >= y AND x <= z". Резултатът на "x NOT BETWEEN y AND z" е същият, както резултата на "NOT (x BETWEEN y AND z)".

Предикат in

Предикатът in се определя по следните синтактични правила:



::=

[NOT] IN

{ | ()}



::=

{,}...

Типовете на левия операнд и стойностите от списъка на десния операнд (ще напомним, че резултиращата таблица на подзаявка трябва да съдържа точно един стълб) трябва да са сравними.

Стойността на предиката е равна на true тогава и само тогава, когато значението на левия операнд съвпада понеж с една стойност от списъка на десния операнд. Ако списъкът на десния операнд е празен (това може да бъде, ако десният операнд се задава с подзаявка), или значението на "подразбиращия се" предикат за сравнение x = y (където x - значение аритметичния израз на левия операнд) е равно на false за всеки елемент y от списъка на десния операнд, то значението на предиката in е равно на false. В противен случай значението на предиката in е равно на unknown. По определение значението на предиката "x NOT IN S" е равно на значението на предиката "NOT (x IN S)".



Предикат like

Предикатът like има следния синтаксис:



::=

[NOT] LIKE

[ESCAPE ]


::=



::=

Типовете данни на стълба на левия операнд и образеца трябва да бъдат типове символни низове. В раздела ESCAPE трябва да е специфициран един символ.

Значението на предиката е равно на true, ако pattern представлява подниз на зададен стълб. При това, ако разделът ESCAPE отсъства, то при съпоставянето на шаблона с низа се извършва специална интерпретация на два символа на шаблона: символът за подчертаване ("_") обозначава произволен единичен символ; символ процент ("%") обозначава последователност от произволни символи с произволна дължина (може да бъде нулева).

Ако разделът ESCAPE присъствува и специфицира някакъв единичен символ x, то двойките символи "x_" и "x%" представляват единичните символи "_" и "%" съответно.

Значението на предиката like е unknown, ако стойността на стълба, или шаблона не е определена.

Стойността на предиката "x NOT LIKE y ESCAPE z" съвпада със значението "NOT x LIKE y ESCAPE z".



Предикат null

Предикатът null се описва със синтактичното правило:



::=

IS [NOT] NULL

Този предикат винаги приема стойности true или false. При това значението на "x IS NULL" е равно на true тогаво и само тогава, когато стойността на x е неопределена. Значението на предиката "x NOT IS NULL" е равно на значението на "NOT x IS NULL".



Предикат с квантор

Предикат с квантор има следния синтаксис:



::=



::=

|

::= ALL

::= SOME | ANY

Да обозначим с x резултатът от изчислението на аритметичния израз на лявата част на предиката, а с S резултатът от изчислението на подзаявката.

Предикатът "x ALL S" има значение true, ако S е празно или значението на предиката "x s" е равно на true за всяко s, входящо в S. Предикатът "x ALL S" има стойност false, ако значението на предиката "x s" е равно на false за поне едно s, входящо в S. В останалите случаи значението на предиката "x ALL S" е равно на unknown.

Предикатът "x SOME S" има стойност false, ако S е празно или значението на предиката "x s" е равно на false за всяко s, входящо в S. Предикатът "x SOME S" има значение true, ако значението на предиката "x s" е равно на true поне за едно s, входящо в S. В останалите случаи значението на предиката "x SOME S" е равно на unknown.



Предикат exists

Предикат exists имеет следующий синтаксис:



::=

EXISTS

Значението на този предикат винаги е true или false, и това значение е равно на true тогава и само тогава, когато резултатът от изчислението на подзаявката не е празен.

15.2.3. Раздел GROUP BY

Ако в табличном выражении присутствует раздел GROUP BY, то следующим изпълнявася он. Синтаксис раздела GROUP BY следующий:

::=

GROUP BY

[{,}...]

Ако обозначим с R таблицата, представляваща резултата от предишен раздел (FROM или WHERE), то резултатът от раздела GROUP BY представлява разбиване на R на множество от групи редове, състоящо се от минимален брой групи такива, че за всеки стълб от списъка стълбове на раздела GROUP BY във всички редове на всяка група, включва повече от един ред, значенията на този стълб са равни. За обозначаване на резултата от раздела GROUP BY в стандарта се използува терминът "групирана таблица".


15.2.4. Раздел HAVING

Накрая, последен при изчисляване на табличен израз се използува разделът HAVING (ако той присуствува). Синтаксисът на този раздел е следния:

::=

HAVING

Разделът HAVING може смислено да се появи в табличния израз само в този случай, когато в него присъствува разделът GROUP BY. Условието за търсене на този раздел задава условие върху група редове от групирана таблица. Формално разделът HAVING може да присъствува и в табличен израз, несъдържащ GROUP BY. В този случай се предполага, че резултатът от изчислението на предишните раздели представлява групиранa таблицa, състояща се от една група без отделени стълбове за групиране.

Условието за търсене на раздела HAVING се строи по същите синтактични правила, както и условието за търсене на раздела WHERE, и може да включва същите предикати. Но има специални синтактични ограничения по частта използване в условието за търсене на спецификациите на стълбовете на таблиците из раздела FROM на даден табличен израз. Тези ограничения следват от това, че условието за търсене на раздела HAVING задава условие върху цяла група, а не върху индивидуални редове.

Затова в аритметичните изрази на предикатите, влизащи в условието за избор на раздела HAVING, директно може да се използуват само спецификации на стълбовете, указани в качеството на стълбове за групиране в раздела GROUP BY. Останалите стълбове може да се специфицират само вътре в спецификациите на агрегатните функции COUNT, SUM, AVG, MIN и MAX, изчисляващи в дадения случай някакво агрегатно значение за цяла група редове. Аналогично стоят нещата с подзаявките, входящи в предикати на условие за избор на раздела HAVING: ако в подзаявката се използува характеристика на текущата група, то тя може да се задава само чрез връзки към стълбове групиране.

Резултатът от изпълнението на раздела HAVING е групирана таблица, съдържаща само тези групи редове, за които резултатът от изчислението на условието за търсене е true. В частност, ако разделът HAVING присъствува в табличен израз, несъдържащ GROUP BY, то резултата от неговото изпълнение ще е или празна таблица, или резултата от изпълнението на предишните раздели на табличния израз, разглеждан като една група без стълбове за групиране.


15.3. Агрегатни функции и резултати от заявки


Агрегатните функции (в стандарта SQL/89 те се наричат функции над множества) се определят в SQL/89 по следните синтактични правила:

::=

COUNT(*) |

|

::=

{ AVG | MAX | MIN | SUM | COUNT }

(DISTNICT )

::=

{ AVG | MAX | MIN | SUM } ([ALL] )

Както се вижда от тези правила, в стандарта SQL/89 са определени пет стандартни агрегатни функции: COUNT – брой редове или значения, MAX – максимална стойност, MIN – минимална стойност, SUM – сумарно значение и AVG - средна стойност.

15.3.1. Семантика нa агрегатните функции

Агрегатните функции са предназначени за изчисляване на някакво значение върху зададено множество редове. Такова множество редове може да бъде група редове, ако агрегатната функция се прилага към групирана таблица, или цялата таблица. За всички агрегатни функции, освен COUNT(*), фактическият (т.е. изискваният от семантиката) ред на изчисленията е следния: на основание параметрите на агрегатната функция от зададено множество редове се съставя списък стойности. След това по този списък съ значения се извършва изчислението на функцията. Ако списъкът се оказва празен, то стойността на функцията COUNT за него е 0, а значението на всички останали функции - null.

Нека T да обозначава типа на стойностите от този списък. Тогава резултатът от изчислението на функцията COUNT е точно число с масщаб и точност, определяеми в реализацията. Типът на резултата на значенията на функцията MAX и MIN съвпада с T. При изчислението на функциите SUM и AVG типът T не трябва да е символен низ, а типът на резултата на функцията – това е тип точни числа с определяеми в реализацията мащаб и точност, ако T е тип на точни числа, и тип на приблизителни числа с определяема в реализацията точност, ако T е тип на приблизителните числа.

Изчислението на функцията COUNT(*) се извършва чрез преброяване броя на редовете в дадено множество. Всички редове се смятат за различни, даже и ако те се състоят от един стълб със значение null във всички редове.

Ако агрегатната функция е специфицирана с ключова дума DISTINCT, то списъкът значения се строит от значенията на указания стълб. (Ще подчертаем, че в този случай не се допуска изчисление на аритметични изрази!) По-нататък от този списък се премахват неопределените значения, и в него се отстраняват значения-дубликати. След това се изчислява указаната функция.

Ако агрегатната функция е специфицирана без ключова дума DISTINCT (или с ключова дума ALL), то списъкът значения се формира от значенията на аритметичния израз, изчисляван за всеки ред от задано множествао. По-нататък от списъка се изтриват неопределените значения, и се извършва изчисление на агрегатната функция. Обърнете внимание, че в този случай не се допуска използването на функцията COUNT!

Двете ограничения, указанные в двата предишни абзаца са по-скоро технически, отколкото принципиални, и могат да отсъствуват в конкретните реализации. Все пак, това са ограничения на стандарта SQL/89, и трябва да се придержаме към тях при мобилното програмиране.


15.3.2. Резултати от заявки

Агрегатните функции може разумно да се използуват в спецификация на курсор, оператор за избор и в подзаявка след ключовата дума SELECT (ще наричаме в този подраздел всички такива конструкции списъкза избор, без да забравяме за това, че в случай на подзаявка този списък се състои само от един елемент), и в условията на извадката на раздела HAVING. Стандартът изпуска повечето екзотически използвания на агрегатните функции в подзаявките (агрегатна функция върху група кортежи на външна заявка), но на практика те се срещат много рядко.

Ще разгледаме различни случаи на приложение на агрегатните функции в списъка за изборк в зависимост от вида на табличния израз.

Ако резултатът от табличния израз R не е групирана таблица, то появата на поне една агрегатна функция от множество редове R в списъка за избор води до това, че R неявно се разглежда като групирана таблица, състояща се от една (или нула) групи с отсъствуващи стълбове за групиране. Затова в този случай в списъка за избор не се допуска прякото използване на спецификации на редовете на R: всички те трябва да се намират вътре в спецификациите на агрегатните функции. Резултатът от заявката представлява таблица, състояща се от не повече от един ред, получен чрез прилагането на агрегатни функции към R.

Аналогични са нещата в случая, когато R представлява групирана таблица, но табличния израз не съдържа раздел GROUP BY (и, следователно, съдържа раздел HAVING). Ако в случая в предишния абзац имаше два варианта за формиране на списък за избор: само с пряко указване на стълбовете на R или само с указването им вътре в спецификациите на агрегатните функции, то в дадения случай е възможен само втория вариант. Резултатът от табличния израз явно е обявен чрез групирана таблица, състояща се от една група, и резултатът от заявката може да се формира само чрез прилагане на агрегатни функции към тази група редове. Отново резултатът от заявката се представя с таблица, състояща се от не повече от един ред, получен чрез прилагане на агрегатни функции към R.

Накрая, ще разгледаме случая, когато R представлява "истинска" групирана таблица, т.е. табличният израз съдържа раздел GROUP BY и, следователно е определен поне един стълб за групиране. В този случай правилата за формиране на списъка за избор напълно съответствува на правилата за формиране на условието за избор в раздела HAVING: допуска пряко използване на спецификацията на стълбовете за групиране, а спецификациите на останалите стълбове на R могат да се появяват само вътре в спецификациите на агрегатните функции. Резултатът от заявката представлява таблица, броят на редовете в която е равен на броя на групите в R, и всеки ред се формира на основата на значенията на стълбовете за групиране и агрегатните функций за дадената група.


Каталог: tadmin -> upload -> storage
storage -> Литература на факта. Аналитизъм. Интерпретативни стратегии. Въпроси и задачи
storage -> Лекция №2 Същност на цифровите изображения Въпрос. Основни положения от теория на сигналите
storage -> Лекция 5 система за вторична радиолокация
storage -> Толерантност и етничност в медийния дискурс
storage -> Ethnicity and tolerance in media discourse revisited Desislava St. Cheshmedzhieva-Stoycheva abstract
storage -> Тест №1 Отбележете невярното твърдение за подчертаните думи
storage -> Лекции по Въведение в статистиката
storage -> Търсене на живот във вселената увод
storage -> Еп. Константинови четения – 2010 г някои аспекти на концептуализация на богатството в руски и турски език

Изтегляне 1.71 Mb.

Сподели с приятели:
1   ...   7   8   9   10   11   12   13   14   ...   17




©obuch.info 2024
отнасят до администрацията

    Начална страница