Тарифы Услуги Сим-карты

Команды SQL-запросов. Как составлять SQL-запросы - подробные примеры

SQL - один из самых распространенных языков программирования, для создания и управления базой данных, а также для проведения разнообразных действий с самими данными.

Как показывает практика, он довольно простой в освоении и максимально использует стандартную лексику английского языка. Как и любой другой язык программирования, SQL имеет собственную логику и синтаксис, набор основных команд и правила их использования.

Классификация команд языка SQL

Все стандартные можно рассматривать исходя из их назначения. Как основу внегласной классификации можно взять такие наборы, как:

    Команды для построения запросов.

    Команды встроенных процедур и функций.

    Команды триггеров и системных таблиц.

    Наборы комбинаций для работы с датой и строковыми переменными.

    Команды для работы с данными и таблицами.

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

Рассматривая классификацию языка, нельзя не упомянуть о том, что он является универсальным, о чем говорит сфера его использования. Этот язык программирования и его разновидности задействуются не только в стандартной среде, но и в других программах, которые, так или иначе, вы использовали.

Сферу использования SQL можно рассматривать с точки зрения офисного программного обеспечения, а именно MicrosoftAccess. Этот язык, а точнее, его разновидность — MySQL, позволяет администрировать базы данных в сети Internet. Даже среда разработки Oracle использует в основе своих запросов команды SQL.

Использование SQL в MicrosoftAccess

Одним из самых простых примеров использования языка для программирования баз данных считается пакет программного обеспечения MicrosoftOffice. Изучение этого программного продукта предусмотрено школьным курсом информатики, а в одиннадцатом классе рассматривается система управления базой данных MicrosoftAccess.

Именно при изучении этого приложения ученики знакомятся с языком разработки баз данных и получают базовое понимание всего в него входящего. SQL команды Access довольно примитивны, конечно же, если рассматривать их на профессиональном уровне. Выполнение таких команд очень простое, а создаются они в приспособленном редакторе кода.

Рассмотрим конкретный пример:

SELECT Pe_SurName

WHERE Pe_Name = "Мэри";

Исходя из синтаксиса команды можно понять, что она вернет пользователю фамилию человека, в данном случае женщины по имени Мэри, которая хранится в таблице базы данных Contacts.

Хоть и использование SQL в Access ограничено, иногда такие простые запросы очень сильно могут упростить выполнение поставленного задания.

Использование команд SQL в Oracle

Oracle - это, наверное, единственный серьезный конкурент Microsoft SQL Server. Именно данная среда разработки и управления постоянно приводит к совершенствованию функций программного продукта компании Microsoft, так как конкуренция - это двигатель прогресса. Несмотря на постоянное соперничество, команды SQL Oracle повторяют SQL. Стоит отметить, что хоть Oracle и считается практически полной копией SQL, логика этой системы и языка в целом считается проще.

Система Oracle при использовании определенного набора команд не имеет такой сложной структуры. Если рассматривать возможности данных сред разработки баз данных, Oracle не имеет сложной структуры вложенных запросов.

Такая разница позволяет во много раз ускорить работу с данными, но, в противовес, ведет к нерациональному использованию памяти, в некоторых отдельных случаях. Структура Oracle в основном построена на временных таблицах и их использовании. Как пример: команды SQL в данной системе строятся по аналогии со стандартами самого языка SQL, хотя незначительно и отличаются от него.

SELECTCONCAT(CONCAT(CONCAT(‘Сотрудник ‘, sname), CONCAT(SUBSTR(fname, 0, 1), SUBSTR(otch, 0, 1))), CONCAT(‘принятнаработу ‘, acceptdate)) FROM employees WHERE acceptdate > to_date(‘01.01.80′,’dd.mm.yyyy’);

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

Использование SQL в сети Internet

С появлением всемирной паутины, то есть интернета, сфера использования языка SQL расширяется. Как известно, в сети хранится масса информации, но она не хаотично расположена, а размещена на сайтах и серверах по определенным критериям.

