[SQL Server] Головоломки (Часть 2)
От: Olaf Россия  
Дата: 03.11.15 08:29
Оценка: 80 (9)
Добрый день, коллеги!

Продолжая начатую тему [SQL Server] Головоломки (Часть 1), решил опубликовать еще пять вопросов...

1. order by (select null)
Дано: Запрос вида
select * from dbo.Table1 order by (select null)

Вопрос: Можно ли с какой-то долей уверенности сказать будут ли отсортированы данные и в каком порядке?
a) Да
б) Нет
  Ответ

б) Нет
Подсказка:
Правильный ответ – Нет. Предложение order by (select null) будет проигнорировано при выполнении, т.е. данные вернутся в произвольном порядке, как если бы указание сортировки отсутствовало. Конструкция применяется там, где является обязательным использование последовательности данных, но по каким-то причинам поле или набор полей упорядочения не может быть определен, например аналитические функции row_number() over(order by (select null)) или использование паджинации order by (select null) offset 10 rows fetch next 5 rows only.



2. Декартово произведение
Дано: Три запроса
/* 1 */
select *
from dbo.Table1 t1
cross join dbo.Table2 t2

/* 2 */
select *
from dbo.Table1 t1, dbo.Table2 t2

/* 3 */
select *
from dbo.Table1 t1
join dbo.Table2 t2 on 1 = 1

Вопрос: Какие из представленных выше запросов реализуют декартово произведение?
a) Все
б) 1, 2
в) 2, 3
г) 1, 3
д) Ни один
Выберите один вариант ответа
  Ответ

a) Все
Подсказка:
Все 3-и запроса реализуют декартово произведение —
Запрос 1 использует стандарт ANSI-92
Запрос 2 использует стандарт ANSI-89
Запрос 3 использует INNER JOIN с «липовым» условием соединения 1 = 1



3. Приоритет типов данных в предикатах соединения
Дано: Две пустые таблицы
create table dbo.Test1
(
   StringColumn varchar(20)
)

create table dbo.Test2
(
   NumericColumn numeric(19, 0),
   DateTimeColumn datetime 
)

и два запроса соединяющие таблицы по полям разных типов. Запросы выполняются по отдельности.
/* 1 */
select *
from dbo.Test1 t1 
join dbo.Test2 t2 on t1.StringColumn = t2.NumericColumn

/* 2 */
select *
from dbo.Test1 t1 
join dbo.Test2 t2 on t1.StringColumn = t2.DateTimeColumn

Вопрос: К какому типу данных будут преобразованы столбцы, используемые в условии соединения таблиц?
a) В запросе 1 столбец t1.StringColumn участвующий в связывании таблиц будет преобразован к типу numeric(19, 0)
б) В запросе 1 столбец t2.NumericColumn участвующий в связывании таблиц будет преобразован к типу varchar(20)
в) При выполнении запроса 1 возникнет ошибка
г) В запросе 2 столбец t1.StringColumn участвующий в связывании таблиц будет преобразован к типу datetime
д) В запросе 2 столбец t2.DateTimeColumn участвующий в связывании таблиц будет преобразован к типу varchar(20)
е) При выполнении запроса 2 возникнет ошибка
Выберите два варианта ответа
  Ответ

a) В запросе 1 столбец t1.StringColumn участвующий в связывании таблиц будет преобразован к типу numeric(19)
г) В запросе 2 столбец t1.StringColumn участвующий в связывании таблиц будет преобразован к типу datetime
Подсказка:
Столбцы, используемые в условии соединения, не обязательно должны иметь одинаковые имена или одинаковый тип данных. Однако если типы данных не совпадают, то они должны быть совместимыми или допускать в SQL Server неявное преобразование. При выполнении неявного преобразования используется старшинство типов данных согласно документу Data Type Precedence (Transact-SQL) Из 3-х типов данных представленных в запросах выше varchar имеет низший приоритет, поэтому столбцы участвующие в соединениях будут преобразованы к типам данных с более высоким приоритетом — numeric и datetime.



4. Объявление переменных
Дано: Запрос, который заполняет в цикле табличную переменную
declare @i int = 0

while (@i < 10)
begin
   declare @table table(i int)
   insert into @table select @i
   set @i += 1
end

select * from @table

Вопрос: Какие данные будут содержаться в переменной @table после выполнения цикла?
a) При выполнении возникнет ошибка «The variable name '@table' has already been declared»
б) Таблица будет содержать 0 записей
в) Таблица будет содержать 1 запись со значением 9
г) Таблица будет содержать 10 записей со значениями от 0 до 9
  Ответ

г) Таблица будет содержать 10 записей со значениями от 0 до 9
Подсказка:
Все переменные, в том числе и табличные, создаются предварительно, т.е. на этапе компиляции запроса. Именно поэтому во время выполнения цикла будет использоваться единственный экземпляр переменной @table, в который попадут 10 записей от 0 до 9.



5. select @local_variable и несколько значений
Дано: Таблица, содержащая 4 записи и запрос, который инициализирует переменную через оператор select.
select * 
into #temp
from (values (1),(3),(4),(2)) t(k)

declare @i int

select @i = k from #temp order by k

select @i

Вопрос: Чему равно значение переменной @i после выполнения запроса?
a) 1
б) 2
в) 3
г) 4
д) NULL
  Ответ

г) 4
Подсказка:
Согласно документации SELECT @local_variable (Transact-SQL) обычно используется для возвращения одиночного значения в переменную. Однако, если аргумент expression является именем столбца, может вернуться несколько значений. Если инструкция SELECT возвращает более одного значения, переменной присваивается последнее возвращенное значение.

 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.