Отладка динамических sql + динамических таблиц в MS SQL Server 2008 - PullRequest
0 голосов
/ 18 марта 2010

У меня грязная хранимая процедура, которая использует динамический sql.

Я могу отладить его во время выполнения, добавив print @sql;, где @sql; - строка, содержащая динамический SQL, прямо перед тем, как я вызову execute (@sql);.

Теперь многостраничная хранимая процедура также создает динамические таблицы и использует их в запросе. Я хочу напечатать эти таблицы на консоли прямо перед тем, как выполнить execute, чтобы точно знать, что пытается сделать запрос.

Однако SQL Server 08 этого не устраивает. Когда я пытаюсь:

print #temp_table; и попробуйте скомпилировать S.P. Я получаю эту ошибку:


Имя "#temp_table" не разрешено в этом контексте. Допустимые выражения - это константы, константные выражения и (в некоторых контекстах) переменные. Имена столбцов не допускаются.


Пожалуйста, помогите.

РЕДАКТИРОВАТЬ:

Я нуб, когда дело доходит до SQL. Тем не менее, следующее утверждение: select * from #tbl; не выводит на консоль ничего, когда он запускается неинтерактивно; хотя оператор print работает.

Следующий оператор имеет неправильный синтаксис: print select * from #tbl;. Есть ли способ для меня перенаправить вывод select в файл, если stdout не вариант?

Спасибо.

Ответы [ 4 ]

1 голос
/ 18 марта 2010

Когда мы используем динамический SQl, мы начинаем с наличия входной переменной отладки в sp (делайте ее последней и присваивайте ей значение по умолчанию 0 (чтобы указать, что в режиме отладки это не будет нарушать вызов существующего кода proc).

Теперь, когда вы запускаете его в режиме отладки, вы печатаете вместо выполнения или вы печатаете и выполняете, но в конце всегда выполняете откат. Если вам нужно просмотреть данные на разных этапах, лучше всего сделать второй шаг. Затем перед откатом вы помещаете данные, которые вы хотите видеть, в таблицу, которую можно изменить (это важно, это не может быть временная таблица). после отката выберите переменную таблицы (которая не вышла за пределы области действия при откате) и запустите инструкции печати, чтобы увидеть выполненные запросы.

1 голос
/ 18 марта 2010

Вы можете печатать переменные, но не таблицы. Однако вы можете ВЫБРАТЬ из таблицы #.

Теперь, если таблица создана, заполнена и изменена в одном выполняемом операторе, вы можете просмотреть состояние таблицы, как оно было до изменения , но данные будут иметь изменено с тех пор.

Конечно, как только динамический SQL завершится, #table больше не будет доступен, поэтому вы застряли!

Чтобы противостоять этому, вы можете вставить в таблицу ## (обратите внимание на двойные хеш-метки) ваш динамический SQL вместе с #table, а затем запросить эту таблицу ## в конце выполнения динамического sql. *

1 голос
/ 18 марта 2010

Насколько я ненавижу курсоры, попробуйте:

SET NOCOUNT ON
CREATE TABLE #TempTable1
(ColumnInt      int        
,ColumnVarchar  varchar(50)
,ColumnDatetime datetime   
)
INSERT INTO #TempTable1 VALUES (1,'A',GETDATE())
INSERT INTO #TempTable1 VALUES (12345,'abcdefghijklmnop','1/1/2010')
INSERT INTO #TempTable1 VALUES (null,null,null)
INSERT INTO #TempTable1 VALUES (445454,null,getdate())
SET NOCOUNT OFF

DECLARE @F_ColumnInt      int
       ,@F_ColumnVarchar  varchar(50)
       ,@F_ColumnDatetime datetime

DECLARE CursorTempTable1 CURSOR FOR
    SELECT
        ColumnInt, ColumnVarchar, ColumnDatetime
    FROM #TempTable1
    ORDER BY ColumnInt
    FOR READ ONLY

--populate and allocate resources to the cursor
OPEN CursorTempTable1

PRINT '#TempTable1 contents:'
PRINT '    '+REPLICATE('-',20)
       +'  '+REPLICATE('-',50)
       +'  '+REPLICATE('-',23)

--process each row
WHILE 1=1
BEGIN

    FETCH NEXT FROM CursorTempTable1
        INTO @F_ColumnInt, @F_ColumnVarchar, @F_ColumnDatetime

    --finished fetching all rows?
    IF @@FETCH_STATUS <> 0
    BEGIN --YES, all done fetching
        --exith the loop
        BREAK
    END --IF finished fetching

    PRINT '    '+RIGHT(   REPLICATE(' ',20)   +   COALESCE(CONVERT(varchar(20),@F_ColumnInt),'null')                               ,20)
           +'  '+LEFT(                            COALESCE(@F_ColumnVarchar,'null')                        +   REPLICATE(' ',50)   ,50)
           +'  '+LEFT(                            COALESCE(CONVERT(char(23),@F_ColumnDatetime,121),'null') +   REPLICATE(' ',23)   ,23)

END --WHILE

--close and free the cursor's resources
CLOSE CursorTempTable1
DEALLOCATE CursorTempTable1

ВЫВОД:

#TempTable1 contents:
--------------------  --------------------------------------------------  -----------------------
                null  null                                                null                   
                   1  A                                                   2010-03-18 13:28:24.260
               12345  abcdefghijklmnop                                    2010-01-01 00:00:00.000
              445454  null                                                2010-03-18 13:28:24.260

Если бы я знал, что у вашей временной таблицы есть PK, я бы привел пример с циклом без курсора.

1 голос
/ 18 марта 2010

Отладка таким способом, единственный способ получить выходные данные - это

select * from #temp_table;

В качестве альтернативы, посмотрите функции отладки, встроенные в SQL Server Management Studio.Например, эта веб-страница может помочь вам

Производительность SQL Server.ком

...