За хранение информации в Интернете, как и в других местах, отвечают непосредственно базы данных, а сайты являются системами управления. Как правило, сайты и их программный код организованы на разных языках программирования, но в основе баз данных лежит одна из разновидностей SQL, а именно язык создания баз данных, ориентированный под веб-интерфейсы MySQL.

Синтаксис и основной набор команд этого языка полностью копируют привычный всем SQL, но с некоторыми своими дополнениями, которые и дают ему отличие от Microsoft tSQL Server.

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

$link = mysqli_connect("localhost", "root", "", "tester");

if (!$link) die("Error");

$query = "create table users(

login VARCHAR(20),

password VARCHAR(20)

if (mysqli_query($link, $query)) echo "Таблица создана.";

elseecho "Таблица не создана: ".mysqli_error();

mysqli_close($link);

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

Синтаксис изменен под Вэб, но в основу положены команды MicrosoftSQLServer.

Построение запросов MicrosoftSQLServer

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

Правила построение команды очень просты, а сама команда select в SQL строится следующим образом. К примеру, есть таблица, в которой имеются данные о сотруднике, которая, к примеру, имеет имя Person. Поставим задачу, что из таблицы нужно выбрать данные о сотрудниках, дата рождения которых - в промежутке от первого января до первого марта текущего года включительно. Для такой выборки необходимо выполнить команду SQL, в которой будет не только стандартная конструкция, но и условие выбора:

Select * from Person

Where P_BerthDay >= ‘01/01/2016’ and P_BerthDay<= ‘03/01/2016’

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

SelectP_Name - имя

P_SurName - фамилия

P_Patronimic - отчество

Where P_BerthDay >= ‘01/01/2016’ and P_BerthDay<= ‘03/01/2016’

Однако это всего лишь выбор чего-либо. Он, по сути своей, не влияет ни на что, а лишь предоставляет информацию. Но если вы решили заняться языком SQL всерьез, вам придется научится вносить изменения в базы данных, так как их построение без этого попросту невозможно. Как это делается, будет рассмотрено чуть ниже.

Основные команды SQL для изменения данных

Синтаксис языка построен не только для выполнения запросов, но и для манипуляций с данными. В основном задачей программиста баз данных является написание скриптов для выборок и отчетов, но иногда необходимо вносить правки в таблицы. Список команд SQL для таких действий невелик и состоит из трех основных команд:

    Insert (пер. Вставить).

    Update (пер. Обновление).

    Delete (пер. Удалить).

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

Как правило, перед использованием такие MSSQL команды нужно продумать, и учесть все возможные последствия их выполнения.

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

Команда Insert

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

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

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

Insert into person

Select ‘Григорьев’,’Виталий’,’Петрович’,’01/01/1988’

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

Insertintoperson(P_Name, P_SurName ,P_BerthDay)

Values (‘Дэвид’, ‘Гук’,’02/11/1986’)

Такая команда заполнит только указанные ячейки, а все остальные будут иметь значение null.

Команда для изменения данных

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

Команда Update SQL имеет несложный синтаксис. Для правильного использования необходимо указать, какие данные, в какой колонке и в какой записи стоит изменить. Далее составить скрипт и выполнить его. Рассмотрим пример. Нужно изменить дату рождения Дэвида Гука, который внесен в таблицу сотрудников под номером 5.

Set P_BerthDay = ’02/10/1986’ where P_ID = 5

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

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

Команды для использования встроенных процедур и функций

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

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

Предположим, что была создана процедура для вывода даты рождения сотрудников с ранее описанной таблицы Person. В таком случае нет необходимости писать весь запрос. Для получения необходимой информации достаточно выполнить команду Exec [имя процедуры] и передать необходимые для выборки параметры. Как пример можно рассмотреть механизм создания процедуры такого характера:

CREATEPROCEDUREPrintPerson

@DB smalldatetime

@DE smalldatetime

SELECT * from Person

FROM HumanResources.vEmployeeDepartmentHistory

WHERE P_BerthDay >= @DB and P_BerthDay <= @DE

