
Комментарии 9
Простите, но тут проблема не в удалении и создании таблиц, а в неправильном использовании процедур Alpha и Beta. Редактор совершенно верно указал, где ошибка.
Этот "антипатерн" растёт оттуда же - если надо код из хранимки выполнить отдельно
Мне обидно, что SQL server считают идиотом со стекающими от вырождения слюнями, идиотом, неспособным заботиться о контексте выполнения
Ваш код способен сделать из разработчика, который читает ваш код, - такого идиота. Он очень удивится, что в начале и конце хранимки у таблицы поля разные
Таблицы по завершении сессии сами удалятся, так? Как-то даже в голову не приходило дропать их. А что с ##-таблицами происходит? Когда они чистятся?
Дополню свои прошлые сообщения тут таким примером.
И да, я реально считаю MSSQL тупым идиотом. Но я знаю как с этим бороться.
create or alter procedure up_second
as
begin
create table #t (
inc int not null identity(1,1)
, value_i int not null
, primary key (inc)
)
insert into #t (value_i)
select 2
select 'DEBUG 2' [DEBUG 2], * from #t
end
GO
create or alter procedure up_main
as
begin
create table #t (
inc int not null identity(1,1)
, value_s varchar(max) not null
, primary key (inc)
)
insert into #t (value_s)
select 's1'
select 'DEBUG 1' [DEBUG 1], * from #t
exec up_second
select 'DEBUG 3' [DEBUG 3], * from #t
end
GO
--exec up_second
exec up_main
GO
drop procedure up_main
drop procedure up_second
Вот пример кода. Мы ожидаем тут увидеть Во втором отладочном селекте value_i = 2
Но этого не произойдёт, потому что мы на самом деле получим ошибку
Msg 207, Level 16, State 1, Procedure up_second, Line 10 [Batch Start Line 37]
Invalid column name 'value_i'.
Дропнуть таблицу в начале - тоже не приведёт ни к чему хорошему.
Дальше - интереснее. Если добавить вызов up_second перед up_main - то все работает и не падает и каждая из процедур нормально воспринимает свой контекст. Потому что в этому случае сервер компилирует up_second на использование таблицы с интовым полем.
И вывод из всего этого нужно сделать такой:
1) Конструкции когда дропаются в начале хранимки временные таблицы - они допустимы
Но надо быть уверенным, что это "головная" хранимка. Во внутренних - это действительно может быть проблемой
if object_id('tempdb..#mytemp') is not null
DROP TABLE #mytemp
или
DROP TABLE if exists #mytemp
2) Внутренние хранимки не должны сами создавать таблицы, если ожидают данные из какой-то известной внешней временной таблицы
И при разработке таких хранимок нужно помнить, какую структуру имеет таблица
Часто такие дропы нужны в скриптах, пока идет активная разработка: добавил поле - словил ошибку выполнения, так как времянка в контексте еще хранит старый состав. А если всунул дроп в начало - то всё ок.
Другое дело, что после того как скрипт доделан и оборачивается уже в хранимку/функцию, часто лишний код не чистится..)
Не удаляйте временные таблицы, умоляю