2015-02-11 2 views
0

Я обнаружил ошибку, компилирующую ошибку в MS SQL.Ошибка динамической таблицы SQL Template

Так скажем, у нас есть хранимая процедура, как этот

CREATE PROCEDURE Test 
@FirstPart bit 
AS 


BEGIN 
if @FirstPart = 1 begin 
Declare @SQL varchar(max) 
    set @SQL = 'ALTER TABLE #Test ADD Column2 varchar(100)' 
    exec(@SQL) 

    set @SQL = 'ALTER TABLE #Test ADD Column3 varchar(100)' 
    exec(@SQL) 
end else   
     SELECT Column1, Column2,Column3 FROM #Test 
END 

Тогда в другой Sesion мы делаем это

CREATE TABLE #Test (Column1 varchar(100))  
exec Test 1 

Обычно это будет выполнять альтер заявления таблицы 2 без проблем, но это запрос выполняется с ошибками

Msg 207, Level 16, State 1, Procedure Test, Line 15 
Invalid column name 'Column2'. 
Msg 207, Level 16, State 1, Procedure Test, Line 15 
Invalid column name 'Column3'. 

Любые идеи?

EDIT:

ALTER PROCEDURE Test 

AS 


BEGIN 



--if @FirstPart = 1 begin 
Declare @SQL varchar(max) 
    set @SQL = 'ALTER TABLE #Test ADD Column2 varchar(100)' 
    exec(@SQL) 

    set @SQL = 'ALTER TABLE #Test ADD Column3 varchar(100)' 
    exec(@SQL) 
--end else  
     SELECT Column1, Column2,Column3 FROM #Test 
END 
+0

когда '@FirstPart <> 1' вы получите эту ошибку и я не вижу необходимости динамического запроса здесь –

+0

я замечаю, если вы закомментировать«еще»часть прок, вы не» t получить ошибку при выполнении. Это подсказывает мне, что при вызове proc обе стороны if оцениваются для ошибок, а не только для того, что будет выполнено. SQL, как я полагаю, работает так. –

+0

@NoDisplayName это всего лишь маленький пример, мой первоначальный запрос имеет неизвестное количество столбцов, поэтому мне нужен динамический sql. Также способ, которым я выполняю процедуру, равен значению 1, поэтому он не может пойти в случай <> 1 – CiucaS

ответ

0

Как вы уже заметили, план запроса производится для всей процедуры. Скорее всего, потому что для анализа кода (и в худшем случае даже данных) потребуется больше времени, чтобы выяснить, какие части кода будут выполняться, а что нет.

Если у вас есть такие функции, вы, вероятно, должны разделить их на две разные процедуры. Это также поможет также в создании лучшего плана при составлении плана с использованием значений параметров, фактически используемых при выполнении этой части, - при условии, что у вас на самом деле больше функциональности в вашей процедуре.

+0

Я уже сделал это (отделил их), но мне просто интересно, почему SQL работает так. Потому что даже если вы удалите IF и запустите (проверьте внесенное мной изменение в сообщение, которое все еще выполняется с ошибками) – CiucaS

+0

Да, план сделан до начала выполнения процедуры. Если вы запускаете инструкции alter обычно, не используя exec, тогда это сработает. Если я правильно помню, что план с этого момента будет создан позже, поскольку альтернативные таблицы вызывают перекомпиляцию. –

0

Обходной путь, который я нашел, - select, должен также присутствовать в динамическом запросе.

create PROCEDURE Test @FirstPart BIT 
AS 
    BEGIN 
     DECLARE @SQL VARCHAR(max) 

     SET @SQL = 'ALTER TABLE #Test ADD Column2 varchar(100)' 

     EXEC(@SQL) 

     SET @SQL = 'ALTER TABLE #Test ADD Column3 varchar(100)' 

     EXEC(@SQL) 

     EXEC('SELECT Column1,Column2,Column3 FROM #Test') -- Dynamic query 
    END 

CREATE TABLE #Test 
    (Column1 VARCHAR(100)) 

EXEC Test 1 
Смежные вопросы