ANDEndDateISNULL;

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

Организация целостности данных. Триггеры

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

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

Типы команд SQL, которые можно использовать в триггере, не ограничены. Рассмотрим на примере.

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

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

Указываем, для какой операции с данными (в нашем случае это операция изменения данных).

Следующим шагом будет указание таблиц и переменных:

declare @ID int. @Date smalldatetime @nID int. @nDatesmalldatetime

DEclare cursor C1 for select P_ID, P_BerthDay from Inserted

DEclare cursor C2 for select P_ID, P_BerthDay from deleted

Задаем шаги выбора данных. После, в теле курсоров прописываем условие и реакцию на него:

if @ID = @nID and @nDate = "01/01/2016"

sMasseges "Выполнить операцию невозможно. Дата не подходит"

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

altertablePERSONdisabletriggerall - для отключения всех триггеров, созданных для данной таблицы, и, соответственно, altertablePERSONenabletriggerall - для их включения.

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

Вывод

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

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

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

Типы данных SQL (Как в Pg , как в стандарте)

Строковые типы

Числовые типы данных

Денежные, Символьные, Двоичные типы данных

Логический тип. Перечисления

Примеры простейших SQL-запросов

Простейшие SELECT-запросы

Оператор SELECT (выбрать) языка SQL является самым важным и самым часто используемым оператором. Он предназначен для выборки информации из таблиц базы данных. Упрощенный синтаксис оператора SELECT выглядит следующим образом.

SELECT [ ALL | DISTINCT ] select_item_commalist

FROM table_reference_commalist

[ WHERE conditional_expression ]

[ GROUP BY column_name_commalist ]

[ HAVING conditional_expression ]

[ ORDER BY order_item_commalist ]

В квадратных скобках указаны элементы, которые могут отсутствовать в запросе.

Ключевое слово SELECT сообщает базе данных, что данное предложение является запросом на извлечение информации.

После слова SELECT через запятую перечисляются наименования полей (список атрибутов), содержимое которых запрашивается.

Обязательным ключевым словом в предложении-запросе SELECT является слово FROM (из). За ключевым словом FROM указывается список разделенных запятыми имен таблиц, из ко-торых извлекается информация.

Например, select title, description from film

Любой SQL-запрос должен заканчиваться символом «;» (точка с запятой). Результатом данного запроса будет таблица...

Порядок следования столбцов в этой таблице соответствует порядку полей, указанному в запросе

Если необходимо вывести значения всех, столбцов таблицы, то можно вместо перечисления их имен использовать символ «*» (звездочка).

SELECT * FROM film;

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

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

Например, запрос «список имен актеров», можно записать в следующем виде.

select first_name from actor;

Его результатом будет таблица, в таблице встречаются одинаковые строки. Для исключения из результата SELECT-запроса повторяющихся записей используется ключевое слово DISTINCT (отличный).

Если запрос SELECT извлекает множество полей, то DISTINCT исключает дубликаты строк, в которых значения всех выбранных полей идентичны.

Предыдущий запрос можно записать в следующем виде.

select distinct first_name from actor;

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

Ключевое слово ALL (все), в отличие от DISTINCT, оказывает противоположное действие, то есть при его использовании повторяющиеся строки включаются в состав выходных данных. Режим, задаваемый ключевым словом ALL, действует по умолчанию, поэтому в реальных запросах для этих целей оно практически не используется.

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

Пример: Написать запрос, выполняющий выборку фамилий всех актеров с именем PENELOPE

select last_name from actor

where first_name="PENELOPE";

В задаваемых в предложении WHERE условиях могут использоваться операции сравнения, определяемые операторами = (равно), > (больше), < (меньше), >= (больше или равно), <- (меньше или равно), <> (не равно), а также логические операторы AND, OR И NOT.

Например, запрос для получения названий и описаний фильмов - короткометражек (короче 60 мин), прокат которых стоит меньше 3$ , будет выглядеть таким образом:

select title, description from film

