Сегодня я бы хотел остановится подробно на том, как можно обезопасить себя от непредсказуемых ошибок в 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 имеется хоть одна запись. Как мы видим, интерпретация запроса получилась совсем другая, которую мы имели ввиду, когда его составляли. Поэтому во избежание подобных случайных ошибок в своих запросах рекомендуется всегда использовать псевдонимы и точно указывать, к каким таблицам и столбцам вы обращаетесь.