Exists sql описание: SQL. 12. EXISTS. [SQL.RU]
EXISTS (Transact-SQL) — SQL Server
-
- Чтение занимает 4 мин
В этой статье
Применимо к:Applies to: SQL ServerSQL Server (все поддерживаемые версии) SQL ServerSQL Server (all supported versions) База данных SQL AzureAzure SQL DatabaseБаза данных SQL AzureAzure SQL Database Управляемый экземпляр SQL AzureAzure SQL Managed InstanceУправляемый экземпляр SQL AzureAzure SQL Managed Instance Azure Synapse AnalyticsAzure Synapse AnalyticsAzure Synapse AnalyticsAzure Synapse Analytics Параллельное хранилище данныхParallel Data WarehouseПараллельное хранилище данныхParallel Data WarehouseПрименимо к:Applies to: SQL ServerSQL Server (все поддерживаемые версии) SQL ServerSQL Server (all supported versions) База данных SQL AzureAzure SQL DatabaseБаза данных SQL AzureAzure SQL Database Управляемый экземпляр SQL AzureAzure SQL Managed InstanceУправляемый экземпляр SQL AzureAzure SQL Managed Instance Azure Synapse AnalyticsAzure Synapse AnalyticsAzure Synapse AnalyticsAzure Synapse Analytics Параллельное хранилище данныхParallel Data WarehouseПараллельное хранилище данныхParallel Data Warehouse
Указывает вложенный запрос для проверки существования строк. Specifies a subquery to test for the existence of rows.
Синтаксические обозначения в Transact-SQLTransact-SQL Syntax Conventions
СинтаксисSyntax
EXISTS ( subquery )
АргументыArguments
subquerysubquery
Ограниченная инструкция SELECT.Is a restricted SELECT statement. Ключевое слово INTO не допускается.The INTO keyword is not allowed. Дополнительные сведения о вложенных запросах см. в разделе SELECT (Transact-SQL).For more information, see the information about subqueries in SELECT (Transact-SQL).
Типы результатаResult Types
BooleanBoolean
Результирующие значенияResult Values
Возвращает значение TRUE, если вложенный запрос содержит хотя бы одну строку.Returns TRUE if a subquery contains any rows.
ПримерыExamples
A.A. Использование значения NULL во вложенном запросе для возвращения результирующего набораUsing NULL in a subquery to still return a result set
В следующем примере возвращается результирующий набор со значением NULL
, указанным во вложенном запросе, и устанавливается значение TRUE с помощью ключевого слова EXISTS
. The following example returns a result set with NULL
specified in the subquery and still evaluates to TRUE by using EXISTS
.
-- Uses AdventureWorks
SELECT DepartmentID, Name
FROM HumanResources.Department
WHERE EXISTS (SELECT NULL)
ORDER BY Name ASC ;
Б.B. Сравнение запросов с помощью ключевых слов EXISTS и INComparing queries by using EXISTS and IN
В следующем примере сравниваются два семантически эквивалентных запроса.The following example compares two queries that are semantically equivalent. В первом запросе используется ключевое слово EXISTS
, а во втором — ключевое слово IN
.The first query uses EXISTS
and the second query uses IN
.
-- Uses AdventureWorks
SELECT a.FirstName, a.LastName
FROM Person.Person AS a
WHERE EXISTS
(SELECT *
FROM HumanResources.Employee AS b
WHERE a.BusinessEntityID = b.BusinessEntityID
AND a. LastName = 'Johnson') ;
GO
В следующем запросе используется ключевое слово IN
.The following query uses IN
.
-- Uses AdventureWorks
SELECT a.FirstName, a.LastName
FROM Person.Person AS a
WHERE a.LastName IN
(SELECT a.LastName
FROM HumanResources.Employee AS b
WHERE a.BusinessEntityID = b.BusinessEntityID
AND a.LastName = 'Johnson') ;
GO
Здесь приведен результирующий набор для каждого запроса.Here is the result set for either query.
FirstName LastName
-------------------------------------------------- ----------
Barry Johnson
David Johnson
Willis Johnson
(3 row(s) affected)
В.C. Сравнение запросов с помощью ключевых слов EXISTS и = ANYComparing queries by using EXISTS and = ANY
В следующем примере показаны два запроса для поиска магазинов, названия которых совпадают с названием поставщика. The following example shows two queries to find stores whose name is the same name as a vendor. В первом запросе используется ключевое слово EXISTS
, а во втором — ключевое слово =``ANY
.The first query uses EXISTS
and the second uses =``ANY
.
-- Uses AdventureWorks
SELECT DISTINCT s.Name
FROM Sales.Store AS s
WHERE EXISTS
(SELECT *
FROM Purchasing.Vendor AS v
WHERE s.Name = v.Name) ;
GO
В следующем запросе используется ключевое слово = ANY
.The following query uses = ANY
.
-- Uses AdventureWorks
SELECT DISTINCT s.Name
FROM Sales.Store AS s
WHERE s.Name = ANY
(SELECT v.Name
FROM Purchasing.Vendor AS v ) ;
GO
Г.D. Сравнение запросов с помощью ключевых слов EXISTS и INComparing queries by using EXISTS and IN
В следующем примере показаны запросы для поиска сотрудников подразделений, имена которых начинаются на P
. The following example shows queries to find employees of departments that start with P
.
-- Uses AdventureWorks
SELECT p.FirstName, p.LastName, e.JobTitle
FROM Person.Person AS p
JOIN HumanResources.Employee AS e
ON e.BusinessEntityID = p.BusinessEntityID
WHERE EXISTS
(SELECT *
FROM HumanResources.Department AS d
JOIN HumanResources.EmployeeDepartmentHistory AS edh
ON d.DepartmentID = edh.DepartmentID
WHERE e.BusinessEntityID = edh.BusinessEntityID
AND d.Name LIKE 'P%') ;
GO
В следующем запросе используется ключевое слово IN
.The following query uses IN
.
-- Uses AdventureWorks
SELECT p.FirstName, p.LastName, e.JobTitle
FROM Person.Person AS p JOIN HumanResources.Employee AS e
ON e.BusinessEntityID = p.BusinessEntityID
JOIN HumanResources.EmployeeDepartmentHistory AS edh
ON e.BusinessEntityID = edh.BusinessEntityID
WHERE edh.DepartmentID IN
(SELECT DepartmentID
FROM HumanResources. Department
WHERE Name LIKE 'P%') ;
GO
Д.E. Использование ключевого слова NOT EXISTSUsing NOT EXISTS
Работа ключевого слова NOT EXISTS противоположна работе ключевого слова EXISTS.NOT EXISTS works the opposite of EXISTS. Предложение WHERE в ключевом слове NOT EXISTS удовлетворяется, если вложенный запрос не возвратил никаких строк.The WHERE clause in NOT EXISTS is satisfied if no rows are returned by the subquery. В следующем примере выполняется поиск сотрудников, не входящих в состав подразделений, имена которых начинаются на P
.The following example finds employees who are not in departments which have names that start with P
.
SELECT p.FirstName, p.LastName, e.JobTitle
FROM Person.Person AS p
JOIN HumanResources.Employee AS e
ON e.BusinessEntityID = p.BusinessEntityID
WHERE NOT EXISTS
(SELECT *
FROM HumanResources.Department AS d
JOIN HumanResources.EmployeeDepartmentHistory AS edh
ON d. DepartmentID = edh.DepartmentID
WHERE e.BusinessEntityID = edh.BusinessEntityID
AND d.Name LIKE 'P%')
ORDER BY LastName, FirstName
GO
Результирующий набор:Here is the result set.
FirstName LastName Title
------------------------------ ------------------------------ ------------
Syed Abbas Pacific Sales Manager
Hazem Abolrous Quality Assurance Manager
Humberto Acevedo Application Specialist
Pilar Ackerman Shipping & Receiving Superviso
François Ajenstat Database Administrator
Amy Alberts European Sales Manager
Sean Alexander Quality Assurance Technician
Pamela Ansman-Wolfe Sales Representative
Zainal Arifin Document Control Manager
David Barber Assistant to CFO
Paula Barreto de Mattos Human Resources Manager
Shai Bassli Facilities Manager
Wanida Benshoof Marketing Assistant
Karen Berg Application Specialist
Karen Berge Document Control Assistant
Andreas Berglund Quality Assurance Technician
Matthias Berndt Shipping & Receiving Clerk
Jo Berry Janitor
Jimmy Bischoff Stocker
Michael Blythe Sales Representative
David Bradley Marketing Manager
Kevin Brown Marketing Assistant
David Campbell Sales Representative
Jason Carlson Information Services Manager
Fernando Caro Sales Representative
Sean Chai Document Control Assistant
Sootha Charncherngkha Quality Assurance Technician
Hao Chen HR Administrative Assistant
Kevin Chrisulis Network Administrator
Pat Coleman Janitor
Stephanie Conroy Network Manager
Debra Core Application Specialist
Ovidiu Crãcium Sr. Tool Designer
Grant Culbertson HR Administrative Assistant
Mary Dempsey Marketing Assistant
Thierry D'Hers Tool Designer
Terri Duffy VP Engineering
Susan Eaton Stocker
Terry Eminhizer Marketing Specialist
Gail Erickson Design Engineer
Janice Galvin Tool Designer
Mary Gibson Marketing Specialist
Jossef Goldberg Design Engineer
Sariya Harnpadoungsataya Marketing Specialist
Mark Harrington Quality Assurance Technician
Magnus Hedlund Facilities Assistant
Shu Ito Sales Representative
Stephen Jiang North American Sales Manager
Willis Johnson Recruiter
Brannon Jones Finance Manager
Tengiz Kharatishvili Control Specialist
Christian Kleinerman Maintenance Supervisor
Vamsi Kuppa Shipping & Receiving Clerk
David Liu Accounts Manager
Vidur Luthra Recruiter
Stuart Macrae Janitor
Diane Margheim Research & Development Enginee
Mindy Martin Benefits Specialist
Gigi Matthew Research & Development Enginee
Tete Mensa-Annan Sales Representative
Ramesh Meyyappan Application Specialist
Dylan Miller Research & Development Manager
Linda Mitchell Sales Representative
Barbara Moreland Accountant
Laura Norman Chief Financial Officer
Chris Norred Control Specialist
Jae Pak Sales Representative
Wanda Parks Janitor
Deborah Poe Accounts Receivable Specialist
Kim Ralls Stocker
Tsvi Reiter Sales Representative
Sharon Salavaria Design Engineer
Ken Sanchez Chief Executive Officer
José Saraiva Sales Representative
Mike Seamans Accountant
Ashvini Sharma Network Administrator
Janet Sheperdigian Accounts Payable Specialist
Candy Spoon Accounts Receivable Specialist
Michael Sullivan Sr. Design Engineer
Dragan Tomic Accounts Payable Specialist
Lynn Tsoflias Sales Representative
Rachel Valdez Sales Representative
Garrett Vargar Sales Representative
Ranjit Varkey Chudukatil Sales Representative
Bryan Walton Accounts Receivable Specialist
Jian Shuo Wang Engineering Manager
Brian Welcker VP Sales
Jill Williams Marketing Specialist
Dan Wilson Database Administrator
John Wood Marketing Specialist
Peng Wu Quality Assurance Supervisor
(91 row(s) affected)
Примеры: Azure Synapse AnalyticsAzure Synapse Analytics и Параллельное хранилище данныхParallel Data WarehouseExamples: Azure Synapse AnalyticsAzure Synapse Analytics and Параллельное хранилище данныхParallel Data Warehouse
Е.
F. Использование ключевого слова EXISTSUsing EXISTS
В следующем примере определяется, могут ли строки в таблице ProspectiveBuyer
соответствовать строкам в таблице DimCustomer
.The following example identifies whether any rows in the ProspectiveBuyer
table could be matches to rows in the DimCustomer
table. Запрос будет возвращать строки, только при совпадении значений LastName
и BirthDate
в двух таблицах.The query will return rows only when both the LastName
and BirthDate
values in the two tables match.
-- Uses AdventureWorks
SELECT a.LastName, a.BirthDate
FROM DimCustomer AS a
WHERE EXISTS
(SELECT *
FROM dbo.ProspectiveBuyer AS b
WHERE (a.LastName = b.LastName) AND (a.BirthDate = b.BirthDate)) ;
Ж.G. Использование ключевого слова NOT EXISTSUsing NOT EXISTS
Работа ключевого слова NOT EXISTS противоположна работе ключевого слова EXISTS. NOT EXISTS works as the opposite as EXISTS. Предложение WHERE в ключевом слове NOT EXISTS удовлетворяется, если вложенный запрос не возвратил никаких строк.The WHERE clause in NOT EXISTS is satisfied if no rows are returned by the subquery. В следующем примере показан поиск всех строк в таблице DimCustomer
, где LastName
и BirthDate
не соответствуют записям в таблице ProspectiveBuyers
.The following example finds rows in the DimCustomer
table where the LastName
and BirthDate
do not match any entries in the ProspectiveBuyers
table.
-- Uses AdventureWorks
SELECT a.LastName, a.BirthDate
FROM DimCustomer AS a
WHERE NOT EXISTS
(SELECT *
FROM dbo.ProspectiveBuyer AS b
WHERE (a.LastName = b.LastName) AND (a.BirthDate = b.BirthDate)) ;
См. также:See Also
Выражения (Transact-SQL) Expressions (Transact-SQL)
Встроенные функции (Transact-SQL) Built-in Functions (Transact-SQL)
WHERE (Transact-SQL)WHERE (Transact-SQL)
CREATE DATABASE — MariaDB Knowledge Base
Синтаксис
CREATE [OR REPLACE] {DATABASE | SCHEMA} [IF NOT EXISTS] db_name [create_specification] . .. create_specification: [DEFAULT] CHARACTER SET [=] charset_name | [DEFAULT] COLLATE [=] collation_name
Описание
CREATE DATABASE
создает базу данных с заданым именем. Для того чтобы использовать данное выражение, Вам необходимо обладать соответствующими привилегиями (En). CREATE SCHEMA
— это синоним выражения CREATE DATABASE
. Если использовано выражение IF NOT EXISTS
, то в ситуации, когда база данных уже существует, пользователю будет выдано предупреждение, а не сообщение об ошибке.
OR REPLACE
MariaDB starting with 10.1.3
Выражение OR REPLACE
было добавлено в MariaDB в версии 10.1.3.
Если необязательное выражение OR REPLACE
используется, то оно действует как сокращение для:
DROP DATABASE IF EXISTS db_name; CREATE DATABASE db_name ...;
IF NOT EXISTS
При использовании выражения IF NOT EXISTS
MariaDB вернет предупреждение, а не сообщение об ошибке в том случае, если база с указанным именем уже существует.
Примеры
CREATE DATABASE db1; Query OK, 1 row affected (0.18 sec) CREATE DATABASE db1; ERROR 1007 (HY000): Can't create database 'db1'; database exists CREATE DATABASE IF NOT EXISTS db1; Query OK, 1 row affected, 1 warning (0.01 sec) SHOW WARNINGS; +-------+------+----------------------------------------------+ | Level | Code | Message | +-------+------+----------------------------------------------+ | Note | 1007 | Can't create database 'db1'; database exists | +-------+------+----------------------------------------------+
Настройка кодировки и правил сортировки (En). Подробнее смотри на странице «Настройка кодировки и правил сортировки» (En).
CREATE DATABASE czech_slovak_names CHARACTER SET = 'keybcs2' COLLATE = 'keybcs2_bin';
Смотри также
Справочник SQL для выражений запросов, применяемых в ArcGIS—ArcGIS Pro
This topic describes the elements of common selection queries in ArcGIS. Выражения запросов в ArcGIS используют SQL.
Внимание:
Синтаксис SQL не работает при вычислении полей с помощью окна Калькулятора поля .
Часто используемые запросы: поиск строк
Строковые значения в выражениях всегда заключаются в одинарные кавычки, например:
STATE_NAME = 'California'
Строки в выражениях чувствительны к регистру, кроме случаев работы в базах геоданных в Microsoft SQL Server. Чтобы выполнять не чувствительный к регистру поиск в других источниках данных, можно использовать функцию SQL для преобразования всех значений в один регистр. Для источников данных на основе файлов, таких как файловые базы геоданных или шейп-файлы, для задания регистра выборки можно использовать функции UPPER или LOWER. Например, при помощи следующего выражения выбирается штат, имя которого написано как ‘Rhode Island’ или ‘RHODE ISLAND’:
UPPER(STATE_NAME) = 'RHODE ISLAND'
Если строка содержит одинарную кавычку, вам в первую очередь требуется использовать другую одинарную кавычку как символ управляющей последовательности, например:
NAME = 'Alfie''s Trough'
При помощи оператора LIKE (вместо оператора = ) строится поиск частей строк. Например, данное выражение выбирает Mississippi и Missouri среди названий штатов США:
STATE_NAME LIKE 'Miss%'
Символ процента (%) означает, что на этом месте может быть что угодно – один символ или сотня, или ни одного. Если вы хотите использовать групповой символ, обозначающий один любой символ, используйте символ подчёркивания (_). Следующий пример показывает выражение для выбора имен Catherine Smith и Katherine Smith:
OWNER_NAME LIKE '_atherine Smith'
Можно также использовать операторы больше (>), меньше (<), больше или равно (>=), меньше или равно (<=), не равно (<>) и BETWEEN, чтобы выбирать строковые значения на основании их сортировки. Например, этот запрос выбирает все города в покрытии, названия которых начинаются с букв от М до Z:
CITY_NAME >= 'M'
Строковые функции могут использоваться для форматирования строк. Например функция LEFT возвращает определенное количество символов начиная с левого края строки. Данный запрос возвращает все штаты, начинающиеся на букву A:
LEFT(STATE_NAME,1) = 'A'
Список поддерживаемых функций вы найдете в документации по своей СУБД.
Часто используемые выражения: поиск значений NULL
Вы можете использовать ключевое слово NULL, чтобы отбирать объекты и записи, содержащие пустые поля. Перед ключевым словом NULL всегда стоит IS или IS NOT. Например, чтобы найти города, для которых не была введена численность населения по данным переписи 1996 года, можно использовать следующее выражение:
POPULATION IS NULL
Или, чтобы найти все города, для которых указана численность населения, используйте:
POPULATION96 IS NOT NULL
Часто используемые выражения: поиск чисел
Точка (.) всегда используется в качестве десятичного разделителя, независимо от региональных настроек. В выражениях в качестве разделителя десятичных знаков нельзя использовать запятую.
Вы можете запрашивать цифровые значения, используя операторы равно (=), не равно (<>), больше (>), меньше (<), больше или равно (>=) и меньше или равно (<=), а также BETWEEN (между), например:
POPULATION >= 5000
Числовые функции можно использовать для форматирования чисел. Например функция ROUND округляет до заданного количества десятичных знаков данные в файловой базе геоданных:
ROUND(SQKM,0) = 500
Список поддерживаемых числовых функций см. в документации по СУБД.
Даты и время
Общие правила и часто используемые выражения
В таких источниках данных, как база геоданных, даты хранятся в полях даты–времени. Однако в шейп-файлах это не тек. Поэтому большинство из примеров синтаксиса запроса, представленных ниже, содержит ссылки на время. В некоторых случаях часть запроса, касающаяся времени, может быть без всякого вреда пропущена, когда известно, что поле содержит только даты; в других случаях её необходимо указывать, или запрос вернет синтаксическую ошибку.
Поиск полей с датой требует внимания к синтаксису, необходимому для источника данных. Если вы создаете запрос в Конструкторе запросов в режиме Условие, правильный синтаксис будет сгенерирован автоматически. Ниже приведен пример запроса, который возвращает все записи после 1 января 2011, включительно, из файловой базы геоданных:
INCIDENT_DATE >= date '2011-01-01 00:00:00'
Даты хранятся в исходной базе данных относительно 30 декабря 1899 года, 00:00:00. Это действительно для всех источников данных, перечисленных здесь.
Цель этого подраздела – помочь вам в построении запросов по датам, но не по значениям времени. Когда со значением даты хранится не нулевое значение (например January 12, 1999, 04:00:00), то запрос по дате не возвратит данную запись, поскольку если вы задаете в запросе только дату для поля в формате дата – время, недостающие поля времени заполняются нулями, и выбраны будут только записи, время которых соответствует 12:00:00 полуночи.
Таблица атрибутов отображает дату и время в удобном для пользователя формате, согласно вашим региональным установкам, а не в формате исходной базы данных. Это подходит для большинства случаев, но имеются и некоторые недостатки:
- Строка, отображаемая в SQL-запросе, может иметь только небольшое сходство со значением, показанным в таблице, особенно когда в нее входит время. Например время, введенное как 00:00:15, отображается в атрибутивной таблице как 12:00:15 AM с региональными настройками США, а сопоставимый синтаксис запроса Datefield = ‘1899-12-30 00:00:15’.
- Атрибутивная таблица не имеет сведений об исходных данных, пока вы не сохраните изменения. Она сначала попытается отформатировать значения в соответствии с ее собственным форматом, затем, после сохранения изменений, она попытается подогнать получившиеся результаты в соответствии с базой данных. По этой причине, вы можете вводить время в шейп-файл, но обнаружите, что оно удаляется при сохранении ваших изменений. Поле будет содержать значение ‘1899-12-30’, которое будет отображаться как 12:00:00 AM или эквивалентно, в зависимости от ваших региональных настроек.
Синтаксис даты-времени для многопользовательских баз геоданных
Oracle
Datefield = date 'yyyy-mm-dd'
Имейте в виду, что здесь записи, где время не равно нулю, не будут возвращены.
Альтернативный формат при запросах к датам в Oracle следующий:
Datefield = TO_DATE('yyyy-mm-dd hh:mm:ss','YYYY-MM-DD Hh34:MI:SS')
Второй параметр ‘YYYY-MM-DD Hh34:MI:SS’ описывает используемый при запросах формат. Актуальный запрос выглядит так:
Datefield = TO_DATE('2003-01-08 14:35:00','YYYY-MM-DD Hh34:MI:SS')
Вы можете использовать более короткую версию:
TO_DATE('2003-11-18','YYYY-MM-DD')
И снова записи, где время не равно нулю, не будут возвращены.
SQL Server
Datefield = 'yyyy-mm-dd hh:mm:ss'
Часть запроса hh:mm:ss может быть опущена, когда в записях не установлено время.
Ниже приведен альтернативный формат:
Datefield = 'mm/dd/yyyy'
IBM Db2
Datefield = TO_DATE('yyyy-mm-dd hh:mm:ss','YYYY-MM-DD Hh34:MI:SS')
Часть запроса hh:mm:ss не может быть опущена, даже если время равно 00:00:00.
PostgreSQL
Datefield = TIMESTAMP 'YYYY-MM-DD Hh34:MI:SS' Datefield = TIMESTAMP 'YYYY-MM-DD'
Вы должны указать полностью временную метку при использовании запросов типа «равно», в или не будет возвращено никаких записей. Вы можете успешно делать запросы со следующими выражениями, если запрашиваемая таблица содержит записи дат с точными временными метками (2007-05-29 00:00:00 или 2007-05-29 12:14:25):
select * from table where date = '2007-05-29 00:00:00';
или
select * from table where date = '2007-05-29 12:14:25';
При использовании других операторов, таких как больше, меньше, больше или равно, или меньше или равно, вам не нужно указывать время, но это можно сделать для повышения точности. Оба эти выражения работают:
select * from table where date < '2007-05-29';
select * from table where date < '2007-05-29 12:14:25';
Файловые базы геоданных, шейп-файлы, покрытия и прочие файловые источники данных
Datefield = date 'yyyy-mm-dd'
Файловые базы геоданных поддерживают использование времени в поле даты, поэтому его можно добавить в выражение:
Datefield = date 'yyyy-mm-dd hh:mm:ss'
Шейп-файлы и покрытия не поддерживают использование времени в поле даты.
SQL, используемый в файловой базе геоданных, базируется на стандарте SQL-92.
Известные ограничения
Построение запросов к датам, находящимся в левой части (первой таблице) соединения, работает только для файловых источников данных, таких как файловые базы геоданных, шейп-файлы и таблицы DBF. Но возможен обходной путь при работе с другими, не файловыми, источниками, такими как многопользовательские данные, как описано ниже.
Запрос к датам левой части соединения будет выполнен успешно, если использовать ограниченную версию SQL, разработанную для файловых источников данных. Если вы не используете такой источник данных, можете перевести выражение для использования этого формата. Нужно обеспечить, чтобы выражение запроса включало поля из более чем одной присоединенной таблицы. Например, если соединены класс пространственных объектов и таблица (FC1 и Table1), и они поступают из многопользовательской базы геоданных, следующее выражение не будет выполнено или не вернет данные:
FC1. date = date #01/12/2001# FC1.date = date '01/12/2001'
Чтобы запрос был выполнен успешно, можно создать вот такой запрос:
FC1.date = date '01/12/2001' and Table1.OBJECTID > 0
Так как запрос включает поля из обеих таблиц, будет использована ограниченная версия SQL. В этом выражении Table1.OBJECTID всегда > 0 для записей, которые сопоставлены в процессе создания соединения, поэтому это выражение всегда верно для всех строк, содержащих сопоставления соединения.
Чтобы быть уверенным, что каждая запись с FC1.date = date ’01/12/2001′ выбрана, используйте следующий запрос:
FC1.date = date '01/12/2001' and (Table1.OBJECTID IS NOT NULL OR Table1.OBJECTID IS NULL)
Такой запрос будет выбирать все записи с FC1.date = date ’01/12/2001′, независимо от того, есть ли сопоставление при соединении для каждой отдельной записи.
Комбинированные выражения
Составные запросы могут комбинироваться путем соединения выражений операторами AND (И) и OR (ИЛИ). Вот пример запроса для выборки всех домов с общей площадью более 1500 квадратных футов и гаражом более чем на три машины:
AREA > 1500 AND GARAGE > 3
Когда вы используете оператор OR (ИЛИ), по крайней мере одно из двух разделенных оператором выражений, должно быть верно для выбираемой записи, например:
RAINFALL < 20 OR SLOPE > 35
Используйте оператор NOT (НЕ) в начале выражения, чтобы найти объекты или записи, не соответствующие условию выражения, например:
NOT STATE_NAME = 'Colorado'
Оператор NOT можно комбинировать с AND и OR. Вот пример запроса, который выбирает все штаты Новой Англии за исключением штата Maine:
SUB_REGION = 'New England' AND NOT STATE_NAME = 'Maine'
Вычисления
Вычисления можно включить в запросы с помощью математических операторов +, –, * и /. Можно использовать вычисление между полем и числом, например:
AREA >= PERIMETER * 100
Вычисления также могут производиться между полями. Например чтобы найти районы с плотностью населения меньшим или равным 25 человек на 1 квадратную милю, можно использовать вот такой запрос:
POP1990 / AREA <= 25
Приоритет выражения в скобках
Выражения выполняются в последовательности, определяемой стандартными правилами. Например, заключённая в круглые скобки часть выражения выполняется раньше, чем часть выражения за скобками.
HOUSEHOLDS > MALES * (POP90_SQMI + AREA)
Вы можете добавить скобки в режиме Редактирование SQL вручную, или использовать команды Группировать и Разгруппировать в режиме Условие, чтобы добавить или удалить их.
Подзапросы
Подзапрос – это запрос, вложенный в другой запрос и поддерживаемый только в базах геоданных. Подзапросы могут использоваться в SQL-выражении для применения предикативных или агрегирующих функций, или для сравнения данных со значениями, хранящимися в другой таблице и т.п. Это может быть сделано с помощью ключевых слов IN или ANY. Например этот запрос выбирает только те страны, которых нет в таблице indep_countries:
COUNTRY_NAME NOT IN (SELECT COUNTRY_NAME FROM indep_countries)
Покрытия, шейп-файлы и прочие файловые источники данных, не относящиеся к базам геоданных, не поддерживают подзапросы. Подзапросы, выполняемые на версионных многопользовательских классах объектов и таблицах, не возвращают объекты, которые хранятся в дельта-таблицах. Файловые базы геоданных имеют ограниченную поддержку подзапросов, описанных в данном разделе, в то время, как многопользовательские базы геоданных поддерживают их полностью. Информацию обо всех возможностях подзапросов к многопользовательским базам геоданных смотрите в документации по своей СУБД.
Этот запрос возвращает объекты, где GDP2006 больше, чем GDP2005 любых объектов, содержащихся в countries (странах):
GDP2006 > (SELECT MAX(GDP2005) FROM countries)
Поддержка подзапросов в файловых базах геоданных ограничена следующим:
Операторы
Ниже приведен полный список операторов, поддерживаемых файловыми базами геоданных, шейп-файлами, покрытиями и прочими файловыми источниками данных. Они также поддерживаются в многопользовательских базах геоданных, хотя для этих источников данных может требоваться иной синтаксис. Кроме нижеперечисленных операторов, многопользовательские базы геоданных поддерживают дополнительные возможности. Более подробную информацию см. в документации по своей СУБД.
Арифметические операторы
Для сложения, вычитания, умножения и деления числовых значений можно использовать арифметические операторы.
Оператор | Описание |
---|---|
* | Арифметический оператор умножения |
/ | Арифметический оператор деления |
+ | Арифметический оператор сложения |
– | Арифметический оператор вычитания |
Операторы сравнения
Операторы сравнения используются для сравнения одного выражения с другим.
Оператор | Описание |
---|---|
< | Меньше . Может использоваться со строками (сравнение основывается на алфавитном порядке) и для числовых вычислений, а также дат. |
<= | Меньше или равно. Может использоваться со строками (сравнение основывается на алфавитном порядке) и для числовых вычислений, а также дат. |
<> | Не равно . Может использоваться со строками (сравнение основывается на алфавитном порядке) и для числовых вычислений, а также дат. |
> | Больше . Может использоваться со строками (сравнение основывается на алфавитном порядке) и для числовых вычислений, а также дат. |
>= | Больше или равно. Может использоваться со строками (сравнение основывается на алфавитном порядке) и для числовых вычислений, а также дат. |
[NOT] BETWEEN x AND y | Выбирает запись, если она имеет значение, которое больше или равно x и меньше или равно y. Если перед ней стоит значение NOT, она выбирает запись, если та имеет значение вне указанного диапазона. Например это выражение выбирает все записи со значениями, которые больше или равны 1 и меньше или равны 10: OBJECTID BETWEEN 1 AND 10 Вот эквивалент этого выражения: OBJECTID >= 1 AND OBJECTID <= 10 Однако, выражение с оператором BETWEEN обрабатывается быстрее, если у вас поле проиндексировано. |
[NOT] EXISTS | Возвращает TRUE (истинно), если подзапрос возвращает хотя бы одну запись; в противном случае возвращает FALSE (ложно). Например, данное выражение вернет TRUE, если поле OJBECTID содержит значение 50: EXISTS (SELECT * FROM parcels WHERE OBJECTID = 50) EXISTS поддерживается только в файловых и многопользовательских базах геоданных. |
[NOT] IN | Выбирает запись, если она содержит одну из нескольких строк или значений в поле. Если впереди стоит NOT, выбирает запись, где нет таких строк или значений. Например, это выражение будет искать четыре разных названия штатов: STATE_NAME IN ('Alabama', 'Alaska', 'California', 'Florida') |
IS [NOT] NULL | Выбирает запись, если там в определенном поле есть нулевое значение. Если перед NULL стоит NOT, выбирает запись, где в определенном поле есть какое-то значение. |
x [NOT] LIKE y [ESCAPE ‘escape-character’] | Используйте оператор LIKE (вместо оператора = ) с групповыми символами, если хотите построить запрос по части строки. Символ процента (%) означает, что на этом месте может быть что угодно – один символ или сотня, или ни одного. Если вы хотите использовать групповой символ, обозначающий один любой символ, используйте символ подчёркивания (_). Если вам нужен доступ к несимвольным данным, используйте функцию CAST. Например, этот запрос возвращает числа, начинающиеся на 8, из целочисленного поля SCORE_INT: CAST (SCORE_INT AS VARCHAR(10)) LIKE '8%' Для включения символа (%) или (_) в вашу строку поиска, используйте ключевое слово ESCAPE для указания другого символа вместо escape, который в свою очередь обозначает настоящий знак процента или подчёркивания. Например данное выражение возвращает все строки, содержащие 10%, такие как 10% DISCOUNT или A10%: AMOUNT LIKE '%10$%%' ESCAPE '$' |
Логические операторы
Оператор | Описание |
---|---|
AND | Соединяет два условия и выбирает запись, в которой оба условия являются истинными. Например, выполнение следующего запроса выберет все дома с площадью более 1 500 квадратных футов и гаражом на две и более машины: AREA > 1500 AND GARAGE > 2 |
OR | Соединяет два условия и выбирает запись, где истинно хотя бы одно условие. Например выполнение следующего запроса выберет все дома с площадью более 1,500 квадратных футов или гаражом на две и более машины: AREA > 1500 OR GARAGE > 2 |
NOT | Выбирает записи, не соответствующие указанному выражению. Например это выражение выберет все штаты, кроме Калифорнии (California): NOT STATE_NAME = 'California' |
Операторы строковой операции
Оператор | Описание |
---|---|
|| | Возвращает символьную строку, являющуюся результатом конкатенации двух или более строковых выражений. FIRST_NAME || MIDDLE_NAME || LAST_NAME |
Функции
Ниже приведен полный список функций, поддерживаемых файловыми базами геоданных, шейп-файлами, покрытиями и прочими файловыми источниками данных. Функции также поддерживаются в многопользовательских базах геоданных, хотя в этих источниках данных может использоваться иной синтаксис или имена функций. Кроме нижеперечисленных функций, многопользовательские базы геоданных поддерживают дополнительные возможности. Более подробную информацию см. в документации по своей СУБД.
Функции дат
Функция | Описание |
---|---|
CURRENT_DATE | Возвращает текущую дату. |
EXTRACT(extract_field FROM extract_source) | Возвращает фрагмент extract_field из extract_source. Аргумент extract_source является выражением даты–времени. Аргументом extract_field может быть одно из следующих ключевых слов: YEAR, MONTH, DAY, HOUR, MINUTE или SECOND. |
CURRENT TIME | Возвращает текущую дату. |
Строковые функции
Аргументы, обозначаемые string_exp, могут быть названием столбца, строковой константой или результатом другой скалярной функции, где исходные данные могут быть представлены в виде символов.
Аргументы, обозначаемые character_exp, являются строками символов переменной длины.
Аргументы, указанные как start или length могут быть числовыми постоянными или результатами других скалярных функций, где исходные данные представлены числовым типом.
Строковые функции, перечисленные здесь, базируются на 1; то есть, первым символом в строке является символ 1.
Функция | Описание |
---|---|
CHAR_LENGTH(string_exp) | Возвращает длину строкового выражения в символах. |
LOWER(string_exp) | Возвращает строку, идентичную string_exp, в которой все символы верхнего регистра изменены на символы нижнего регистра. |
POSITION(character_exp IN character_exp) | Возвращает место первого символьного выражения во втором символьном выражении. Результат – число с точностью, определяемой реализацией и коэффициентом кратности 0. |
SUBSTRING(string_exp FROM start FOR length) | Возвращает символьную строку, извлекаемую из string_exp, начинающуюся с символа, положение которого определяется символами start и length . |
TRIM(BOTH | LEADING | TRAILING trim_character FROM string_exp) | Возвращает string_exp, укороченную на количество символов, указанное в аргументе trim_character, с начала, с конца или с обоих концов строки. |
UPPER(string_exp) | Возвращает строку, идентичную string_exp, в которой все символы нижнего регистра изменены на символы верхнего регистра. |
Числовые функции
Все числовые функции возвращают числовые значения.
Аргументы, обозначенные numeric_exp, float_exp или integer_exp могут быть именем столбца, результатом другой скалярной функции или числовой константой, где исходные данные могут быть представлены числовым типом.
Функция | Описание |
---|---|
ABS(numeric_exp) | Возвращает абсолютное значение numeric_exp. |
ACOS(float_exp) | Возвращает угол в радианах, равный арккосинусу float_exp. |
ASIN(float_exp) | Возвращает угол в радианах, равный арксинусу float_exp. |
ATAN(float_exp) | Возвращает угол в радианах, равный арктангенсу float_exp. |
CEILING(numeric_exp) | Возвращает наименьшее целочисленное значение, большее или равное numeric_exp. |
COS(float_exp) | Возвращает косинус float_exp, где float_exp — угол, выраженный в радианах. |
FLOOR(numeric_exp) | Возвращает наибольшее целое значение, меньшее или равное numeric_exp. |
LOG(float_exp) | Возвращает натуральный логарифм float_exp. |
LOG10(float_exp) | Возвращает логарифм по основанию 10 float_exp. |
MOD(integer_exp1, integer_exp2) | Возвращает результат деления integer_exp1 на integer_exp2. |
POWER(numeric_exp, integer_exp) | Возвращает значение numeric_exp в степени integer_exp. |
ROUND(numeric_exp, integer_exp) | Возвращает numeric_exp, округленное до integer_exp знаков справа от десятичной точки. Если integer_exp отрицательное, numeric_exp округляется до |integer_exp| знаков слева от десятичной запятой. |
SIGN(numeric_exp) | Возвращает указатель знака numeric_exp. Если numeric_exp меньше нуля, возвращается -1. Если numeric_exp равно нулю, возвращается 0. Если numeric_exp больше нуля, возвращается 1. |
SIN(float_exp) | Возвращает синус float_exp, где float_exp — угол, выраженный в радианах. |
TAN(float_exp) | Возвращает тангенс float_exp, где float_exp — угол, выраженный в радианах. |
TRUNCATE(numeric_exp, integer_exp) | Возвращает numeric_exp, округленное до integer_exp знаков справа от десятичной точки. Если integer_exp отрицательное, numeric_exp округляется до |integer_exp| знаков слева от десятичной запятой. |
Функция CAST
Функция CAST конвертирует значение в определенный тип данных. Синтаксис выглядит так:
CAST(exp AS data_type [(length)])
Пример:
CAST (SCORE_INT AS VARCHAR(10))
Аргумент exp может быть названием столбца, результатом другой скалярной функции или буквенным. Data_type может быть любым из следующих ключевых слов, и задается строчными или заглавными буквами: CHAR, VARCHAR, INTEGER, SMALLINT, REAL, DOUBLE, DATE, TIME, DATETIME, NUMERIC или DECIMAL.
Более подробно о функции CAST см. CAST and CONVERT.
Связанные разделы
Отзыв по этому разделу?
Техническая документация — Техническая документация — Помощь
Настройка БД MSSQL для хранения сессий
Для того, чтобы MSSQL мог хранить сессии необходимо в базе данных создать специальный набор таблиц и хранимых процедур. Во всех источниках говорится, что это можно сделать при помощи мастера, запускаемого из командной строки:
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\aspnet_regsql.exe
Проблема заключается в том, что мастер не показывает ошибки, если они возникают при его выполнении. Утилита aspnet_regsql.exe позволяет сделать экспорт скрипта, который выполняется на сервере MSSQL. Это делается следующей командой:
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\aspnet_regsql.exe -S uXXXXX.mssql.masterhost.ru -U uXXXXX_user -P PASSWORD -d uXXXXX_name -ssadd -sstype c -sqlexportonly C:\ssdb.sql
uXXXXX.mssql.masterhost.ru — адрес сервера MSSQL
uXXXXX_user — нужный MSSQL-логин
uXXXXX_db — имя нужной базы данных MSSQL
PASSWORD — соответствующий пароль доступа к базе данныхПосле выполнения команды создастся файл C:\ssdb.sql с кодом скрипта для настройки базы. Откроем этот файл в любом текстовом редакторе. База данных уже создана, поэтому из кода убираем следующую часть:
/* Create and populate the session state database */ IF DB_ID(N'uXXXXX') IS NULL BEGIN DECLARE @cmd nvarchar(500) SET @cmd = N'CREATE DATABASE [uXXXXX]' EXEC(@cmd) END GO
На хостинговом MSSQL-сервере отключен SQL Agent, поэтому невозможно создание заданий. Убираем части кода, касаемые создания заданий:
Убираем часть 1:
/* Drop the DeleteExpiredSessions_Job */ DECLARE @jobname nvarchar(200) SET @jobname = N' uXXXXX' + '_Job_DeleteExpiredSessions' -- Delete the [local] job -- We expected to get an error if the job doesn't exist. PRINT 'If the job does not exist, an error from msdb.dbo.sp_delete_job is expected.' EXECUTE msdb.dbo.sp_delete_job @job_name = @jobname GO
Убираем часть 2:
/* Create the job to delete expired sessions */ -- Add job category -- We expect an error if the category already exists. PRINT 'If the category already exists, an error from msdb.dbo.sp_add_category is expected.' EXECUTE msdb.dbo.sp_add_category @name = N'[Uncategorized (Local)]' GO BEGIN TRANSACTION DECLARE @JobID BINARY(16) DECLARE @ReturnCode int DECLARE @nameT nchar(200) SELECT @ReturnCode = 0 -- Add the job SET @nameT = N'uXXXXX' + '_Job_DeleteExpiredSessions' EXECUTE @ReturnCode = msdb. dbo.sp_add_job @job_id = @JobID OUTPUT, @job_name = @nameT, @owner_login_name = NULL, @description = N'Deletes expired sessions from the session state database.', @category_name = N'[Uncategorized (Local)]', @enabled = 1, @notify_level_email = 0, @notify_level_page = 0, @notify_level_netsend = 0, @notify_level_eventlog = 0, @delete_level= 0 IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback -- Add the job steps SET @nameT = N'uXXXXX' + '_JobStep_DeleteExpiredSessions' EXECUTE @ReturnCode = msdb.dbo.sp_add_jobstep @job_id = @JobID, @step_id = 1, @step_name = @nameT, @command = N'EXECUTE DeleteExpiredSessions', @database_name = N'uXXXXX', @server = N'', @subsystem = N'TSQL', @cmdexec_success_code = 0, @flags = 0, @retry_attempts = 0, @retry_interval = 1, @output_file_name = N'', @on_success_step_id = 0, @on_success_action = 1, @on_fail_step_id = 0, @on_fail_action = 2 IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback EXECUTE @ReturnCode = msdb. dbo.sp_update_job @job_id = @JobID, @start_step_id = 1 IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback -- Add the job schedules SET @nameT = N'uXXXXX' + '_JobSchedule_DeleteExpiredSessions' EXECUTE @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id = @JobID, @name = @nameT, @enabled = 1, @freq_type = 4, @active_start_date = 20001016, @active_start_time = 0, @freq_interval = 1, @freq_subday_type = 4, @freq_subday_interval = 1, @freq_relative_interval = 0, @freq_recurrence_factor = 0, @active_end_date = 99991231, @active_end_time = 235959 IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback -- Add the Target Servers EXECUTE @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @JobID, @server_name = N'(local)' IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback COMMIT TRANSACTION GOTO EndSave QuitWithRollback: IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION EndSave: GO /*************************************************************/
Остается решить, что делать со старыми сессиями. Их периодически необходимо удалять, иначе размер базы данных будет расти. Это можно сделать добавив следующий код либо в начало процедуры TempGetAppID, либо в код самого приложения:
Exec [dbo].[DeleteExpiredSessions]
По окончании редактирования файла достаточно выполнить его, например, подключившись к нужной базе данных с помощью Microsoft SQL Management Studio.
Настройка сайта для работы с БД MSSQL для хранения сессий
Для настройки сайта достаточно внести в файл конфигурации web.config в раздел <system.web> следующие строки:
<sessionState mode="SQLServer" allowCustomSqlDatabase="true" sqlConnectionString="Data Source=uXXXXX.mssql.masterhost.ru; Initial Catalog=uXXXXX_db;uid=uXXXXX_user;pwd=PASSWORD;" cookieless="false" timeout="20" />
uXXXXX.mssql.masterhost.ru — адрес сервера MSSQL
uXXXXX_user — нужный MSSQL-логин
uXXXXX_db — имя нужной базы данных MSSQL
PASSWORD — соответствующий пароль доступа к базе данныхСкачать пример готового web. config
Пример кода для проверки хранения сессий в БД MSSQL
Для проверки корректности хранения сессий в базе данных MSSQL можно использовать такой код:
<%@ Page Language="VB" %> <Script runat=server> Sub Session_Add(sender As Object, e As EventArgs) Session("MySession") = text1.Value span1.InnerHtml = "Session data updated! <P> Your session contains: <font color=red>" + Session("MySession").ToString() + "</font>" End Sub Sub CheckSession(sender As Object, e As EventArgs) If Session("MySession") Is DBNull.Value Then span1.InnerHtml = "NOTHING, SESSION DATA LOST!" Else span1.InnerHtml = "Your session contains: <font color=red>" + Session("MySession").ToString() + "</font>" End If End Sub </Script> <form id="Form1" runat=server> <input id=text1 type=text runat=server> <input id="Submit1" type=submit runat=server OnServerClick="Session_Add" Value="Add to Session State"> <input id="Submit2" type=submit runat=server OnServerClick="CheckSession" Value="View Session State"> </form> <hr size=1> <font size=6><span id=span1 runat=server/></font>
Код нужно сохранить в файле с расширением . aspx и загрузить файл на площадку в директорию сайта
НОУ ИНТУИТ | Лекция | Формирование запросов средствами языка SQL
Аннотация: В лекции обсуждаются вопросы применения оператора SELECT для построения сложных запросов.
Формирование запросов средствами языка SQL
Оператор SELECT
Оператор SELECT позволяет формировать запрос к базе данных. В результате выполнения этого оператора СУБД формирует результирующий набор (иногда также называемый набором данных). Если этот оператор был введен в интерактивном режиме взаимодействия с базой данных, то результат отображается в виде таблицы в текущем диалоговом окне. На рис. 3.1 приведен пример выполнения оператора SELECT , извлекающего данные всех столбцов из таблицы dept.
Рис.
3.1.
выполнение оператора SELECTЕсли оператор SELECT выполняется из приложения на другом языке программирования, то формируется результирующий набор, размещаемый в памяти приложения или сервера БД, а затем приложение извлекает данные из результирующего набора в свои переменные.
Оператор SELECT имеет в стандарте SQL92 следующее формальное описание:
SELECT [DISTINCT] { {function_agregate | expr [AS new_field_name] } .,: | specification.* | * [INTO list_variable] FROM {{ имя_таблицы [AS] [table_alias] [(field .,:)]} | {subquery [AS] subquery_alas [(field .,:)]} | union_table | constructor_of_table_value | {TABLE имя_таблицы [AS] alias [(field .,:)]} } .,: [WHERE condition] [GROUP BY {{ имя_таблицы | alias }.field} .,: {COLLATE name}] [HAVING condition] [{ UNION | INTERSECT | EXCEPT } [ALL] [CORRESPONDING [BY (field.,:)]] SELECT_operator | {TABLE имя_таблицы} | constructor_of_table_value [ORDER BY] {{field_result [ASC|DESC]}.,:} |{{ integer [ASC|DESC]}.,:} ;Листинг
intuit.ru/2010/edi»>Для выполнения запроса требуется привилегия SELECT на все таблицы, участвующие в запросе.
3.1.
Формальное описание оператора SELECTПосле фразы SELECT указывается список выражений, определяющий значения, формируемые запросом. В самом простом случае список выражений является списком полей таблицы. Если требуется извлечение значений всех полей, то вместо списка полей можно указать символ *. Например:
Имя поля может быть квалифицировано именем таблицы, указываемым через точку. Например:
SELECT tbl1.f1, tbl2.f1 FROM tbl1, tbl2;
- Фраза FROM определяет одну или несколько таблиц или подзапросов, используемых для извлечения данных.
- Фраза INTO используется только во встроенном SQL, указывая переменные, в которые записывается результат запроса. При этом формируемый результирующий набор может содержать только одну строку.
- Фраза WHERE определяет условие, которому должны удовлетворять все строки, используемые для формирования результирующего набора.
Во всех операциях сравнения языка SQL применяется трехзначная логика ( 3VL ). Предикат, указываемый фразой WHERE, может принимать одно из следующих значений: TRUE, FALSE или UNKNOWN. Значение UNKNOWN получается при сравнении значения NULL с любым другим значением, включая значение NULL.
Предикат содержит одно или несколько выражений, выполняющих сравнения. В выражениях могут участвовать имена столбцов, функции агрегирования, переменные встроенного SQL, параметры модульного SQL.
Кроме стандартных операторов сравнения, таких как =, <>, >, <, >=, <= могут быть использованы следующие операторы:
Вариант сравнения | Предикат | ||
---|---|---|---|
SOME | ANY | All | |
Результат сравнения конструктора значений строки с каждой строкой из набора строк, полученных как подзапрос, равен TRUE | TRUE | TRUE | TRUE |
Результат выполнения подзапроса не содержит строк для сравнения | FALSE | FALSE | TRUE |
Результат сравнения конструктора значений строки с каждой строкой из набора строк, полученных как подзапрос, равен FALSE | FALSE | FALSE | FALSE |
Хотя бы один из результатов сравнения конструктора значений строки со строкой из набора строк, полученных как подзапрос, равен TRUE | TRUE | TRUE | UNKNOWN |
(10, 1)> ANY (12, 2 0, NULL 5, 20),
так как первая строка из подзапроса удовлетворяет условию. А предикат
(NULL, NULL) = ANY (12, 2 NULL, NULL 5, 20)
вернет значение UNKNOWN, так как сравнение NULL c NULL в результате дает UNKNOWN. Предикат
(10, 1)> ALL (12, 0 0, NULL 5, 20)
вернет значение FALSE, так как сравнение строки (10,1) с каждой строкой подзапроса возвращает значение FALSE.
ТОП 30 статей для изучения языка T-SQL – Уровень «Начинающий»
Приветствую Вас на сайте Info-Comp.ru! В этом материале я представляю Вам 30 лучших своих статей, посвященных языку T-SQL, которые отлично подойдут начинающим программистам для изучения языка T-SQL.
Данную подборку статей я назвал – Уровень «Начинающий», ведь все представленные здесь статьи не требуют особой подготовки и знаний языка T-SQL и Microsoft SQL Server.
Статьи упорядочены в порядке увеличения сложности и специфичности, иными словами, в начале этого списка я расположил статьи с базовыми знаниями, а затем постепенно осуществляется переход к более сложным и специфичным задачам.
Таким образом, данный материал можно было бы смело назвать «Курс по изучения языка T-SQL для начинающих», так как последовательно читая все представленные здесь статьи Вы будете изучать язык T-SQL примерно так же, как на специализированных курсах по T-SQL.
Однако за счет того, что здесь отсутствует какая-либо методика обучения, направленная на комплексное изучение языка T-SQL, а представлена всего лишь подборка подходящих статьей, при этом даже такое количество статей не охватывает тот объем информации, который требуется начинающим, данный материал я назвал именно так, т. е. – «ТОП 30 статей для изучения языка T-SQL – Уровень «Начинающий».
Почему Уровень «Начинающий»? Потому что это — первый материал из цикла статей на данную тему, будут еще подборки: Уровень «Продвинутый» и Уровень «Эксперт». Поэтому следите за выходом новых статей в наших группах в социальных сетях: ВКонтакте, Facebook, Одноклассники, Twitter и Tumblr.
Все статьи написаны лично мной (некоторые уже достаточно давно, поэтому не судите строго) и расположены они на этом же сайте в открытом доступе, поэтому Вам не придётся посещать какие-то сторонние ресурсы для того, чтобы прочитать их.
Итак, давайте приступать.
Что такое SQL
Статья – Что такое SQL. Назначение и основа
Из данного материала Вы узнаете, что такое SQL вообще, для чего нужен и используется данный язык, я расскажу про диалекты языка SQL, а также про базы данных и системы управления базами данных. Здесь представлена основа, база, с которой необходимо начать свое знакомство с языком T-SQL (Что такое T-SQL?).
Как создать и выполнить SQL запрос
Статья – Как создать и выполнить SQL запрос к базе данных. Обзор основных инструментов
Из этой статьи Вы узнаете, какими инструментами создавать и выполнять SQL запросы к базе данных, будут рассмотрены инструменты не только для Microsoft SQL Server, но и для других популярных СУБД. Таким образом, в материале представлены основные инструменты, с которыми Вам придётся работать при разработке инструкций на языке SQL.
Создание базы данных
Статья – Создание базы данных в Microsoft SQL Server – инструкция для новичков
В этом материале представлена подробная инструкция для новичков по созданию базы данных в Microsoft SQL Server. Здесь рассмотрены основные этапы создания базы данных, а также два способа создания БД. Без знаний, представленных в этой статье, создать базу не получится.
Создание таблиц
Статья – Создание таблиц в Microsoft SQL Server (CREATE TABLE) – подробная инструкция
В этой статье рассмотрен процесс создания таблиц в Microsoft SQL Server, Вы узнаете, как это делается в графическом интерфейсе, а также как создавать таблицы на языке T-SQL. Здесь, как и во всех других материалах, представлены практические примеры со скриншотами и пояснениями.
Изменение таблиц
Статья – Изменение таблиц в Microsoft SQL Server или как добавить, удалить, изменить столбец в таблице?
В материале подробно рассмотрен процесс изменения таблиц в Microsoft SQL Server, Вы научитесь добавлять или удалять столбцы в таблицах, а также изменять свойства столбцов.
Переименование столбцов
Статья – Как переименовать столбец таблицы в Microsoft SQL Server на T-SQL?
Из данного материала Вы узнаете, как переименовать столбец таблицы в Microsoft SQL Server на языке T-SQL уже после создания этой таблицы. В некоторых случаях это бывает очень полезно, так как Вам не нужно пересоздавать всю таблицу целиком.
Добавление данных
Статья – Инструкция INSERT INTO в Transact-SQL – несколько способов добавления данных в таблицу
В этой статье рассмотрено несколько способов добавления данных в базу Microsoft SQL Server. Иными словами, Вы узнаете, как добавляются новые строки в таблицы на языке T-SQL с использованием инструкции INSERT INTO.
Обновление данных
Статья – Инструкция UPDATE в T-SQL — обновление данных в Microsoft SQL Server
В этом материале подробно рассмотрена инструкция UPDATE языка T-SQL, с помощью которой происходит обновление данных в таблицах Microsoft SQL Server. Таким образом, Вы узнаете, как изменять уже существующие данные в базе.
Вычисляемые столбцы
Статья – Вычисляемые столбцы в Transact-SQL
В данной статье рассмотрены вычисляемые столбцы в таблицах Microsoft SQL Server, Вы узнаете, для чего они нужны и как они создаются.
Инструкция SELECT INTO
Статья – Инструкция SELECT INTO в T-SQL или как создать таблицу на основе SQL запроса?
Из данного материала Вы узнаете, как создать таблицу на основе результата SQL запроса в Microsoft SQL Server с использованием инструкции SELECT INTO. Будет рассмотрено несколько примеров с подробным описанием.
Типы данных в T-SQL
Статья – Типы данных в T-SQL (Microsoft SQL Server)
В этой статье подробно рассмотрены все типы данных языка T-SQL, а также приоритеты и синонимы типов данных. Вы узнаете, какие существуют типы данных, какие у них особенности, а также в каких случаях использовать тот или иной тип данных.
Оператор BETWEEN
Статья – BETWEEN в T-SQL – примеры использования логического оператора
В данном материале будет рассмотрен логический оператор BETWEEN языка T-SQL, с помощью которого можно проверить, входит ли значение в определённый диапазон. Мы разберем несколько примеров его использования в разных секциях SQL запроса.
Оператор EXISTS
Статья – Логический оператор EXISTS в T-SQL. Описание и примеры
Из данной статьи Вы узнаете, как работает логический оператор EXISTS в языке T-SQL, который принимает и обрабатывает вложенный SQL запрос (SELECT) с целью проверки существования строк. В качестве результата возвращает значения TRUE или FALSE. Здесь будет рассмотрено несколько примеров его использования в разных конструкциях.
Команда USE
Статья – Как изменить контекст базы данных в Microsoft SQL Server? Команда USE
Из данного материала Вы узнаете, как можно сменить контекст базы данных в Microsoft SQL Server, будет рассмотрена команда USE, которая используется в T-SQL как раз для этого.
Составные операторы присваивания
Статья – Составные операторы присваивания в Transact-SQL
Из данной статьи Вы узнаете, какие существуют составные операторы в языке Transact-SQL, которые используются для упрощения написания операций присваивания, и как их использовать.
Инструкция TRUNCATE TABLE
Статья – Инструкция TRUNCATE TABLE в Transact-SQL
В этом материале рассмотрена инструкция TRUNCATE TABLE, которую можно использовать для удаления данных. Вы узнаете, чем отличается TRUNCATE TABLE от DELETE, и какие преимущества нам дает эта инструкция.
Группировка данных GROUP BY
Статья – Transact-SQL группировка данных GROUP BY
В данной статье рассмотрена конструкция GROUP BY языка T-SQL, которая используется для группировки данных. Данная конструкция очень полезна, и она используется достаточно часто для анализа различных данных.
Объединение JOIN
Статья – Язык SQL – объединение JOIN
В этом материале рассмотрены основы объединения данных из разных таблиц, Вы узнаете, что такое INNER, LEFT, RIGHT и CROSS JOIN, и, конечно же, посмотрите на примеры использования этих конструкций.
Объединение UNION и UNION ALL
Статья – Объединение UNION и UNION ALL в SQL – описание и примеры
В этой статье рассмотрено объединение UNION и UNION ALL, которое используется для объединения результирующего набора данных нескольких SQL запросов. Вы узнаете, для чего может потребоваться этот тип объединения, и посмотрите на примеры использования UNION и UNION ALL.
Хранимые процедуры
Статья – Хранимые процедуры в T-SQL — создание, изменение, удаление
Из данной статьи Вы узнаете, что такое хранимые процедуры в языке T-SQL, научитесь создавать, изменять и удалять хранимые процедуры.
Ограничения
Статья – Ограничения в Microsoft SQL Server — что это такое и как их создать?
Ограничения – это специальные объекты в Microsoft SQL Server, с помощью которых можно задать правила допустимости определенных значений в столбцах с целью обеспечения автоматической целостности базы данных.
В данной статье будут рассмотрены основы и примеры создания ограничений в Microsoft SQL Server, таких как: PRIMARY KEY, FOREIGN KEY, CHECK и других.
Основы индексов
Статья – Основы индексов в Microsoft SQL Server
В этой статье рассмотрены основы индексов в Microsoft SQL Server, Вы узнаете, для чего нужны индексы, какие типы индексов бывают, а также как создаются, оптимизируются и удаляются индексы на языке T-SQL.
Вложенные запросы
Статья – Вложенные запросы в T-SQL – описание и примеры
Из данного материала Вы узнаете, что такое вложенные запросы SQL, где и в каких конструкциях их можно использовать, будут рассмотрены примеры их использования, а также я расскажу про особенности и некоторые ограничения вложенных SQL запросов.
Выражение CASE
Статья – Примеры использования выражения CASE в Transact-SQL
CASE – это инструкция, которая проверяет список условий и возвращает соответствующий результат. Если говорить в целом о программировании, то CASE – это что-то вроде многократного использования конструкции IF-ELSE, во многих языках есть похожая конструкция SWITCH.
В этом материале рассмотрено выражение CASE языка Transact-SQL: описание, синтаксис, а также примеры использования выражения CASE.
Как получить первые (или последние) строки запроса
Статья – Как в SQL получить первые (или последние) строки запроса? TOP или OFFSET?
Из данного материала Вы узнаете два способа получения первых или последних строк SQL запроса, первый — с применением фильтра TOP, второй — используя конструкцию OFFSET-FETCH.
Операция MERGE
Статья – Операция MERGE в языке Transact-SQL – описание и примеры
MERGE – операция в языке T-SQL, при которой происходит обновление, вставка или удаление данных в таблице на основе результатов соединения с данными другой таблицы или SQL запроса. Другими словами, с помощью MERGE можно осуществить слияние двух таблиц, т.е. синхронизировать их.
В этом материале будут рассмотрены основы и примеры использования операции MERGE.
Оператор DROP IF EXISTS
Статья – Инструкция DROP IF EXISTS в языке T-SQL
У инструкции DROP, которая используется для удаления объектов базы данных, есть дополнительный параметр IF EXISTS, благодаря которому можно предварительно проверить существование объекта, перед его непосредственным удалением.
В этой статье рассмотрена инструкция DROP IF EXISTS и примеры ее использования.
Конструкция OFFSET-FETCH
Статья – OFFSET-FETCH в T-SQL – описание и примеры использования
OFFSET-FETCH – это конструкция языка T-SQL, которая является частью ORDER BY, и позволяет применять фильтр к результирующему, уже отсортированному, набору данных.
В данном материале рассмотрена конструкция OFFSET-FETCH, а также приведены примеры использования этой конструкции.
Как вывести повторяющиеся значения в столбце
Статья – Как вывести повторяющиеся значения в столбце на T-SQL? Microsoft SQL Server
Из данного материала Вы узнаете, как вывести повторяющиеся значения в столбце таблицы на языке T-SQL, будут рассмотрены конкретные примеры.
Основы программирования на T-SQL
Статья – Основы программирования на T-SQL
В этом материале рассмотрены основы программирования на языке T-SQL, Вы узнаете, что такое пакеты, переменные, научитесь использовать условные конструкции, циклы, а также познакомитесь с командами GOTO, WAITFOR, RETURN и другими.
Виталий Трунин
Автор всех статей. Разработчик T-SQL
Задать вопрос
Для комплексного и последовательного изучения языка T-SQL рекомендую пройти мой курс по T-SQL для начинающих, который включает, не только текстовый материал, но и видео, задания, тесты, а также поддержку ментора и сертификат о прохождении.
На сегодня это все, до новых встреч на сайте Info-Comp.ru!
добейтесь большего от SQL Server » Статьи о Microsoft Windows. Установка, администрирование, ускорение и оптимизация Microsoft Windows 7, Windows 8, Windows XP, и Windows 10
Я расскажу, как обращаться к данным, которые содержатся в XML-строках, передаваемых хранимым процедурам, и как выводить XML-данные. На рис. 1 показана высокоуровневая архитектура этих операций. Я познакомлю вас со следующими синтаксическими конструкциями T-SQL, связанными с XML:
— sp_xml_preparedocument;
— OPENXML;
— sp_xml_removedocument;
— FOR XML EXPLICIT.
Рис. 1. Применение на практике некоторых новшеств в синтаксисе T-SQL
Простой пример: пакетная проверка пользовательского ввода
В SQL Server 2000 нет встроенного типа для хранения XML-данных. Для хранения XML-строк в переменных или полях таблиц применяют тип (n)(var)char или (n)text. Почти во всех случаях, встречающихся при разработке, такие переменные оказываются входными параметрами хранимых процедур; поэтому так будет и в моем примере. (Следует заметить, что передача кода T-SQL между уровнями всегда рискованна с точки зрения безопасности и, как правило, оказывается не лучшим вариантом с точки зрения производительности; это достаточно веские причины, чтобы никогда так не поступать.)
Рассмотрим хранимую процедуру sptxValidateLookupData, разработанную моей группой несколько лет назад. Она предназначена для проверки на допустимость данных, вводимых пользователем в рабочий процесс определенной системы. Чтобы свести к минимуму количество обменов с базой данных, разработчики системы решили накапливать весь пользовательский ввод и передавать информацию, которую требуется проверять на допустимость, в базу данных в одном XML-документе. Хранимая процедура выполняет проверку на допустимость и возвращает вызывающему процессу результаты, также помещая их в один XML-документ. Процедура sptxValidateLookupData обслуживает несколько разных рабочих процессов, поэтому в одном и том же пакете могут запрашиваться проверки «существует» или «не существует» для любого значения (datum) или области (domain). В следующем фрагменте кода показаны типичные входные XML-данные этой хранимой процедуры:
<ValidateData>
<Validate Type=»Countries» Name=»CountryCode»
Value=»JA» Test=»Not Exists»/>
<Validate Type=»Countries» Name=»CountryCode»
Value=»BO1″ Test=»Exists»/>
<Validate Type=»Languages» Name=»LanguageCode»
Value=»EN» Test=»Exists»/>
<Validate Type=»ContactPreferences»
Name=»ContactPreferenceCode» Value=»EN»
Test=»Exists»/></ValidateData>
В корневом узле содержатся подузлы , описывающие, какую проверку нужно выполнить. Type задает область, для которой выполняется проверка, Name — проверяемый атрибут, а Test — тип проверки (существует ли значение Value в поле, указанном атрибутом Name, в области Type). Заметьте: этот фрагмент XML-данных описывает четыре операции проверки на допустимость для трех областей, но версия хранимой процедуры, которая используется в настоящее время, поддерживает 17 областей и любое число проверок. Таким образом, у нас есть компонент проверки на допустимость, обеспечивающий многократное использование кода, отличную расширяемость и высокую производительность, удобный в сопровождении, а главное — простой до неприличия!
Результаты также возвращаются в XML-формате. Если все проверки для данного потока возвратили TRUE (т. е. если истинны утверждения, задаваемые в узлах Test), возвращается пустой тэг . Однако, если какие-либо проверки потерпели неудачу, возвращается список ошибок:
<Errors>
<Error ErrorMessage=»JA exists in Countries»
FieldName=»CountryCode»/>
<Error ErrorMessage=»BO1 does not exist in Countries»
FieldName=»CountryCode»/>
<Error ErrorMessage=»EN does not exist in ContactPreferences»
FieldName=»ContactPreferenceCode»/>
</Errors>
Работа с XML-данными
В SQL Server 2000 XML-данные передаются процессу T-SQL как простые строки. Чтобы с ними можно было работать как с реляционными или иерархическими данными, необходимо дать SQL Server «понять», что это XML-данные, — «подготовить» их. Для этого вызывается системная хранимая процедура sp_xml_preparedocument. Давайте посмотрим начало хранимой процедуры sptxValidateLookupData (листинг 1). Системная хранимая процедура sp_xml_preparedocument считывает XML-текст, передаваемый как входной параметр (параметр @XMLString в вызове в листинге 1), затем передает текст анализатору MSXML и формирует проанализированный документ, готовый к обработке функцией OPENXML, возвращающей набор записей.
Этот документ является иерархическим представлением различных узлов XML-документа (элементов, атрибутов, текста, комментариев и т.д.). Оно хранится в кэше сервера, максимальный размер которого равен одной восьмой от общего объема памяти сервера. Поэтому необходимо аккуратно работать с этим внутренним представлением в интенсивно используемых системах или в средах с ограниченным объемом памяти.
Листинг 1. Хранимая процедура sptxValidateLookupData
create procedure sptxValidateLookupData
@XMLString ntext
as
set nocount on
declare @idoc int, @Name nvarchar(30), @Value nvarchar(300),
@Test nvarchar(30), @Result int, @Type nvarchar(30),
@TestResult int
— Готовим входные XML-данные к выборке с помощью OPENXML
exec sp_xml_preparedocument @idoc OUTPUT, @XMLString
Процедура sp_xml_preparedocument возвращает описатель (значение @idoc в вызове в листинге 1), через который можно обращаться к созданному внутреннему представлению XML-документа. Это значение используется в качестве параметра функции OPENXML, возвращающей набор записей для оператора SELECT. OPENXML — «мост» к подготовленному XML-документу, и ее можно указывать в операторе SELECT аналогично таблице или представлению (листинг 2).
Я создал и заполнил табличную переменную, чтобы не выполнять многократные вызовы OPENXML, которые были бы менее эффективны, чем многократное обращение к табличной переменной. Лучше копировать содержимое XML-документов в табличные переменные, чтобы избавиться от многократного неэффективного доступа к XML-данным (хотя, если вы собираетесь обратиться к XML-данным только один раз, просто выполните запрос с OPENXML без предварительного создания табличной переменной). Второй оператор на рис. 3 копирует входные XML-данные в табличную переменную @tempValidateLookupData.
Листинг 2. Создание табличной переменной
— Создаем табличную переменную для хранения
— данных о проверках
declare @tempValidateLookupData table (
[Type] nvarchar(30),
[Name] nvarchar(30),
[Value] nvarchar(300),
[Test] nvarchar(30),
[TestResult] int
)
— Заполняем табличную переменную данными о проверках,
— которые требуется выполнить
insert @tempValidateLookupData
select [Type], [Name], [Value], [Test], NULL
from OPENXML (@idoc, ‘/ValidateData/Validate’)
with ([Type] nvarchar(30), [Name] nvarchar(30),
[Value] nvarchar(300), [Test] nvarchar(30))
Знакомимся с OPENXML
Теперь повнимательнее рассмотрим синтаксис OPENXML:
OPENXML(idoc int [in],rowpattern nvarchar[in],[flags byte[in]])
[WITH (SchemaDeclaration | TableName)]
Параметр idoc — описатель документа, созданный для внутреннего представления XML-документа. Другими словами, это значение, ранее возвращенное процедурой sp_xml_preparedocument. Заметьте: в одной хранимой процедуре можно манипулировать несколькими XML-строками. В таком случае необходимо вызвать sp_xml_preparedocument для каждой XML-строки и объявить по отдельной переменной для хранения каждого возвращенного описателя.
Параметр rowpattern идентифицирует узлы XML-документа, связанного с описателем idoc, которые должны обрабатываться как записи. Он указывает XML-анализатору, где в XML-документе находятся интересующие вас данные.
Параметр flags задает, какое сопоставление используется при запросе в первую очередь — ориентированное на атрибуты (attribute-centric) или на элементы (element-centric). Если этот параметр опущен, SQL Server 2000 по умолчанию применяет сопоставление, ориентированное на атрибуты, что вполне подходит для нашего случая. Подробнее об этом параметре см. описание функции OPENXML в SQL Server Books Online.
Раздел WITH функции OPENXML указывает SQL Server 2000, какие типы данных SQL сопоставляются содержимому XML-документа. Вы можете либо явно задать поля, либо сослаться на таблицу базы данных с подходящей структурой. Каждое поле XML-документа, используемое в операторе SELECT, должно присутствовать в разделе WITH (описываться явно или в таблице). В рассматриваемом примере:
— Заполняем табличную переменную данными о проверках,
— которые требуется выполнить
insert @tempValidateLookupData
select [Type], [Name], [Value], [Test], NULL
from OPENXML (@idoc, ‘/ValidateData/Validate’)
with ([Type] nvarchar(30), [Name] nvarchar(30),
[Value] nvarchar(300), [Test] nvarchar(30))
имена полей в операторе SELECT и в разделе WITH должны соответствовать именам атрибутов во входном XML-документе. Также заметьте, что, поскольку XML-данные рассматриваются как набор записей, программа проверки на допустимость будет правильно работать при любом количестве значений (хоть при одном, хоть при десяти): вызывающий процесс просто передает столько узлов XML-документа, сколько нужно проверить на допустимость.
Освобождение памяти
Внутреннее представление XML-документа остается в памяти, пока соединение процесса с сервером не будет закрыто или сброшено или пока память не освободят явно. Следует вызывать системную процедуру sp_xml_removedocument как можно раньше, поскольку лучше поскорее освободить эту память, чтобы на сервере было доступно больше ресурсов (для освобождения памяти требуется указать описатель):
— Освобождаем память сервера, которая используется
— образом входных XML-данных, созданным OPENXML
exec sp_xml_removedocument @idoc
Это особенно важно в средах, где используется пул соединений. В таких средах соединения могут существовать в течение нескольких дней, и многократное создание образов XML-документов в памяти без последующего освобождения может вызвать снижение производительности, поскольку количество свободной памяти сократится. Пул соединений сбрасывает соединение, если оно повторно используется кем-то другим, при этом освобождаются и описатели XML-данных. Но лучше явно освобождать описатели, а не полагаться, на то, что при сбросе соединений это сделают за вас.
После разбора XML-документа процедура sptxValidateLookupData выполняет большой оператор IF, чтобы выбрать требуемую проверку и занести в переменную @TestResult значение, соответствующее результатам проверки. Затем результаты проверки используются при обновлении табличной переменной (листинг 3).
Листинг 3. Выбор требуемой проверки
— Заносим результаты проверок в табличную переменную,
— перебирая записи, у которых поле TestResult содержит NULL
while exists (select TestResult from @tempValidateLookupData
where TestResult is null) begin
— Извлекаем данные из записи, проверяемой на допустимость
Select top 1 @Type=[Type], @Name=[Name], @Value=Value,
@Test=Test
from @tempValidateLookupData
where TestResult is null
— И выполняем соответствующую проверку…
— Проверка для области Countries (взята в качестве примера)
if @Type = ‘Countries’ begin
if exists (select CountryCode from dbo. Country where
CountryCode = convert(nvarchar(4), @Value))
select @TestResult =
CASE when @Test = ‘Exists’ then 1
else 0
end
else
select @TestResult =
CASE when @Test = ‘Not Exists’ then 1
else 0
end
end
— (16 других проверок на допустимость опущены для краткости)
— Обновляем соответствующую запись: заносим в нее результат
— проверки
update @tempValidateLookupData
set TestResult = @TestResult
where Name = @Name
and Value = @Value
and Test = @Test
end
SQL-синтаксис для возврата XML-данных
Итак, проверки на допустимость выполнены, теперь нужно возвратить результаты вызывающему процессу. SQL Server 2000 поддерживает несколько механизмов вывода XML-данных с помощью директивы FOR XML оператора SELECT. Прежде чем продолжить рассказ о sptxValidateLookupData, я кратко рассмотрю еще кое-какие новшества в синтаксисе языка SQL.
В SQL Server 2000 три типа разделов FOR XML. FOR XML RAW и FOR XML AUTO позволяют сформировать простейший XML-вывод с минимумом усилий и соответственно с отсутствием контроля над форматом вывода. Большинство уважающих себя программистов для SQL Server 2000 используют FOR XML EXPLICIT. При применении режима EXPLICIT программист полностью контролирует вид XML-документа, возвращаемого запросом, и должен обеспечить синтаксическую корректность и допустимость XML-документа.
Как выглядит содержимое раздела EXPLICIT?
Существует ряд жестких синтаксических требований к формированию запросов, использующих режим EXPLICIT. Каждый запрос с режимом EXPLICIT должен содержать два поля метаданных. У первого поля, указываемого в операторе SELECT, должно быть имя Tag и тип int. Это номер тэга текущего элемента, т. е. фактически номер типа поддерева. У второго поля должно быть имя Parent и тоже тип int. Оно содержит номер тэга элемента, который является родителем текущего элемента. Эти поля описывают иерархию XML-дерева. Если поле Parent записи имеет значение 0 или NULL, его данные располагаются на вершине XML-иерархии. Кроме этого единственного исключения, все значения поля Parent должны соответствовать ранее объявленным значениям тэгов. Заметьте: набор результатов должен содержать ровно одну запись, у которой поле Parent содержит 0 или NULL, причем она должна быть первой в наборе результатов (если имеется более одной записи, у которой номер тэга родителя равен 0 или NULL, генерируется XML-фрагмент).
Имена остальных полей запроса должны соответствовать специальному формату, который определяет, как имена элементов связаны с номерами тэгов, и задает имена атрибутов для генерируемых XML-данных. Имя поля имеет формат:
[ElementName!TagNumber!AttributeName!Directive]
где ElementName — имя элемента (если в качестве ElementName указано «Countries», результатом будет ), а TagNumber — номер тэга элемента. TagNumber вместе с полями метаданных Tag и Parent описывает иерархию XML-дерева. Каждый TagNumber соответствует одному ElementName, а AttributeName является именем XML-атрибута (если оно задано).
Рассмотрение использования Directive и работы в нескольких ситуациях, в которых AttributeName может быть NULL, выходит за рамки данной статьи. Раздел «Using Explicit Mode» в SQL Server 2000 Books Online — превосходный источник дополнительной информации.
Кроме того, для формирования корректных XML-данных набор результатов должен быть упорядочен так, чтобы каждый родитель шел непосредственно перед своими потомками.
Вернемся к sptxValidateLookupData. Как вы помните, в описании процедуры говорилось о двух форматах возвращаемого набора результатов. Если все проверки данного пакета возвратили TRUE, я возвращаю пустой тэг . Но если какая-то проверка потерпела неудачу, я возвращаю XML-документ со списком ошибок.
В листинге 4 приведен код процедуры sptxValidateLookupData, который генерирует наборы результатов с помощью FOR XML EXPLICIT. Синтаксис режима EXPLICIT довольно многословен, поэтому рассмотрим его по частям. Первая ветвь оператора IF обрабатывает простую ситуацию, когда все мои проверки возвратили TRUE:
— Если все проверки на допустимость пройдены,
— возвращаем пустой набор XML-данных…
if not exists (select [TestResult] from
@tempValidateLookupData where TestResult = 0)
select 1 as TAG, 0 as parent,
NULL as [Results!1!]
for xml explicit
Листинг 4. Применение FOR XML EXPLICIT
— Если все проверки на допустимость пройдены,
— возвращаем пустой набор XML-данных…
if not exists (select [TestResult] from
@tempValidateLookupData where TestResult = 0)
select 1 as TAG, 0 as parent,
NULL as [Results!1!]
for xml explicit
— …иначе возвращаем XML-данные о проверках,
— потерпевших неудачу
else
select 1 as TAG, 0 as parent,
NULL as [Errors!1!],
NULL as [Error!2!],
NULL as [Error!2!ErrorMessage],
NULL as [Error!2!FieldName]
union all
select 2 as TAG, 1 as parent,
NULL,
NULL,
ltrim(rtrim(value)) + ‘ does not exist in ‘ + type,
[name]
from @tempValidateLookupData
where [TestResult] = 0
and test = ‘Exists’
union all
select 2 as TAG, 1 as parent,
NULL,
NULL,
ltrim(rtrim(value)) + ‘ already exists in ‘ + type,
[name]
from @tempValidateLookupData
where [TestResult] = 0
and test = ‘Not Exists’
for xml explicit
Поскольку AttributeName не задано, этот оператор создаст единственный XML-элемент Results без атрибутов и потомков:
Ветвь ELSE гораздо интереснее: в ней я формирую XML-данные о проверках, потерпевших неудачу, объединяя операторы SELECT с помощью UNION. Как показано в листинге 5, каждый запрос формирует узлы выходных XML-данных определенного типа (который описывается в комментариях после каждого запроса).
Листинг 5. Формирование узлов
— …иначе возвращаем XML-данные о проверках,
— потерпевших неудачу
else
select 1 as TAG, 0 as parent,
NULL as [Errors!1!],
NULL as [Error!2!],
NULL as [Error!2!ErrorMessage],
NULL as [Error!2!FieldName]
— (приведенный выше запрос формирует элемент <Errors>)
union all
select 2 as TAG, 1 as parent,
NULL,
NULL,
ltrim(rtrim(value)) + ‘ does not exist in ‘ + type,
[name]
from @tempValidateLookupData
where [TestResult] = 0
and test = ‘Exists’
— (приведенный выше запрос формирует узлы вида
— <Error ErrorMessage=»BO1 does not exist in Countries»
— FieldName=»CountryCode»/>)
union all
select 2 as TAG, 1 as parent,
NULL,
NULL,
ltrim(rtrim(value)) + ‘ exists in ‘ + type,
[name]
from @tempValidateLookupData
where [TestResult] = 0
and test = ‘Not Exists’
— (приведенный выше запрос формирует узлы вида
— <Error ErrorMessage=»JA exists in Countries»
— FieldName=»CountryCode»/>)
for xml explicit
Заметьте: запросы, объединенные UNION, упорядочены так, чтобы каждый потомок шел сразу за своим родителем, хотя узлы могут быть потомками нескольких подзапросов (у запросов «exists» и «not exists» поля tag и parent имеют одинаковые значения). Когда запросы, объединенные с помощью UNION, обрабатываются в режиме FOR XML EXPLICIT, сериализатор FOR XML вычисляет имена полей
[ElementName!TagNumber!AttributeName!Directive]
и значения полей метаданных Tag и Parent, а затем выводит XML-иерархию, заданную программистом:
<Errors>
<Error ErrorMessage=»JA exists in Countries»
FieldName=»CountryCode»/>
<Error ErrorMessage=»BO1 does not exist in Countries»
FieldName=»CountryCode»/>
<Error ErrorMessage=»EN does not exist in ContactPreferences»
FieldName=»ContactPreferenceCode»/>
</Errors>
Миссия выполнена
Имея в распоряжении описанные выше средства, вы можете запрашивать и генерировать XML-данные в среде SQL Server 2000. Но какими бы мощными ни были эти средства, SQL Server 2005 предоставит еще больше программных функций всем специалистам, обрабатывающим XML-данные с помощью T-SQL, и позволит добиться еще большей производительности.
XML-программирование в SQL Server 2005
При разработке SQL Server 2005 Microsoft значительно усовершенствовала поддержку XML. Последние два года я создавал новую систему на основе внутренних версий этого продукта (рай для SQL-разработчика!) и рад сообщить, что программистов, использующих XML, ждет масса хороших новостей.
Весь синтаксис поддержки XML, введенный в SQL Server 2000, не изменился, но в SQL Server 2005 в него внесена уйма дополнений. Я рассмотрю некоторые из них и покажу, как изменится хранимая процедура sptxValidateLookupData, рассмотренная в статье. Я также расскажу о следующих новшествах SQL Server 2005: о типах данных XML, FOR XML PATH, TYPE, синтаксисе nodes().
Все методики работы с XML, применяемые в SQL Server 2000 (передача XML-строк хранимым процедурам в параметрах типа ntext, манипулирование ими с помощью sp_xml_preparedocument, sp_xml_removedocument, FOR XML EXPLICIT и OPENXML), доступны и в SQL Server 2005, но в новой версии появились средства, позволяющие использовать другие подходы. Как только вы поработаете с новым синтаксисом, вам уже не захочется возвращаться к старому.
В SQL Server 2005 внесены революционные изменения в сам механизм хранения данных, в частности введены три новых типа данных: nvarchar(max), varbinary(max) и xml. В T-SQL возникали сложности с обработкой значений типа ntext, поэтому, если вы собираетесь по-прежнему использовать те же конструкции работы с XML, что и в SQL Server 2000, имеет смысл отказаться от ntext и перейти на nvarchar(max) и varbinary(max). Однако наиболее интересен тип данных XML, также добавленный в ядро сервера. Он предоставляет программистам ряд совершенно новых возможностей.
Переработанный пример
Как вы помните, хранимая процедура sptxValidateLookupData, рассмотренная в статье, поддерживает единый процесс пакетной проверки пользовательского ввода в Web-страницы, позволяющий выполнить несколько разных проверок на допустимость для значений, получаемых из гетерогенных источников. Директивы, описывающие проверки, передаются хранимой процедуре в одном XML-документе. Хранимая процедура выполняет проверки и возвращает результаты вызывающему процессу, тоже в одном XML-документе.
Новая версия процедуры
Как и в процедуре для SQL Server 2000, я помещаю содержимое входного XML-документа в табличную переменную. Но я больше не вызываю sp_xml_preparedocument и не применяю OPENXML. Как показано в листинге 6, я изменил тип данных параметра на xml (с ntext) и воспользовался новым синтаксисом nodes().
Листинг 6. Использование типа данных XML
create procedure sptxValidateLookupData
@XMLString xml
as
set nocount on
declare @idoc int, @Name nvarchar(30), @Value nvarchar(300),
@Test nvarchar(30), @Result int, @Type nvarchar(30),
@TestResult int
— Создаем табличную переменную для хранения
— данных о проверках
declare @tempValidateLookupData table (
[Type] nvarchar(30),
[Name] nvarchar(30),
[Value] nvarchar(300),
[Test] nvarchar(30),
[TestResult] int
)
— Заполняем табличную переменную данными о проверках,
— которые требуется выполнить
insert @tempValidateLookupData
select ref. value (‘@Type’, ‘[nvarchar](30)’),
ref.value (‘@Name’, ‘[nvarchar](30)’),
ref.value (‘@Value’, ‘[nvarchar](300)’),
ref.value (‘@Test’, ‘[nvarchar](30)’),
NULL
from @XMLString.nodes(‘/ValidateData/Validate’)
as node(ref)
Давайте повнимательнее рассмотрим метод nodes. Он позволяет получить ссылку для каждой записи, которая соответствует элементу Validate, находящемуся внутри элемента ValidateData переменной @XMLString. Эта переменная описывается инструкцией AS NODE(ref) как набор записей, представляющий узлы (node rowset). В каждом определении поля в операторе SELECT вызывается метод value, извлекающий значение заданного атрибута. Он выполняется для каждой записи, поэтому для каждого элемента Validate с параметрами проверки генерируется по одной записи.
В каждом вызове метода value указывается имя атрибута элемента, извлекаемого из XML-узла. Перед именем атрибута ставится символ @, и оно заключается в одинарные кавычки, затем (также в кавычках) указывается тип данных SQL, сопоставляемый атрибуту.
Логика выполнения проверок на допустимость в новой версии sptxValidateLookupData осталась прежней.
Возврат результатов
Как вы помните, в исходной спецификации процедуры описывались два формата возвращаемого набора записей. Если все проверки данного пакета возвратили TRUE, набор должен содержать пустой тэг . Однако, если какие-то проверки потерпели неудачу, нужно вернуть список XML-данных об ошибках.
В листинге 7 приведен новый код процедуры sptxValidateLookupData, генерирующий наборы результатов с помощью FOR XML PATH, TYPE. Обратите внимание, насколько этот синтаксис компактнее старого синтаксиса FOR XML EXPLICIT.
Листинг 7. Применение FOR XML PATH
— Если все проверки на допустимость пройдены,
— возвращаем пустой набор XML-данных…
if not exists (select [TestResult]
from @tempValidateLookupData
where TestResult = 0)
select null
for xml path (‘Results’), type
— …иначе возвращаем XML-данные о проверках,
— потерпевших неудачу
else
select null,
(
select
ltrim(rtrim(value)) + ‘ does not exist in ‘ +
type AS ‘@ErrorMessage’,
[name] AS ‘@FieldName’
from @tempValidateLookupData
where [TestResult] = 0
and test = ‘Exists’
for xml path (‘Error’), type
),
(
select
ltrim(rtrim(value)) + ‘ already exists in ‘ +
type AS ‘@ErrorMessage’,
[name] AS ‘@FieldName’
from @tempValidateLookupData
where [TestResult] = 0
and test = ‘Not Exists’
for xml path (‘Error’), type
)
for xml path (‘Errors’), type
Как и прежде, первая ветвь оператора IF обрабатывает простой случай, когда все проверки возвратили TRUE:
— Если все проверки на допустимость пройдены,
— возвращаем пустой набор XML-данных. ..
if not exists (select [TestResult] from
@tempValidateLookupData where TestResult = 0)
select null
for xml path (‘Results’), type
Ветвь ELSE, как и раньше, формирует XML-данные для проверок, потерпевших неудачу, но на сей раз с помощью нескольких вложенных операторов SELECT FOR XML PATH, TYPE. Явно заданные имена полей указывают SQL Server, что их нужно использовать в качестве имен XML-атрибутов (перед ними должен идти символ @, их надо заключить в одинарные кавычки). Директивы FOR XML PATH (‘Error’) указывают серверу, что требуется обернуть XML-данные, создаваемые внутренними операторами SELECT, элементом Error, а директива FOR XML PATH (‘Errors’) — что внешний SELECT формирует корневой элемент ‘Errors’. Таким образом, этот SQL-код генерирует тот же набор результатов, что и прежде, но с помощью гораздо более лаконичного запроса, чем запрос с FOR XML EXPLICIT.
Может, на первый взгляд это и не очевидно, но отказ от запросов SELECT, объединенных операторами UNION, выполняемых при использовании FOR XML EXPLICIT, делает код гетерогенных запросов гораздо компактнее и удобнее в сопровождении. Например, недавно моя группа переписала одну пользовательскую функцию SQL Server 2000 длиной в 5000 строк (большую их часть составлял 43-уровневый запрос с FOR XML EXPLICIT). Новый синтаксис позволил уложиться в 497 строк.
Если вы хотите по-прежнему придерживаться модели с UNION (что сомнительно), то можете написать второй запрос SELECT так, как показано в листинге 8. Этот подход не сработал бы, если бы ваши внутренние XML-узлы содержали разные количества атрибутов. Одно из основных преимуществ нового вложенного синтаксиса в том, что в отличие от операторов SELECT с UNION количество полей в подзапросах не обязательно должно быть одинаковым. Тем не менее, пример в листинге 8 демонстрирует еще одну новую конструкцию — FOR XML ROOT. Она позволяет объявить корневой элемент возвращаемых XML-данных, не создавая явный запрос SELECT. Дополнительные сведения по этому вопросу см. в статье «XML Options in Microsoft SQL Server 2005» (EN).
Листинг 8. Применение FOX XML ROOT
select
ltrim(rtrim(value)) + ‘ does not exist in ‘ +
type AS ‘@ErrorMessage’,
[name] AS ‘@FieldName’
from @tempValidateLookupData
where [TestResult] = 0
and test = ‘Exists’
union all
select
ltrim(rtrim(value)) + ‘ already exists in ‘ +
type AS ‘@ErrorMessage’,
[name] AS ‘@FieldName’
from @tempValidateLookupData
where [TestResult] = 0
and test = ‘Not Exists’
for xml path (‘Error’), root
(‘Errors’), type
С помощью этих новых средств SQL Server 2005 вы можете запрашивать и генерировать XML-данные еще эффективнее, чем раньше. Я рассмотрел лишь небольшую часть возможностей нового синтаксиса. SQL Server 2005 позволяет делать с XML-данными почти все, что угодно. Если вас интересуют ресурсы с самой свежей информацией о SQL Server 2005, посетите сайт «Introducing SQL Server 2005» (EN).
Оцените статью: Голосов 1
SQL EXISTS, SQL Subquery EXISTS — с примерами
Что делает WHERE EXISTS?
WHERE EXISTS проверяет наличие каких-либо записей в подзапросе.
EXISTS возвращает истину, если подзапрос возвращает одну или несколько записей.
Условие EXISTS обычно используется с коррелированными подзапросами.
Синтаксис SQL EXISTS
Общий синтаксис:
ВЫБЕРИТЕ имена столбцов ОТ имя-таблицы ГДЕ СУЩЕСТВУЕТ (ВЫБЕРИТЕ имя-столбца ОТ имя-таблицы ГДЕ условие)
ПОСТАВЩИК |
---|
Идентификатор |
Название компании |
Контактное имя |
Город |
Страна |
Телефон |
Факс |
ПРОДУКТ | |
---|---|
ProductName | |
SupplierId | |
UnitPrice | |
Package | |
Is Снят с производства |
SQL EXISTS
Пример
Задача: Найти поставщиков
с продуктами более 100 долларов.
ВЫБЕРИТЕ CompanyName ОТ поставщика ГДЕ СУЩЕСТВУЕТ (ВЫБЕРИТЕ ProductName ОТ продукта ГДЕ SupplierId = Supplier.Id И UnitPrice> 100)
Примечание. Это коррелированный подзапрос , поскольку подзапрос ссылается на включающий запрос (с Supplier.Id).
Результат: 2 записи
Название компании |
---|
Plutzer Lebensmittelgroßmärkte AG |
Aux joyeux ecclésiastiques |
СУЩЕСТВУЕТ (Transact-SQL) — SQL Server
- 5 минут на чтение
В этой статье
Применимо к: SQL Server (все поддерживаемые версии) База данных SQL AzureAzure SQL Managed InstanceAzure Synapse Analytics Хранилище параллельных данных
Задает подзапрос для проверки существования строк.
Соглашения о синтаксисе Transact-SQL
Синтаксис
СУЩЕСТВУЕТ (подзапрос)
Аргументы
подзапрос
Это ограниченный оператор SELECT. Ключевое слово INTO недопустимо. Для получения дополнительной информации см. Информацию о подзапросах в SELECT (Transact-SQL).
Типы результатов
логический
Значения результата
Возвращает TRUE, если подзапрос содержит какие-либо строки.
Примеры
А.Использование NULL в подзапросе для возврата набора результатов
В следующем примере возвращается набор результатов с NULL
, указанным в подзапросе, и все еще оценивается как ИСТИНА с использованием EXISTS
.
- Использует AdventureWorks
ВЫБЕРИТЕ ИД отдела, имя
ОТ HumanResources. Отдел
ГДЕ СУЩЕСТВУЕТ (ВЫБРАТЬ NULL)
ЗАКАЗАТЬ Имя ASC;
B. Сравнение запросов с использованием EXISTS и IN
В следующем примере сравниваются два семантически эквивалентных запроса. Первый запрос использует EXISTS
, а второй запрос использует IN
.
- Использует AdventureWorks
ВЫБЕРИТЕ a.FirstName, a.LastName
ОТ Person.Person КАК
ГДЕ СУЩЕСТВУЕТ
(ВЫБРАТЬ *
ОТ HumanResources.Сотрудник AS b
ГДЕ a.BusinessEntityID = b.BusinessEntityID
И a.LastName = 'Johnson');
ИДТИ
В следующем запросе используется IN
.
- Использует AdventureWorks
ВЫБЕРИТЕ a.FirstName, a.LastName
ОТ человека.Человек КАК
ГДЕ a.LastName IN
(ВЫБЕРИТЕ a.LastName
ОТ HumanResources.Сотрудник AS b
ГДЕ a.BusinessEntityID = b.BusinessEntityID
И a.LastName = 'Johnson');
ИДТИ
Вот набор результатов для любого запроса.
Имя Фамилия
-------------------------------------------------- ----------
Барри Джонсон
Дэвид Джонсон
Уиллис Джонсон
(3 строки затронуты)
С.Сравнение запросов с использованием EXISTS и = ANY
В следующем примере показаны два запроса для поиска магазинов, название которых совпадает с названием продавца. Первый запрос использует EXISTS
, а второй использует = `` ANY
.
- Использует AdventureWorks
ВЫБЕРИТЕ РАЗЛИЧНОЕ имя
ИЗ Sales.Store AS s
ГДЕ СУЩЕСТВУЕТ
(ВЫБРАТЬ *
ОТ Purchasing.Vendor AS v
ГДЕ s.Name = v.Name);
ИДТИ
В следующем запросе используется = ANY
.
- Использует AdventureWorks
ВЫБЕРИТЕ РАЗЛИЧНОЕ имя
ИЗ Sales.Store AS s
ГДЕ s.Name = ЛЮБОЙ
(ВЫБЕРИТЕ v.Name
ОТ Purchasing.Vendor AS v);
ИДТИ
D. Сравнение запросов с использованием EXISTS и IN
В следующем примере показаны запросы для поиска сотрудников отделов, имя которых начинается с P
.
- Использует AdventureWorks
ВЫБЕРИТЕ p.FirstName, p.LastName, e.JobTitle
ОТ Person.Person AS p
ПРИСОЕДИНЯЙТЕСЬ к HumanResources.Сотрудник AS e
НА e.BusinessEntityID = p.BusinessEntityID
ГДЕ СУЩЕСТВУЕТ
(ВЫБРАТЬ *
ОТ HumanResources. Отдел AS d
ПРИСОЕДИНЯЙТЕСЬ HumanResources. EmployeeDepartmentHistory AS edh
ON d.DepartmentID = edh.DepartmentID
ГДЕ e.BusinessEntityID = edh.BusinessEntityID
AND d.Name КАК 'P%');
ИДТИ
В следующем запросе используется IN
.
- Использует AdventureWorks
ВЫБЕРИТЕ p.FirstName, p.LastName, e.JobTitle
ОТ Person.Person AS p ПРИСОЕДИНЯЙТЕСЬ к HumanResources.Сотрудник AS e
НА e.BusinessEntityID = p.BusinessEntityID
ПРИСОЕДИНЯЙТЕСЬ HumanResources.EmployeeDepartmentHistory AS edh
НА e.BusinessEntityID = edh.BusinessEntityID
ГДЕ edh.
(ВЫБЕРИТЕ ИД отдела
ОТ HumanResources. Отдел
ГДЕ Имя LIKE 'P%');
ИДТИ
E. Использование NOT EXISTS
NOT EXISTS работает противоположно EXISTS. Предложение WHERE в NOT EXISTS выполняется, если подзапрос не возвращает ни одной строки. В следующем примере выполняется поиск сотрудников, не работающих в отделах, имена которых начинаются с P
.
ВЫБРАТЬ p.FirstName, p.LastName, e. JobTitle
ОТ Person.Person AS p
ПРИСОЕДИНЯЙТЕСЬ к HumanResources.Employee AS e
НА e.BusinessEntityID = p.BusinessEntityID
ГДЕ НЕ СУЩЕСТВУЕТ
(ВЫБРАТЬ *
ОТ HumanResources. Отдел AS d
ПРИСОЕДИНЯЙТЕСЬ HumanResources.EmployeeDepartmentHistory AS edh
ON d.DepartmentID = edh.DepartmentID
ГДЕ e.BusinessEntityID = edh.BusinessEntityID
И d.Имя КАК 'P%')
ЗАКАЗАТЬ ПО Фамилии, Имени
ИДТИ
Вот результат.
Имя Фамилия Заголовок
------------------------------ -------------------- ---------- ------------
Сайед Аббас, Тихоокеанский менеджер по продажам
Хазем Аболрус, менеджер по обеспечению качества
Умберто Асеведо, специалист по применению
Пилар Акерман Руководитель службы доставки и получения
Франсуа Аженстат Администратор базы данных
Эми Альбертс, менеджер по продажам в Европе
Шон Александр Техник по обеспечению качества
Памела Ансман-Вулф, торговый представитель
Зайнал Арифин Менеджер по контролю документов
Дэвид Барбер Помощник финансового директора
Паула Баррето де Маттос Менеджер по персоналу
Шай Бассли Менеджер по эксплуатации
Ванида Бенсхооф Ассистент по маркетингу
Карен Берг, специалист по применению
Карен Берге Помощник по контролю документов
Андреас Берглунд Специалист по обеспечению качества
Маттиас Берндт, ответственный за доставку и прием
Джо Берри Дворник
Джимми Бишофф Стокер
Майкл Блайт, торговый представитель
Дэвид Брэдли, менеджер по маркетингу
Кевин Браун Ассистент по маркетингу
Дэвид Кэмпбелл, торговый представитель
Джейсон Карлсон Менеджер информационных служб
Фернандо Каро, торговый представитель
Шон Чай Помощник по контролю документов
Sootha Charncherngkha Технический специалист по обеспечению качества
Хао Чен Помощник по кадровым вопросам
Кевин Крисулис Сетевой администратор
Пэт Коулман Дворник
Стефани Конрой Сетевой менеджер
Специалист по приложениям Debra Core
Ovidiu Crãcium Sr. Конструктор инструментов
Грант Калбертсон, помощник по управлению персоналом
Мэри Демпси Ассистент по маркетингу
Дизайнер инструментов Тьерри Д'Эрс
Терри Даффи, вице-президент по проектированию
Сьюзан Итон Стокер
Терри Эминхайзер Специалист по маркетингу
Гейл Эриксон, инженер-конструктор
Дженис Гэлвин Дизайнер инструментов
Мэри Гибсон, специалист по маркетингу
Йосеф Голдберг, инженер-конструктор
Сария Харнпадунгсатая Специалист по маркетингу
Марк Харрингтон, техник по обеспечению качества
Магнус Хедлунд Помощник по эксплуатации
Торговый представитель Шу Ито
Стивен Цзян, менеджер по продажам в Северной Америке
Уиллис Джонсон Рекрутер
Браннон Джонс Финансовый менеджер
Тенгиз Харатишвили Специалист по контролю
Кристиан Кляйнерман Начальник технического обслуживания
Вамси Куппа, ответственный за доставку и приемку
Дэвид Лю менеджер по работе с клиентами
Видур Лутра Рекрутер
Стюарт Макрэй Дворник
Дайан Маргхейм, инженер по исследованиям и разработкам
Минди Мартин, специалист по льготам
Джиджи Мэтью, инженер по исследованиям и разработкам
Торговый представитель Тете Менса-Аннан
Рамеш Мейяппан, специалист по применению
Дилан Миллер, менеджер по исследованиям и развитию
Линда Митчелл, торговый представитель
Барбара Морленд Бухгалтер
Лаура Норман Финансовый директор
Крис Норред Специалист по контролю
Торговый представитель Дже Пак
Ванда Паркс Дворник
Дебора По, специалист по дебиторской задолженности
Ким Раллс Стокер
Цви Рейтер Торговый представитель
Шэрон Салавария, инженер-конструктор
Кен Санчес Главный исполнительный директор
Хосе Сараива, торговый представитель
Майк Симанс Бухгалтер
Администратор сети Ашвини Шарма
Джанет Шепердигиан Специалист по счетам к оплате
Candy Spoon Специалист по дебиторской задолженности
Майкл Салливан-старшийИнженер-проектировщик
Драган Томич Специалист по кредиторской задолженности
Линн Цофлиас Торговый представитель
Рэйчел Вальдес, торговый представитель
Торговый представитель Гарретта Варгара
Ранджит Варки Чудукатил Торговый представитель
Брайан Уолтон, специалист по дебиторской задолженности
Цзянь Шо Ван Технический менеджер
Брайан Велкер, вице-президент по продажам
Джилл Уильямс, специалист по маркетингу
Дэн Уилсон, администратор базы данных
Специалист по маркетингу Джона Вуда
Пэн У Супервайзер по обеспечению качества
(91 строка (и) затронута)
Примеры: Azure Synapse Analytics и хранилище параллельных данных
Ф.
Использование EXISTS
В следующем примере определяется, могут ли какие-либо строки в таблице ProspectiveBuyer
совпадать со строками в таблице DimCustomer
. Запрос вернет строки только в том случае, если значения LastName
и BirthDate
в двух таблицах совпадают.
- Использует AdventureWorks
ВЫБЕРИТЕ a.LastName, a.BirthDate
ОТ DimCustomer КАК
ГДЕ СУЩЕСТВУЕТ
(ВЫБРАТЬ *
ОТ dbo.ProspectiveBuyer AS b
ГДЕ (a.LastName = b.Фамилия) И (a.BirthDate = b.BirthDate));
G. Использование NOT EXISTS
NOT EXISTS работает как противоположность EXISTS. Предложение WHERE в NOT EXISTS выполняется, если подзапрос не возвращает ни одной строки. В следующем примере выполняется поиск строк в таблице DimCustomer
, где LastName
и BirthDate
не соответствуют никаким записям в таблице ProspectiveBuyers
.
- Использует AdventureWorks
ВЫБЕРИТЕ a. LastName, a.Дата рождения
ОТ DimCustomer КАК
ГДЕ НЕ СУЩЕСТВУЕТ
(ВЫБРАТЬ *
ОТ dbo.ProspectiveBuyer AS b
ГДЕ (a.LastName = b.LastName) AND (a.BirthDate = b.BirthDate));
См. Также
Выражения (Transact-SQL)
Встроенные функции (Transact-SQL)
WHERE (Transact-SQL)
Как работают операторы SQL EXISTS?
Модель таблицы базы данных
Предположим, у нас есть следующие две таблицы в нашей базе данных, которые образуют связь между таблицами «один ко многим».
Таблица student,
является родительской, а таблица student_grade
является дочерней, поскольку в ней есть столбец внешнего ключа student_id, ссылающийся на столбец первичного ключа id в таблице учеников.
Таблица студентов
содержит следующие две записи:
| id | first_name | last_name | admission_score |
| ---- | ------------ | ----------- | ----------------- |
| 1 | Алиса | Смит | 8. 95 |
| 2 | Боб | Джонсон | 8.75 |
И таблица student_grade
хранит оценки, полученные учащимися:
| id | class_name | сорт | student_id |
| ---- | ------------ | ------- | ------------ |
| 1 | Математика | 10 | 1 |
| 2 | Математика | 9,5 | 1 |
| 3 | Математика | 9,75 | 1 |
| 4 | Наука | 9,5 | 1 |
| 5 | Наука | 9 | 1 |
| 6 | Наука | 9.25 | 1 |
| 7 | Математика | 8.5 | 2 |
| 8 | Математика | 9.5 | 2 |
| 9 | Математика | 9 | 2 |
| 10 | Наука | 10 | 2 |
| 11 | Наука | 9,4 | 2 |
СУЩЕСТВУЕТ SQL
Допустим, мы хотим получить всех учеников, получивших 10 баллов по математике.
Если нас интересует только идентификатор студента, мы можем запустить такой запрос:
ВЫБРАТЬ
student_grade.student_id
ИЗ
student_grade
КУДА
student_grade.grade = 10 И
student_grade.class_name = 'Математика'
СОРТИРОВАТЬ ПО
student_grade.student_id
Но приложение заинтересовано в отображении полного имени ученика
, а не только идентификатора, поэтому нам также нужна информация из таблицы student
.
Чтобы отфильтровать записи учеников
с 10 оценками по математике, мы можем использовать оператор EXISTS SQL, например:
ВЫБРАТЬ
id, first_name, last_name
ИЗ
ученик
ГДЕ СУЩЕСТВУЕТ (
ВЫБРАТЬ 1
ИЗ
student_grade
КУДА
student_grade.student_id = student.id И
student_grade.grade = 10 И
student_grade.class_name = 'Математика'
)
ЗАКАЗАТЬ ПО id
При выполнении вышеуказанного запроса мы видим, что выбрана только строка Алисы:
| id | first_name | last_name |
| ---- | ------------ | ----------- |
| 1 | Алиса | Смит |
Внешний запрос выбирает столбцы строки student
, которые мы хотим вернуть клиенту. Однако предложение WHERE использует оператор EXISTS со связанным внутренним подзапросом.
Оператор EXISTS возвращает истину, если подзапрос возвращает хотя бы одну запись, и ложь, если строка не выбрана. Механизм базы данных не должен полностью выполнять подзапрос. Если совпадает одна запись, оператор EXISTS возвращает true, и выбирается связанная другая строка запроса.
Внутренний подзапрос коррелирован, поскольку столбец student_id таблицы student_grade
сопоставляется со столбцом id внешней таблицы student.
Как использовать SQL СУЩЕСТВУЕТ И НЕ СУЩЕСТВУЕТ SQL-функции?
Введение
Назначение операторов SQL «Существует» и «Не существует» — проверить наличие записей в подзапросе.Еще один похожий оператор — это предложение with, которое было введено в 1999 году для поддержки функций CTE (Common Table Expressions). Эти операторы предопределены в SQL и используются вместе с операторами UPDATE, DELETE или SELECT. Операторы SQL Exists и Not Exists следует использовать вместе, поскольку они не являются независимыми сами по себе.
Когда SQL Exists используется вместе с предложением Where, он проверяет наличие строк в подзапросе.
- Если этот подзапрос содержит строку, он возвращает ИСТИНА.
- Оператор Exists аналогичен оператору IN в SQL, и их вывод почти такой же, но синтаксис отличается.
- Можно использовать оператор Exists с операторами UPDATE, DELETE или SELECT.
Читайте: Служба отчетов SQL Server: все, что вам нужно знать о параметризованных отчетах
Базовый синтаксис оператора SQL Exists приведен ниже.
- Здесь вы должны указать имя столбца таблицы.
- Выражения могут быть одной константой, переменной, скалярной функцией, именем столбца или частями SQL-запроса, который сравнивает значения и при необходимости выполняет арифметические вычисления.
- Во второй строке кода вы должны добавить имя таблицы.
- Последняя строка кода проверяет наличие одной или нескольких строк в подзапросе. Когда единственная строка удовлетворяет условию, она возвращает логическое значение True. Если совпадающих строк нет, возвращается логическое значение False, в противном случае вы также можете использовать оператор «Not Exists».
Чтение: Типы данных SQL для Oracle PL / SQL, MySQL, SQL Server и MS Access
Слово подзапроса до сих пор использовалось несколько раз.Вы действительно знаете значение подзапроса в SQL? Если нет, не волнуйтесь. Мы кратко обсудим, что такое подзапрос SQL, прежде чем углубляться в детали.
Что такое подзапрос в SQL?
Подзапрос также называется внутренним запросом или вложенным запросом, который часто используется в других запросах. Подзапрос SQL может быть вложен в несколько операторов, таких как операторы SELECT, INSERT, UPDATE или DELETE и т. Д. В основном мы используем подзапрос в SQL с предложениями Where и Exists.Вот несколько основных правил использования подзапросов в SQL.
- Каждый подзапрос следует заключать в круглые скобки.
- Мы не можем использовать предложение Order By в подзапросе, пока мы не будем использовать предложение TOP.
- Каждый подзапрос должен включать обычный оператор SELECT.
- Предложения «Have», «Where», «Group By» могут использоваться необязательно в подзапросе.
- Вы не можете использовать предложение Compute в подзапросе.
- Подзапрос обычно вложен в предложения WHERE и Have или внешние операторы, такие как SELECT, INSERT, UPDATE, DELETE и т. Д.
- SQL-сервер позволяет размещать подзапросы до 32 уровней. Он может варьироваться в зависимости от требований.
Чтобы получить больше знаний о подзапросах в SQL, присоединяйтесь к нашим онлайн-урокам для самостоятельного изучения сегодня с огромной скидкой.
Изучите SQL Server самым простым способом
- Учитесь на видео
- Учитесь в любое время в любом месте
- Карманный режим обучения
- Доступна бесплатная электронная книга
Оператор SQL Exists с примером
Для более глубокого понимания оператора SQL «Exists» рассмотрим приведенный ниже пример. Есть две таблицы, в одной из которых хранятся сведения о сотрудниках, а во второй — ежемесячная заработная плата сотрудников. Давайте посмотрим, как использовать оператор «Exists» с этими двумя таблицами. В таблице вы можете увидеть три набора фиктивных данных. Здесь первая таблица хранит данные о сотрудниках, вторая таблица хранит зарплату, выплаченную сотрудникам, а третья таблица хранит результат для запроса «Существует». В третьей таблице вы можете увидеть, что всего возвращается пять записей, и каждая из них имеет уникальный идентификатор сотрудника, который сравнивается вместе для обеих таблиц.
Если есть какой-либо идентификатор, который не существует в обеих таблицах, тогда результатом будет ЛОЖЬ. Например, идентификатор «6» указан в первой таблице, но не упомянут во второй таблице, поэтому он не отображается в качестве выходных данных в таблице Exists.
Оператор «IN» в SQL
Оператор IN также может использоваться для получения того же вывода. Но вопрос в том, какой оператор больше подходит для разных ситуаций? Если подзапрос возвращает очень большой набор записей, тогда здесь отлично работает оператор Exists. Однако, если набор записей меньше, в этом случае необходимо использовать оператор IN.
Прочтите: что такое ключ кандидата SQL? Разница между первичным ключом и ключом-кандидатом
Оператор «Не существует» в SQL
Оператор «Не существует» работает противоположно оператору «Существует». Это означает, что строки не возвращаются, когда выполняется оператор «Не существует». Давайте разберемся в концепции с помощью того же примера, приведенного ранее. Выход здесь будет противоположным. В приведенной выше таблице Exists эти две записи были опущены, и для извлечения этих двух строк следует использовать оператор Not Exists.Такой же вывод дает оператор «Not IN» в SQL, поскольку он работает противоположно оператору «IN».
Существуют операторы счетчика в SQL
Оператор счетчика используется для проверки общего количества строк в таблице, в то время как оператор Exists используется для проверки наличия строк при выполнении определенного условия. Проще говоря, оператор «Существует» может выполнить короткое замыкание после того, как найдет первую совпадающую строку, в то время как «Счетчик» не может показывать такое поведение.
Обучение и сертификация по SQL Server
- Демонстрационный класс бесплатно
- Промышленный эксперт в качестве вашего инструктора
- Доступно по вашему расписанию
- Служба поддержки клиентов
База данных SQL работает немного лучше при использовании оператора Exists вместо оператора Count из-за гораздо лучшей оценки количества элементов в середине плана выполнения.Каждый раз, когда вы хотите проверить строку на наличие, вы всегда должны использовать оператор Exists в этом случае. Кроме того, связанные с этим затраты с оператором Exists почти в 30 раз меньше, чем с оператором Count.
«Очевидно, что проверка существования выполняется быстрее, чем подсчет всех строк вместе, если вы действительно делаете что-то только для существования».
Рекомендации по производительности с Exists Operator
Каждый оператор SQL имеет значение для повышения производительности запроса.Оператор SQL работает с элементами данных и возвращает результат. Oracle использует операторы в разных условиях, которые можно использовать с запросами для фильтрации набора результатов. В то же время оператор Exists обеспечивает наилучшую производительность, когда запрос содержит объемные данные для оценки.
Чтение: различные типы ключей SQL: пример и использование
Причина в том, что оператор Exists следует принципу «по крайней мере найден» в запросах. Он устанавливается в значение ИСТИНА, если условию удовлетворяет даже одна строка. В некоторых случаях он останавливает выполнение в том же месте, где для результата устанавливается значение ИСТИНА.Однако вы должны использовать операторы сравнения с Exists, чтобы продолжить сканирование таблицы.
Заключение
На этом обсуждение мы подошли к концу блога. Здесь вы познакомитесь с основами оператора SQL Exists и узнаете, как его использовать с запросами SQL. Мы также обсудили один подробный пример для вашей справки, чтобы глубже понять концепцию. Но для практики этого оператора недостаточно одного примера.
Чтобы изучить несколько примеров SQL Exists, вам следует сразу же присоединиться к онлайн-программе сертификации SQL и быстро начать практиковать разные операторы.Это поможет вам практически выучить SQL и получить работу в области SQL с привлекательными пакетами заработной платы.
Зарегистрируйтесь на наш демо-класс сегодня, чтобы получить более подробную информацию!
Прочитано: 100 самых популярных вопросов и ответов на собеседовании по SQL
Обзор учебного пособия по SQL
Введение
Оператор и функции SQL Server
Ключи SQL Server
Запросы SQL Server
Дифференциация
Карьера
Интервью
Полезный ресурс
Учебник
Курс SQL Server
Предстоящие партии
Популярные курсы
AWS
- AWS и основы Linux
- Amazon Simple Storage Service
- Эластичное вычислительное облако
- Обзор баз данных и Amazon Route 53
Предстоящий класс
0 день 12 фев 2021
DevOps
- Введение в DevOps
- GIT и Maven
- Дженкинс и Ansible
- Докер и облачные вычисления
Предстоящий класс
0 день 12 фев 2021
Наука о данных
- Введение в науку о данных
- Обзор Hadoop и Spark
- Python и введение в программирование на R
- Машинное обучение
Предстоящий класс
21 день 05 мар. 2021
Hadoop
- Архитектура, HDFS и MapReduce
- Оболочка Unix и установка Apache Pig
- Установка HIVE и пользовательские функции
- Установка SQOOP и Hbase
Предстоящий класс
7 дней 19 фев 2021
Salesforce
- Введение в конфигурацию Salesforce
- Процессы безопасности и автоматизации
- Облако продаж и обслуживания
- Программирование Apex, SOQL и SOSL
Предстоящий класс
8 дней 20 фев 2021
QA
- Введение и тестирование программного обеспечения
- Жизненный цикл тестирования программного обеспечения
- Автоматизация тестирования и тестирования API
- Разработка фреймворка Selenium с использованием тестирования
Предстоящий класс
0 день 12 фев 2021
Бизнес-аналитик
- BA и обзор заинтересованных сторон
- BPMN, выявление требований
- BA Инструменты и проектная документация
- Анализ предприятия, Agile и Scrum
Предстоящий класс
0 день 12 фев 2021
MS SQL Server
- Введение и запрос к базе данных
- Программирование, индексы и системные функции
- Процедуры разработки пакетов служб SSIS
- Дизайн отчета SSRS
Предстоящий класс
7 дней 19 фев 2021
Python
- Особенности Python
- Редакторы Python и IDE
- Типы данных и переменные
- Операция с файлом Python
Предстоящий класс
8 дней 20 фев 2021
Искусственный интеллект
- Компоненты AI
- Категории машинного обучения
- Рекуррентные нейронные сети
- Рекуррентные нейронные сети
Предстоящий класс
15 дней 27 фев 2021
Машинное обучение
- Введение в машинное обучение и Python
- Машинное обучение: обучение с учителем
- Машинное обучение: обучение без учителя
Предстоящий класс
28 дней 12 мар. 2021
Таблица
- Знакомство с Tableau Desktop
- Методы преобразования данных
- Настройка сервера таблиц
- Интеграция с R & Hadoop
Предстоящий класс
5 дней 17 фев 2021
— Выберите курс -SalesforceAzureQA TestingSQL ServerБизнес-аналитикHadoopAWSDevOpsНаука о данныхJavaЦифровой маркетингDotnetPMPSeleniumСтоит посетитьМашинное обучениеPythonOracle DBADАналитик данныхТаблицаauSixmaScrum MasterBlockchainИскусственный интеллект7AndroidCyber SecurityVMware 9000
— Категория — СтатьяУчебникиВопросы для интервью
— Выберите время -На этой неделе, в этом месяце, в этом годуСамые популярные
Курс SQL Server
Предстоящие партии
Получать последние материалы и предложения по курсу SQL Server
SQL EXISTS Оператор
Оператор SQL EXISTS используется для ограничения количества строк, возвращаемых оператором SELECT. Оператор EXISTS в SQL проверяет наличие строк в подзапросе и, если они есть, возвращает TRUE, в противном случае — FALSE.
Синтаксис оператора SQL EXISTS
Базовый синтаксис оператора EXISTS в SQL Server можно записать как:
SELECT [имена столбцов] ОТ [Источник] ГДЕ СУЩЕСТВУЕТ (написать подзапрос для проверки)
- Столбцы: Позволяет нам выбрать количество столбцов из таблиц. Это может быть Один или несколько.
- Источник: Одна или несколько таблиц, присутствующих в базе данных.SQL JOINS используются для объединения нескольких таблиц.
- Подзапрос: Здесь мы должны предоставить подзапрос. Если подзапрос возвращает истину, он вернет записи, в противном случае SQL Server не вернет никаких записей.
Для этой демонстрации EXISTS Operator мы собираемся использовать показанные ниже данные
Пример оператора SQL EXISTS 1
Следующий запрос оператора Exists найдет всех сотрудников, присутствующих в таблице сотрудников, у которых [Продажи] больше 1000
СОВЕТ: Прежде чем перейти к этому примеру оператора Sql Server Exists, я предлагаю вам обратиться к статье «Подзапросы SQL», чтобы понять проектирование подзапросов и анализ запросов.
- Пример для оператора EXISTS SQL Server ИСПОЛЬЗУЙТЕ [Учебное пособие по SQL] ИДТИ ВЫБЕРИТЕ EMP1. [EmpID] , EMP1. [Имя] , EMP1. [Фамилия] , EMP1. [Образование] , EMP1. [Профессия] , EMP1. [Годовой доход] , EMP1. [Продажи] , EMP1. [HireDate] ОТ [Сотрудник] AS EMP1 ГДЕ СУЩЕСТВУЕТ (ВЫБРАТЬ * ОТ [Сотрудник] КАК EMP2 ГДЕ EMP1. [EmpID] = EMP2. [EmpID] И [Продажи]> 1000 )
Позвольте мне показать вам результат подзапроса
Позвольте мне изменить условие на Sales = 1000, что является ложным условием
- Пример для оператора EXISTS SQL Server ИСПОЛЬЗУЙТЕ [Учебное пособие по SQL] ИДТИ ВЫБЕРИТЕ EMP1.[EmpID] , EMP1. [Имя] , EMP1. [Фамилия] , EMP1. [Образование] , EMP1. [Профессия] , EMP1. [Годовой доход] , EMP1. [Продажи] , EMP1. [HireDate] ОТ [Сотрудник] AS EMP1 ГДЕ СУЩЕСТВУЕТ (ВЫБРАТЬ * ОТ [Сотрудник] КАК EMP2 ГДЕ EMP1. [EmpID] = EMP2. [EmpID] И [Продажи] = 1000 )
Как вы можете видеть, запрос возвращает пустые записи, потому что подзапрос возвращает ложь. Позвольте нам показать вам еще один пример для лучшего понимания.
EXISTS Пример оператора 2
Следующий запрос SQL существует для поиска всех сотрудников в таблице сотрудников, чья [профессия] равна Management
- Пример для оператора EXISTS SQL Server ИСПОЛЬЗУЙТЕ [Учебное пособие по SQL] ИДТИ ВЫБЕРИТЕ EMP1.[EmpID] , EMP1. [Имя] , EMP1. [Фамилия] , EMP1. [Образование] , EMP1. [Профессия] , EMP1. [Годовой доход] , EMP1. [Продажи] , EMP1. [HireDate] ОТ [Сотрудник] AS EMP1 ГДЕ СУЩЕСТВУЕТ (ВЫБРАТЬ * ОТ [Сотрудник] КАК EMP2 ГДЕ EMP1. [EmpID] = EMP2. [EmpID] И [Профессия] = "Менеджмент" )
EXISTS Пример оператора 3
Следующий запрос SQL существует оператор найдет всех сотрудников, присутствующих в таблице сотрудников, чья профессия — менеджмент, профессиональный или канцелярский.Здесь мы собираемся использовать оператор SQL IN внутри SubQuery
.
- Пример для оператора EXISTS SQL Server ИСПОЛЬЗУЙТЕ [Учебное пособие по SQL] ИДТИ ВЫБЕРИТЕ EMP1. [EmpID] , EMP1. [Имя] , EMP1. [Фамилия] , EMP1. [Образование] , EMP1. [Профессия] , EMP1. [Годовой доход] , EMP1. [Продажи] , EMP1. [HireDate] ОТ [Сотрудник] AS EMP1 ГДЕ СУЩЕСТВУЕТ (ВЫБРАТЬ * ОТ [Сотрудник] КАК EMP2 ГДЕ EMP1. [EmpID] = EMP2. [EmpID] И [Профессия] IN («Менеджмент», «Профессиональный», «Канцелярский») )
EXISTS Пример оператора 4
Вы можете спросить, почему я использую EMP1.[EmpID] = EMP2. [EmpID] внутри подзапроса. Итак, позвольте мне удалить эту строку и посмотреть
- Пример для оператора EXISTS SQL Server ИСПОЛЬЗУЙТЕ [Учебное пособие по SQL] ИДТИ ВЫБЕРИТЕ EMP1. [EmpID] , EMP1. [Имя] , EMP1. [Фамилия] , EMP1. [Образование] , EMP1. [Профессия] , EMP1. [Годовой доход] , EMP1. [Продажи] , EMP1. [HireDate] ОТ [Сотрудник] AS EMP1 ГДЕ СУЩЕСТВУЕТ (ВЫБРАТЬ * ОТ [Сотрудник] КАК EMP2 ГДЕ [Профессия] IN («Менеджмент», «Профессиональный», «Канцелярский») )
Как видно из приведенного ниже снимка экрана, этот SQL-запрос возвращает все записи, присутствующие в выбранной таблице. Потому что подзапрос возвращает ИСТИНА
Рассмотрите возможность использования [NOT] EXISTS вместо [NOT] IN с подзапросом (PE019)
- Подсказка SQL
- Анализ кода SQL
Фил Фактор объясняет, почему вы должны предпочесть использование [НЕ] СУЩЕСТВУЕТ, а не [НЕ] IN, при сравнении наборов данных с помощью подзапроса.Хотя существенного преимущества в производительности больше нет, использование NOT EXISTS позволит избежать непредвиденных результатов, когда исходные данные подзапроса содержат значения NULL.
Гостевой пост
Это гостевой пост от Фила Фактора. Фил Фактор (настоящее имя не разглашается для защиты виновных), также известный как Database Mole, имеет 30-летний опыт работы с приложениями, интенсивно использующими базы данных.
Несмотря на то, что однажды на выставке в начале 1980-х на него кричал разъяренный Билл Гейтс, он оставался абсолютно анонимным на протяжении всей своей карьеры.
Он является постоянным участником Simple Talk и SQLServerCentral .
Раньше логический оператор EXISTS был быстрее, чем IN, при сравнении наборов данных с помощью подзапроса. Например, в случаях, когда запрос должен был выполнить определенную задачу, но только если подзапрос вернул какие-либо строки, тогда при оценке WHERE [NOT] EXISTS (подзапрос) ядро базы данных может прекратить поиск, как только найдет только одну row, тогда как WHERE [NOT] IN (подзапрос) будет всегда собирать все результаты подзапроса перед дальнейшей обработкой.
Однако оптимизатор запросов теперь обрабатывает EXISTS и IN одинаково, когда это возможно, поэтому вы вряд ли заметите какие-либо существенные различия в производительности. Тем не менее, вы должны быть осторожны при использовании оператора NOT IN, если исходные данные подзапроса содержат значения NULL. В таком случае вам следует рассмотреть возможность использования оператора NOT EXISTS вместо NOT IN или преобразовать оператор в левое внешнее соединение.
Рекомендация предпочитать использование [NOT] EXISTS перед [NOT] IN »включена в качестве правила анализа кода в запрос SQL (PE019).
Что работает лучше: EXISTS или IN….?
Существует множество способов устранения различий между двумя наборами данных, но два из наиболее распространенных — использование логического оператора EXISTS
или IN
. Представьте, что у нас есть две простые таблицы: одна со всеми общеупотребительными словами английского языка ( CommonWords,
), а другая со списком всех слов из «Дракулы» Брэма Стокера ( WordsInDracula
). Загрузка TestExistsAndIn включает сценарий для создания этих двух таблиц и заполнения каждой из связанных с ней текстовых файлов.Как правило, полезно иметь такие таблицы на вашем сервере песочницы для запуска тестов во время разработки, хотя книга, которую вы используете, — это ваш выбор!
Сколько слов в Дракуле не являются общеупотребительными? Предполагая, что в столбце CommonWords. Word
нет значений NULL
(подробнее об этом позже), следующие запросы вернут тот же результат (1555 слов) и будут иметь тот же план выполнения, который использует объединение слиянием . (Правое анти-полусоединение) между двумя столами.
—использование NOT IN SELECT Count (*) FROM dbo.WordsInDracula WHERE word NOT IN (SELECT CommonWords.word FROM dbo.CommonWords); —Использование NOT EXISTS SELECT Count (*) FROM dbo.WordsInDracula WHERE NOT EXISTS (SELECT * FROM dbo.CommonWords WHERE CommonWords.word = WordsInDracula.слово); |
Листинг 1
Короче говоря, оптимизатор SQL Server обрабатывает оба запроса одинаково, и они будут выполнять то же самое.
… или ЛЮБОЙ, КРОМЕ, INNER JOIN, OUTER JOIN или INTERSECT…?
А как насчет всех других возможных методов, таких как использование ANY
, EXCEPT
, INNER
JOIN
, OUTER
JOIN
или INTERSECT
? В листинге 2 показаны еще семь альтернатив, которые я мог легко придумать, хотя будут и другие.
1 2 3 4 5 6 7 8 9 10 11 12 13 140004 14 18 19 20 21 22 23 24 25 26 27 28 29 30 34 35 36 37 38 39 40 41 42 43 44 45 46 48 51 52 53 54 55 56 57 58 59 60 61 | — использование ЛЮБОГО SELECT Count (*) FROM dbo.WordsInDracula ГДЕ НЕТ (WordsInDracula.word = ЛЮБОЕ (ВЫБЕРИТЕ слово ИЗ общих слов)); — Правое соединение с полуслияниями — с использованием EXCEPT SELECT Count (*) FROM ( SELECT word FROM dbo. WordsInDracula EXCEPT 9000 word dbo.CommonWords ) AS JustTheUncommonOnes; — Правое анти-полуслитое соединение —использование ЛЕВОГО ВНЕШНЕГО СОЕДИНЕНИЯ SELECT Count (*) FROM dbo.WordsInDracula ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ dbo.CommonWords ON CommonWords.word = WordsinDracula.word ГДЕ CommonWords.word IS NULL; — правое внешнее объединение слиянием — использование ПОЛНОГО ВНЕШНЕГО СОЕДИНЕНИЯ SELECT Count (*) FROM dbo.WordsInDracula full OUTER JOIN dbo.CommonWords ON CommonWords.word.word = WordsinDracula ГДЕ CommonWords.word ЕСТЬ NULL; —Полное внешнее соединение реализовано как соединение слиянием. — использование пересечения для получения разницы SELECT (SELECT Count (*) FROM WordsInDracula) -Count (*) FROM ( SELECT word FROM dbo.WordsInDracula correct ВЫБЕРИТЕ слово ИЗ dbo. CommonWords ) AS JustTheUncommonOnes; — внутреннее объединение слиянием — использование синтаксиса FULL OUTER JOIN для получения разницы SELECT Count (*) — (SELECT Count (*) FROM CommonWords) FROM dbo.WordsInDracula full OUTER JOIN dbo.CommonWords ON CommonWords.word = WordsinDracula.word — полное внешнее объединение слиянием — использование синтаксиса INNER JOIN для получения разницы SELECT (SELECT Count (*) FROM WordsinDracula) -Count (*) FROM dbo.WordsInDracula INNER JOIN dbo.CommonWords ON CommonWords.word = WordsinDracula.word — внутреннее объединение слиянием |
Листинг 2
Испытательная привязь
Все девять запросов дают одинаковые результаты, но работает ли какой-либо один подход лучше? Давайте поместим их всех в простую систему тестирования, чтобы увидеть, сколько времени занимает каждая версия! Опять же, файл загрузки кода включает в себя код тестовой оснастки и все девять запросов.
Как показывают результаты, хотя запросы выглядят по-разному, обычно это просто «синтаксический сахар» для оптимизатора. Каким бы элегантным ни был ваш SQL, оптимизатор просто пожимает плечами и предлагает эффективный план его выполнения. Фактически, первые четыре используют один и тот же план выполнения «правильное противополу слияния», и все они занимают одинаковое количество времени.
Мы проверим вариации, запустив тест несколько раз. Запросы INTERSECT
и INNER JOIN
использовали внутреннее соединение слиянием и были близки.Два запроса FULL OUTER JOIN
были немного медленнее, но это была близкая гонка.
Ловушка НЕ В
Есть определенная нереальность в сравнении наборов с нулевыми значениями в них, но если это происходит в разгар повседневной отчетности базы данных, все может пойти очень плохо. Если у вас есть значение NULL
в результате подзапроса или выражения, которое передается логическому оператору IN
, он даст разумный ответ и будет таким же, как эквивалент EXISTS
. Однако НЕ В
ведет себя совершенно иначе.
Листинг 3 демонстрирует проблему. Мы вставляем три общих и три необычных слова в табличную переменную @someWord
и хотим узнать количество общих слов, которых нет в нашей табличной переменной.
1 2 3 4 5 6 7 8 9 10 11 12 13 140004 14 18 19 20 21 22 23 24 25 26 27 28 29 30 34 35 36 37 38 39 40 41 42 43 44 45 46 48 51 52 53 54 55 56 57 | УСТАНОВИТЬ БЕЗ СЧЕТА; DECLARE @someWord TABLE ( word NVARCHAR (35) NULL ); INSERT INTO @someWord ( word ) — три общих слова SELECT TOP 3 word FROM dbo. общие слова ORDER BY word DESC; — три необычных слова INSERT INTO @someWord ( word ) ЗНАЧЕНИЯ (‘flibberty’), (‘jibberty ), b0004 (‘ jibberty ) ; SELECT [НЕ СУЩЕСТВУЕТ без NULL] = COUNT (*) FROM commonwords AS MyWords WHERE NOT EXISTS ( SELECT word FROM @someWord AS s WHERE s.word LIKE MyWords.слово ); SELECT [NOT IN без NULL] = COUNT (*) FROM commonwords AS MyWords WHERE word NOT IN ( SELECT word FROM @someWord ); —Вставить значение NULL INSERT INTO @someWord ( word ) VALUES (NULL); SELECT [NOT EXISTS with NULL] = COUNT (*) FROM commonwords AS MyWords WHERE NOT EXISTS ( SELECT word FROM @someWord AS s WHERE s.word LIKE MyWords.word ); SELECT [NOT IN with NULL] = COUNT (*) FROM commonwords AS MyWords WHERE word NOT IN ( SELECT word FROM @someWord ); |
Листинг 3.
Запрос NOT
IN
, прежде чем мы вставили NULL
в какое-то слово @
, и оба запроса NOT
EXISTS
, все правильно говорят нам, что 60385 слов нет в нашей табличной переменной, потому что три есть, а всего существует 60388 общих слов.Однако, если подзапрос может вернуть NULL
, то NOT
IN
вообще не возвращает строк.
NULL
на самом деле означает «неизвестно», а не ничего, поэтому любое выражение, которое сравнивается со значением NULL
, возвращает NULL
или unknown.
Логически SQL Server оценивает подзапрос, заменяет его списком возвращаемых значений, а затем оценивает условие [НЕ]
IN
.Для варианта IN
нашего запроса это не вызывает проблемы, потому что решает следующее:
ГДЕ word = ‘flibberty’ OR word = ‘jibberty’ OR word = ‘flob’ OR word = ‘zygotes’ OR word = ‘zygote’ OR word = ‘zydeco’ OR word = NULL; |
Возвращает 3 строки для совпадений по словам «z…». Жало идет с НЕ
В
, что разрешает следующее:
ГДЕ слово <> ‘flibberty’ И слово <> ‘jibberty’ И слово <> ‘flob’ И слово <> ‘zygotes’ И слово <> ‘zygote’ И слово <> ‘zydeco’ И слово <> NULL; |
Условие AND
при сравнении с NULL
оценивается как «неизвестно», и поэтому выражение всегда будет возвращать нулевые строки.Это не ошибка; это по дизайну. Вы можете возразить, что NULL
нельзя допускать ни в одном столбце, где вы хотите использовать выражение NOT
IN
, но в нашей реальной рабочей жизни эти вещи могут закрасться в источники таблиц. Стоит быть осторожным. Итак, используйте вариант EXISTS
или один из других, или всегда не забывайте включать предложение WHERE
в условие IN
, чтобы исключить NULL
s.
Как использовать предложение EXISTS в SQL? Пример реального SQL-запроса с использованием EXISTS
Привет, ребята, вы, возможно, слышали о том, насколько полезно предложение EXISTS при написании сложных запросов. Тем не менее, в то же время я также видел, что многие программисты изо всех сил пытаются понять и использовать предложения EXISTS и NOT EXISTS при написании SQL-запросов. Если вы один из них, то вы попали в нужное место. Сегодня вы узнаете, как использовать предложение EXISTS в SQL, взяв реальный пример и превосходный
из LeetCode. Предположим, что на веб-сайте есть две таблицы, таблица
.
Чтобы решить эту проблему, вам нужно сначала подумать о данных. Например, если покупатель никогда ничего не заказывал, значит, для него не будет никакой записи в таблице «Заказы».Молодец, половина задачи сделана.
Теперь вторая половина: как проверить, есть ли запись для конкретного клиента? Здесь вам помогут предложения EXISTS и NOT EXISTS, и об этом вы узнаете из этой статьи.
На самом деле это тоже популярный вопрос на собеседовании по SQL, и вы, возможно, уже видели его, но если нет, это нормально. Этот вопрос не так популярен, как второй по величине запрос о зарплате, но он также является одним из часто задаваемых SQL-запросов на собеседовании по программированию; вы можете увидеть полный список здесь.
Хотя я согласен с тем, что эту проблему можно решить другим способом, но это также прекрасный пример того, как можно использовать предложение SQL EXISTS .
Но, если вы новичок в мире SQL, лучше начать с всеобъемлющего курса SQL, такого как курс The Complete SQL Bootcamp от Jose Portilla на Udemy. Это поможет вам изучать SQL лучше и быстрее, и такие статьи также будут иметь больше смысла, если у вас есть некоторые знания SQL за плечами.
Таблицы и данные SQL
Прежде чем рассматривать запрос, давайте посмотрим на схему, таблицы и данные, чтобы лучше понять проблему. У нас есть две таблицы «Клиенты» и «Заказы». Клиенты содержат два столбца: Id и Name. Идентификатор представляет собой числовой столбец, а имя — текстовый столбец, предположим, что это тип VARCHAR.
Если какой-либо клиент заказал что-либо, его идентификатор клиента будет присутствовать в таблице заказов, и мы воспользуемся этими знаниями для решения этой проблемы.
У нас четыре клиента с идентификаторами от 1 до 4. Наша вторая таблица, Заказы, содержит Id, который представляет собой уникальный идентификатор для заказа, и CustomerId, который представляет собой идентификатор клиента, который делает этот заказ. Если какой-либо Клиент разместит заказ, его идентификатор будет существовать в таблице заказов.
Таблица: Клиенты.
+ —- + ——- +
| Id | Имя |
+ —- + ——- +
| 1 | Джо |
| 2 | Генри |
| 3 | Сэм |
| 4 | Макс |
+ —- + ——- +
Таблица: Заказы.
+ —- + ———— +
| Id | CustomerId |
+ —- + ———— +
| 1 | 3 |
| 2 | 1 |
+ —- + ———— +
Используя приведенные выше таблицы в качестве примера, верните следующее:
+ ———— +
| Заказчики |
+ ———— +
| Генри |
| Макс |
+ ———— +
Если вы ищете еще несколько SQL-задач, вы можете попробовать решить задачи, приведенные в классической книге Джо Селко « SQL-головоломки и ответы», 2-е издание . Одна из лучших книг для улучшения ваших навыков работы с SQL-запросами.
Решение для клиентов, которые никогда не заказывают
Одно из наиболее распространенных решений этой проблемы — использование предложения SQL JOIN. Вы можете использовать LEFT OUTER JOIN для решения этой проблемы, как показано ниже:
SELECT C.Name FROM Customers C LEFT JOIN Orders O ON C.Id = O.CustomerId ГДЕ O.CustomerId - НУЛЬ
Когда вы соединяете две таблицы в SQL с помощью LEFT OUTER JOIN, тогда будет создана большая таблица со значениями NULL в столбце, которых нет в другой таблице.
Например, большая таблица будет иметь четыре столбца C.Id, C.Name, O.Id и O.CustomerId, для клиентов, которые никогда ничего не заказывали, O.CustomerId будет NULL.
Многие программисты совершают ошибку, используя ! = в условии JOIN для решения этой проблемы, предполагая, что if = возвращает совпадающие строки, тогда! = Вернет те идентификаторы, которых нет в другой таблице. Так что остерегайтесь этого.
Если вам сложно понять, как присоединиться, я предлагаю вам взглянуть на отличный курс Хосе Портиллы по SQL The Complete SQL Bootcamp на Udemy.Его стиль преподавания потрясающий, и вы сразу поймете, как он присоединяется.
В любом случае, эта проблема на самом деле является отличным примером , как и когда использовать предложение EXISTS:
SELECT C.Name FROM Customers C ГДЕ НЕ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ Orders O WHERE C.Id = O.CustomerId)
Это коррелированный подзапрос, в котором внутренний запрос будет выполняться для каждой строки внешнего запроса, и будут возвращены только те клиенты, которые ничего не заказывали.
Кстати, самое простое решение — использовать NOT IN Clause.
ВЫБЕРИТЕ A. Имя от клиентов A ГДЕ A.Id НЕ ВХОДИТ (ВЫБЕРИТЕ B.CustomerId из заказов B)
Это все о том, как использовать предложение EXISTS в SQL для поиска всех клиентов, которые никогда не заказывали. Если вы хотите улучшить навыки работы с SQL-запросами, вы также можете решить задачи, описанные в классической книге Джо Селко «Загадки и ответы на SQL», 2-е издание. Одна из лучших книг с множеством сложных вопросов для проверки ваших навыков SQL, и если вам нужны онлайн-курсы для углубленного изучения SQL или заполнения пробелов в ваших знаниях SQL, следующие курсы — хорошее место для начала.
Дальнейшее обучение
Введение в SQL
SQL для новичков: анализ данных для начинающих
SQL-головоломки и ответы, 2-е издание
Другие связанные запросы SQL , вопросы интервью и статьи:
- Как присоединиться к трем таблицы в одном SQL-запросе (решение)
- Напишите запрос SQL, чтобы найти все имена таблиц в базе данных в MySQL (решение)
- 5 курсов для изучения баз данных и SQL Better (курсы)
- Написать SQL-запрос для копирования или резервного копирования таблицы в MySQL (решение)
- Как найти повторяющиеся строки в таблице базы данных? (раствор)
- 5 курсов для изучения баз данных Oracle и Microsoft SQL Server (курсы)
- Реальная разница между предложениями WHERE и HAVING в SQL? (ответ)
- Как перенести SQL-запросы с Oracle на SQL Server 2008? (ответ)
- 5 лучших веб-сайтов для БЕСПЛАТНОГО изучения SQL в Интернете? (ресурс)
- В чем разница между UNION и UNION ALL в SQL? (ответ)
- Разница между Self и Equi Join в SQL? (ответ)
- Лучшие курсы 5 для изучения базы данных MySQL для начинающих (курсы)
- В чем разница между представлением и материализованным представлением в базе данных? (ответ)
- Разница между кластеризованным и некластеризованным индексом в SQL? (ответ)
- Разница между первичным ключом и ключом кандидата в таблице? (ответ)
- 5 бесплатных курсов по изучению T-SQL и SQL Server для начинающих (курсы)
- Разница между уникальным и первичным ключом в таблице? (ответ)
- Разница между первичным и внешним ключом в таблице? (ответ)
Спасибо, что прочитали эту статью, если вам понравилась эта статья по SQL, поделитесь ею со своими друзьями и коллегами.