where length < 60 and rental_rate < 3

Результат выполнения этого запроса имеет вид:

rental - прокат

inventory - опись, запасы

store- запас, магазин

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

Все эти функции возвращают единственное значение. При этом функции COUNT, MIN и MAX применимы к любым типам данных, в то время как SUM и AVG используются только для числовых полей. Разница между функцией COUNT(*) и COUNT(<имя поля>) состоит в том, что вторая при подсчете не учитывает NULL-значения.

Пример. Найти минимальную и максимальную цену на персональные компьютеры:

Пример. Найти имеющееся в наличии количество компьютеров, выпущенных производителем А:

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

Пример. Найти количество имеющихся различных моделей, выпускаемых производителем А. Запрос похож на предыдущий, в котором требовалось определить общее число моделей, выпускаемых производителем А. Здесь же требуется найти число различных моделей в таблице PC (т.е. имеющихся в продаже).

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

Если же нам требуется получить количество моделей ПК, производимых каждым производителем, то потребуется использовать предложение GROUP BY , синтаксически следующего после предложения WHERE .

Предложение GROUP BY

Предложение GROUP BY используется для определения групп выходных строк, к которым могут применяться агрегатные функции (COUNT, MIN, MAX, AVG и SUM) . Если это предложение отсутствует, и используются агрегатные функции, то все столбцы с именами, упомянутыми в SELECT , должны быть включены в агрегатные функции , и эти функции будут применяться ко всему набору строк, которые удовлетворяют предикату запроса. В противном случае все столбцы списка SELECT, не вошедшие в агрегатные функции, должны быть указаны в предложении GROUP BY . В результате чего все выходные строки запроса разбиваются на группы, характеризуемые одинаковыми комбинациями значений в этих столбцах. После этого к каждой группе будут применены агрегатные функции. Следует иметь в виду, что для GROUP BY все значения NULL трактуются как равные, т.е. при группировке по полю, содержащему NULL-значения, все такие строки попадут в одну группу.
Если при наличии предложения GROUP BY , в предложении SELECT отсутствуют агрегатные функции , то запрос просто вернет по одной строке из каждой группы. Эту возможность, наряду с ключевым словом DISTINCT, можно использовать для исключения дубликатов строк в результирующем наборе.
Рассмотрим простой пример:
SELECT model, COUNT(model) AS Qty_model, AVG(price) AS Avg_price
FROM PC
GROUP BY model;

В этом запросе для каждой модели ПК определяется их количество и средняя стоимость. Все строки с одинаковыми значениями model (номер модели) образуют группу, и на выходе SELECT вычисляются количество значений и средние значения цены для каждой группы. Результатом выполнения запроса будет следующая таблица:
model Qty_model Avg_price
1121 3 850.0
1232 4 425.0
1233 3 843.33333333333337
1260 1 350.0

Если бы в SELECT присутствовал столбец с датой, то можно было бы вычислять эти показатели для каждой конкретной даты. Для этого нужно добавить дату в качестве группирующего столбца, и тогда агрегатные функции вычислялись бы для каждой комбинации значений (модель−дата).

Существует несколько определенных правил выполнения агрегатных функций :

  • Если в результате выполнения запроса не получено ни одной строки (или не одной строки для данной группы), то исходные данные для вычисления любой из агрегатных функций отсутствуют. В этом случае результатом выполнения функций COUNT будет нуль, а результатом всех других функций - NULL.
  • Аргумент агрегатной функции не может сам содержать агрегатные функции (функция от функции). Т.е. в одном запросе нельзя, скажем, получить максимум средних значений.
  • Результат выполнения функции COUNT есть целое число (INTEGER). Другие агрегатные функции наследуют типы данных обрабатываемых значений.
  • Если при выполнении функции SUM был получен результат, превышающий максимальное значение используемого типа данных, возникает ошибка .

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

Предложение HAVING

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

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

    производные таблицы;

    обобщенные табличные выражения.

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

Производные таблицы

