О том, что всегда нужно использовать псевдонимы

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

use tempdb;
go

if object_id('tempdb..#t1', N'U') is not null
	drop table #t1;

create table #t1 (
	id int not null primary key,
	some_value char(10) not null
);

insert into #t1 (id, some_value)
values
	(1, 'A'), (2, 'B');

-- Пример запроса без использования псевдонимов.
select id, some_value
from #t1;

-- Пример запроса с использованием псевдонимов.
select t1.id, t1.some_value
from #t1 as t1;

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

use tempdb;
go

if object_id('tempdb..#t1', N'U') is not null
	drop table #t1;

if object_id('tempdb..#t2', N'U') is not null
	drop table #t2;

create table #t1 (
	id int not null primary key,
	some_value char(10) not null
);

create table #t2 (
	id int not null primary key,
	some_value char(10) not null
);

insert into #t1 (id, some_value)
values
	(1, 'A'), (2, 'B');

insert into #t2 (id, some_value)
values
	(1, 'C'), (2, 'D');

-- Пример корректно написанного запроса.
select t1.id, t2.some_value
from #t1 as t1
inner join #t2 as t2 on
	t2.id = t1.id;

-- Пример запроса, который вызовет ошибку.
select id, some_value
from #t1 as t1
inner join #t2 as t2 on
	t2.id = t1.id;

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

Msg 102, Level 15, State 1, Line 31
Incorrect syntax near ‘t2’.

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

use tempdb;
go

if object_id('tempdb..#t1', N'U') is not null
	drop table #t1;

if object_id('tempdb..#t2', N'U') is not null
	drop table #t2;

create table #t1 (
	id int not null,
	some_id int not null
);

create table #t2 (
	no_id int not null
);

insert into #t1 (id, some_id)
values
	(1, 1),
	(2, 3);

insert into #t2 (no_id) values (5);

-- В таблице #t2 отсутствует поле id, но запрос при этом выполняется без ошибок.
select *
from #t1 as t1
where
	some_id in (select id from #t2);

В данном случае мы предполагали, что поле id присутствует во временной таблице #t2, хотя его там нет. Запрос при этом отработал без ошибок и вернул данные, т.к. написан он корректно: вернул те записи, у которых поля id и some_id совпадают, если в таблице #t2 имеется хоть одна запись. Как мы видим, интерпретация запроса получилась совсем другая, которую мы имели ввиду, когда его составляли. Поэтому во избежание подобных случайных ошибок в своих запросах рекомендуется всегда использовать псевдонимы и точно указывать, к каким таблицам и столбцам вы обращаетесь.

Leave a Reply

Your email address will not be published. Required fields are marked *