Производная таблица (derived table) - это табличное выражение, входящее в предложение FROM запроса. Производные таблицы можно применять в тех случаях, когда использование псевдонимов столбцов не представляется возможным, поскольку транслятор SQL обрабатывает другое предложение до того, как псевдоним станет известным. В примере ниже показана попытка использовать псевдоним столбца в ситуации, когда другое предложение обрабатывается до того, как станет известным псевдоним:

USE SampleDb; SELECT MONTH(EnterDate) as enter_month FROM Works_on GROUP BY enter_month;

Попытка выполнить этот запрос выдаст следующее сообщение об ошибке:

Msg 207, Level 16, State 1, Line 5 Invalid column name "enter_month". (Сообщение 207: уровень 16, состояние 1, строка 5 Недопустимое имя столбца enter_month)

Причиной ошибки является то обстоятельство, что предложение GROUP BY обрабатывается до обработки соответствующего списка инструкции SELECT, и при обработке этой группы псевдоним столбца enter_month неизвестен.

Эту проблему можно решить, используя производную таблицу, содержащую предшествующий запрос (без предложения GROUP BY), поскольку предложение FROM исполняется перед предложением GROUP BY:

USE SampleDb; SELECT enter_month FROM (SELECT MONTH(EnterDate) as enter_month FROM Works_on) AS m GROUP BY enter_month;

Результат выполнения этого запроса будет таким:

Обычно табличное выражение можно разместить в любом месте инструкции SELECT, где может появиться имя таблицы. (Результатом табличного выражения всегда является таблица или, в особых случаях, выражение.) В примере ниже показывается использование табличного выражения в списке выбора инструкции SELECT:

Результат выполнения этого запроса:

Обобщенные табличные выражения

Обобщенным табличным выражением (OTB) (Common Table Expression - сокращенно CTE) называется именованное табличное выражение, поддерживаемое языком Transact-SQL. Обобщенные табличные выражения используются в следующих двух типах запросов:

    нерекурсивных;

    рекурсивных.

Эти два типа запросов рассматриваются в следующих далее разделах.

OTB и нерекурсивные запросы

Нерекурсивную форму OTB можно использовать в качестве альтернативы производным таблицам и представлениям. Обычно OTB определяется посредством предложения WITH и дополнительного запроса, который ссылается на имя, используемое в предложении WITH. В языке Transact-SQL значение ключевого слова WITH неоднозначно. Чтобы избежать неопределенности, инструкцию, предшествующую оператору WITH, следует завершать точкой с запятой.

USE AdventureWorks2012; SELECT SalesOrderID FROM Sales.SalesOrderHeader WHERE TotalDue > (SELECT AVG(TotalDue) FROM Sales.SalesOrderHeader WHERE YEAR(OrderDate) = "2005") AND Freight > (SELECT AVG(TotalDue) FROM Sales.SalesOrderHeader WHERE YEAR(OrderDate) = "2005")/2.5;

Запрос в этом примере выбирает заказы, чьи общие суммы налогов (TotalDue) большие, чем среднее значение по всем налогам, и плата за перевозку (Freight) которых больше чем 40% среднего значения налогов. Основным свойством этого запроса является его объемистость, поскольку вложенный запрос требуется писать дважды. Одним из возможных способов уменьшить объем конструкции запроса будет создать представление, содержащее вложенный запрос. Но это решение несколько сложно, поскольку требует создания представления, а потом его удаления после окончания выполнения запроса. Лучшим подходом будет создать OTB. В примере ниже показывается использование нерекурсивного OTB, которое сокращает определение запроса, приведенного выше:

USE AdventureWorks2012; WITH price_calc(year_2005) AS (SELECT AVG(TotalDue) FROM Sales.SalesOrderHeader WHERE YEAR(OrderDate) = "2005") SELECT SalesOrderID FROM Sales.SalesOrderHeader WHERE TotalDue > (SELECT year_2005 FROM price_calc) AND Freight > (SELECT year_2005 FROM price_calc)/2.5;

Синтаксис предложения WITH в нерекурсивных запросах имеет следующий вид:

Параметр cte_name представляет имя OTB, которое определяет результирующую таблицу, а параметр column_list - список столбцов табличного выражения. (В примере выше OTB называется price_calc и имеет один столбец - year_2005.) Параметр inner_query представляет инструкцию SELECT, которая определяет результирующий набор соответствующего табличного выражения. После этого определенное табличное выражение можно использовать во внешнем запросе outer_query. (Внешний запрос в примере выше использует OTB price_calc и ее столбец year_2005, чтобы упростить употребляющийся дважды вложенный запрос.)

OTB и рекурсивные запросы

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

Параметры cte_name и column_list имеют такое же значение, как и в OTB для нерекурсивных запросов. Тело предложения WITH состоит из двух запросов, объединенных оператором UNION ALL . Первый запрос вызывается только один раз, и он начинает накапливать результат рекурсии. Первый операнд оператора UNION ALL не ссылается на OTB. Этот запрос называется опорным запросом или источником.

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

Оператор UNION ALL соединяет накопившиеся на данный момент строки, а также дополнительные строки, добавленные текущим вызовом рекурсивного члена. (Наличие оператора UNION ALL означает, что повторяющиеся строки не будут удалены из результата.)

Наконец, параметр outer_query определяет внешний запрос, который использует OTB для получения всех вызовов объединения обеих членов.

Для демонстрации рекурсивной формы OTB мы используем таблицу Airplane, определенную и заполненную кодом, показанным в примере ниже:

USE SampleDb; CREATE TABLE Airplane (ContainingAssembly VARCHAR(10), ContainedAssembly VARCHAR(10), QuantityContained INT, UnitCost DECIMAL (6,2)); INSERT INTO Airplane VALUES ("Самолет", "Фюзеляж",1, 10); INSERT INTO Airplane VALUES ("Самолет", "Крылья", 1, 11); INSERT INTO Airplane VALUES ("Самолет", "Хвост",1, 12); INSERT INTO Airplane VALUES ("Фюзеляж", "Салон", 1, 13); INSERT INTO Airplane VALUES ("Фюзеляж", "Кабина", 1, 14); INSERT INTO Airplane VALUES ("Фюзеляж", "Нос",1, 15); INSERT INTO Airplane VALUES ("Салон", NULL, 1,13); INSERT INTO Airplane VALUES ("Кабина", NULL, 1, 14); INSERT INTO Airplane VALUES ("Нос", NULL, 1, 15); INSERT INTO Airplane VALUES ("Крылья", NULL,2, 11); INSERT INTO Airplane VALUES ("Хвост", NULL, 1, 12);

Таблица Airplane состоит из четырех столбцов. Столбец ContainingAssembly определяет сборку, а столбец ContainedAssembly - части (одна за другой), которые составляют соответствующую сборку. На рисунке ниже приведена графическая иллюстрация возможного вида самолета и его составляющих частей:

Таблица Airplane состоит из следующих 11 строк:

В примере ниже показано применение предложения WITH для определения запроса, который вычисляет общую стоимость каждой сборки:

USE SampleDb; WITH list_of_parts(assembly1, quantity, cost) AS (SELECT ContainingAssembly, QuantityContained, UnitCost FROM Airplane WHERE ContainedAssembly IS NULL UNION ALL SELECT a.ContainingAssembly, a.QuantityContained, CAST(l.quantity * l.cost AS DECIMAL(6,2)) FROM list_of_parts l, Airplane a WHERE l.assembly1 = a.ContainedAssembly) SELECT assembly1 "Деталь", quantity "Кол-во", cost "Цена" FROM list_of_parts;

Предложение WITH определяет список OTB с именем list_of_parts, состоящий из трех столбцов: assembly1, quantity и cost. Первая инструкция SELECT в примере вызывается только один раз, чтобы сохранить результаты первого шага процесса рекурсии. Инструкция SELECT в последней строке примера отображает следующий результат.

Каждый веб-разработчик должен знать SQL, чтобы писать запросы к базам данных. И, хотя, phpMyAdmin никто не отменял, зачастую необходимо испачкать руки, чтобы написать низкоуровневый SQL.

Именно поэтому мы подготовили краткий экскурс по основам SQL. Начнем же!

1. Создание таблицы

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

Создадим простую таблицу по имени month . Она состоит из 3 колонок:

  • id – Номер месяца в календарном году (целое число).
  • name – Название месяца (строка, максимум 10 символов).
  • days – Количество дней в этом месяце (целое число).

Вот как будет выглядеть соответствующий SQL запрос:

CREATE TABLE months (id int, name varchar(10), days int);

Также при создании таблиц целесообразно добавить первичный ключ для одной из колонок. Это позволит держать записи уникальными и ускорит запросы на выборку. Пусть в нашем случае уникальным будет название месяца (столбец name )

CREATE TABLE months (id int, name varchar(10), days int, PRIMARY KEY (name));

Дата и время
Тип данных Описание
DATE Значения даты
DATETIME Значения даты и времени с точностью до минты
TIME Значения времени

2. Вставка строк

Теперь давайте заполнять нашу таблицу months полезной информацией. Добавление записей в таблицу производится через инструкцию INSERT . Есть два способа записи этой инструкции.

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

Этот способ записи прост, но небезопасен, поскольку нет гарантии, что по мере расширения проекта и редактировании таблицы, столбцы будут располагаться в том же порядке, что и ранее. Безопасный (и в тоже время более громоздкий) способ записи инструкции INSERT требует указания как значений, так и порядка следования столбцов:

Здесь первое значение в списке VALUES соответствует первому указанному имени столбца и т.д.

3. Извлечение данных из таблиц

Инструкция SELECT - наш лучший друг, когда мы хотим получить данные из базы данных. Она используется очень часто, так что отнеситесь к этому разделу очень внимательно.

Самый простое использование инструкции SELECT - запрос, который возвращает все столбцы и строки из таблицы (например, таблицы по имени characters ):

SELECT * FROM "characters"

Символ звездочка (*) означает, что мы хотим получить данные из всех столбцов. Так базы данных SQL обычно состоят из более чем одной таблицы, то требуется обязательно указывать ключевое слово FROM , следом за которым через пробел должно следовать название таблицы.

Иногда мы не хотим получить данные не из всех столбцов в таблице. Для этого, вместо звездочки (*) мы должны через запятую записать имена желаемых столбцов.

SELECT id, name FROM month

Кроме того, во многих случаях мы хотим, чтобы полученные результаты были отсортированы в определенном порядке. В SQL мы делаем это с помощью ORDER BY . Он может принимать опциональный модификатор – ASC (по-умолчанию) сортирующий по возрастанию или DESC , сортирующий по убыванию:

SELECT id, name FROM month ORDER BY name DESC

При использовании ORDER BY убедитесь, что оно будет последним в инструкции SELECT . В противном случае будет выдано сообщение об ошибке.

4. Фильтрация данных

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

В этом запросе мы выбираем только те месяцы из таблицы month , в которых больше 30 дней с помощью оператора больше (>).

SELECT id, name FROM month WHERE days > 30

5. Расширенная фильтрация данных. Операторы AND и OR

Ранее мы использовали фильтрацию данных с использованием одного критерия. Для более сложной фильтрации данных можно использовать операторы AND и OR и операторов сравнения (=,<,>,<=,>=,<>).

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


SELECT * FROM albums WHERE genre = "рок" AND sales_in_millions <= 50 ORDER BY released

6. In/Between/Like

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

  • IN – служит для указания диапазона условий, любое из которых может быть выполнено
  • BETWEEN – проверяет, находится ли значение в указанном диапазоне
  • LIKE – ищет по определенным паттернам

Например, если мы хотим выбрать альбомы с поп и соул музыкой, мы можем использовать IN("value1","value2") .

SELECT * FROM albums WHERE genre IN ("pop","soul");

Если мы хотим получить все альбомы, изданные между 1975 и 1985годами, мы должны записать:

SELECT * FROM albums WHERE released BETWEEN 1975 AND 1985;

7. Функции

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

  • COUNT() – возвращает количество строк
  • SUM() – возвращает общую сумму числового столбца
  • AVG() – возвращает среднее значение из множества значений
  • MIN() / MAX() – получает минимальное / максимальное значение из столбца

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

SELECT MAX(released) FROM albums;

8. Подзапросы

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

Мы знаем, как получить эти конкретные столбцы:

SELECT artist, album, released FROM albums;

Мы также знаем, как получить самый ранний год:

SELECT MIN(released) FROM album;

Все, что нужно сейчас, - это объединить два запроса с помощью WHERE:

SELECT artist,album,released FROM albums WHERE released = (SELECT MIN(released) FROM albums);

9. Объединение таблиц

В более сложных базах данных существует несколько таблиц, связанных друг с другом. Например, ниже представлены две таблицы о видеоиграх (video_games ) и разработчиков видеоигр (game_developers ).


В таблице video_games есть колонка разработчик (developer_id ), но в ней содержится целое число, а не имя разработчика. Это число представляет собой идентификатор (id ) соответствующего разработчика из таблицы разработчиков игр (game_developers ), связывая логически два списка, что позволяет нам использовать информацию, хранящуюся в них обоих одновременно.

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

SELECT video_games.name, video_games.genre, game_developers.name, game_developers.country FROM video_games INNER JOIN game_developers ON video_games.developer_id = game_developers.id;

Это самый простой и наиболее распространенный тип JOIN . Есть несколько других вариантов, но они применимы к менее частым случаям.

10. Алиасы

Если вы посмотрите на предыдущий пример, то вы заметите, что существуют две колонки называемые name . Это сбивает с толку, так что давайте установим псевдоним одного из повторяющихся столбцов, например, name из таблицы game_developers будет называться developer .

Мы также можем сократить запрос задав псевдонимы имен таблиц: video_games назовем games , game_developers - devs :

SELECT games.name, games.genre, devs.name AS developer, devs.country FROM video_games AS games INNER JOIN game_developers AS devs ON games.developer_id = devs.id;

11. Обновление данных

Часто мы должны изменить данные в некоторых строках. В SQL это делается с помощью инструкции UPDATE . Инструкция UPDATE состоит из:

  • Таблицы, в которой находится значение для замены;
  • Имен столбцов и их новых значений;
  • Выбранные с помощью WHERE строки, которые мы хотим обновить. Если этого не сделать, то изменятся все строки в таблице.

Ниже приведена таблица tv_series с сериалами с их рейтингом. Однако, в таблицу закралась маленькая ошибка: хотя сериал Игра престолов и описывается как комедия, он на самом деле ей не является. Давайте исправим это!

Данные таблицы tv_series UPDATE tv_series SET genre = "драма" WHERE id = 2;

12. Удаление данных

Удаление строки таблицы с помощью SQL - это очень простой процесс. Все, что вам нужно, - это выбрать таблицу и строку, которую нужно удалить. Давайте удалим из предыдущего примера последнюю строку в таблице tv_series . Делается это с помощью инструкции >DELETE

DELETE FROM tv_series WHERE id = 4

Будьте осторожными при написании инструкции DELETE и убедитесь, что условие WHERE присутствует, иначе все строки таблицы будут удалены!

13. Удаление таблицы

Если мы хотим, чтобы удалить все строки, но оставить саму таблицу, то воспользуйтесь командой TRUNCATE:

TRUNCATE TABLE table_name;

В случае, когда мы на самом деле хотим, чтобы удалить и данные, и саму таблицу, то нам пригодится команда DROP:

DROP TABLE table_name;

Будьте очень осторожны с этими командами. Их нельзя отменить!/p>

На этом мы завершаем наш учебник по SQL! Мы многое о чем не рассказали, но то, что вы уже знаете, должно быть достаточно, чтобы дать вам несколько практических навыков в вашей веб-карьере.