(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

Просмотр стека вызова процедур в SQL Server

Источник: gotdotnet

При возникновении ошибок (да и не только), разработчикам хочется видеть стек вызова процедур.
И разработчики баз данных - не исключение.
Но к сожалению, T-SQL в частности и MSSQL Server вцелом не предоставляют нам такой счастливой возможности.
 

Оказывается все не так плохо...

Межно и самим сделать. ;)

Ограничение нижеследующего решения (касается текста процедур, обращения к которым хочется видеть в стеке):

  • процедуры будут модифицированы (возможны проблемы с ПО "сторонних разрабитчиков", которые требуют невмешательства)
  • процедуры должны создаваться командой create procedure, начинающейся с первого символа любой строки
  • слова create & procedure разделяются строго одним пробелом, после procedure также идет строго один пробел.
  • ключевое слово as также должно начинаться с первого символа строки, других символов в строке быть не должно.

Впрочем, данные ограничения связаны с нежеланием (надеюсь, понятным) применять в данном примере сложный парсинг T-SQL.
Ну и конечно, никто не мешает поменять данный код с учетом применяемых правил и традиций форматирования своего кода.

Использование:

  1. Запускаем скрипт
  2. Выполняем _Context.UpdateProcedures
    (в качестве параметра можно передать имя схемы, тогда будут затронуты только процедуры данной схемы)
  3. В процедурах смотрим содержимое стека конструкцией
    select * from _Context.Stack()

Обсдуждение решение здесь: http://www.sql.ru/forum/actualthread.aspx?tid=665929&pg=-1

Ну и само решение:

-- Схема

if schema_id('_Context') is null exec('create schema _Context')

go

if object_id('_Context.Push') is not null drop procedure _Context.Push

go

-- Процедура, меняющая контекст

create procedure _Context.Push

      @ID int

as

begin

      declare

            @level   int,

            @Context varbinary(128)

           

      select

            @Context = isnull(context_info(), convert(varbinary(128), replicate(convert(binary(1), 0x00), 128))),

            @level = (@@NESTLEVEL - 1) * 4

 

      set @Context = substring(@Context, 1, @level) + convert(binary(4), @ID) + substring(@Context, @level + 5, 128)

      set context_info @Context  

end

go

-- Опорная таблица с числами для "парсинга" контекста

if object_id('_Context.Numbers') is not null drop table _Context.Numbers

go

create table _Context.Numbers(Number int primary key)

go

-- Заполняем значениями от 1 до 32

insert into _Context.Numbers(Number)

select sv.number

from master.dbo.spt_values sv (nolock)

where sv.[type] = 'P'

and sv.number > 0

and sv.number <= 32

go

if object_id('_Context.Stack') is not null drop function _Context.Stack

go

-- Функция просмотра стека

create function _Context.Stack()

returns table

as

return

      (

      select

            stack_level,

            '['+object_schema_name(proc_id)+'].['+object_name(proc_id)+']' as procedure_name

      from

            (

            select

                  n.Number as stack_level,

                  convert(int, substring(context_info(), n.Number*4+1, 4)) as proc_id

            from _Context.Numbers n (nolock)

            where n.Number <= @@NESTLEVEL

      ) q

      )

go

if object_id('_Context.UpdateProcedures') is not null drop procedure _Context.UpdateProcedures

go

-- Процедура, добавляющая изменение стека в уже существующие

create procedure _Context.UpdateProcedures

      @SchemaName sysname = null

as

begin

      declare

            @procid int,

            @definition  nvarchar(max),

            @_definition nvarchar(max),

            @CRLF        char(2),

            @create_pos  int,

            @as_pos      int

           

      set @CRLF = char(13)+char(10)

     

      declare curs cursor local static forward_only for

            select

                  procid,

                  object_definition(procid)

            from

                  (

                  select

                        object_id('['+r.ROUTINE_SCHEMA + '].['+r.ROUTINE_NAME+']') as procid

                  from INFORMATION_SCHEMA.ROUTINES r

                  where r.ROUTINE_TYPE='PROCEDURE'

                  and isnull(@SchemaName, r.ROUTINE_SCHEMA) = r.ROUTINE_SCHEMA

                  -- Не меняем "себя"

                  and not(r.ROUTINE_SCHEMA='_Context' and r.ROUTINE_NAME='Push')

                  ) q

      open curs

      while 1=1

      begin

            fetch next from curs into @procid, @_definition

            if @@FETCH_STATUS <> 0 break

 

            select

                  @create_pos = 0,

                  @definition = upper(@_definition)

 

            -- ищем первое вхождение CREATE PROCEDURE

            if substring(@definition, 1, 17) = 'CREATE PROCEDURE '

                  set @create_pos = 1

            else

            begin

                  set @create_pos = charindex(@CRLF+'CREATE PROCEDURE ', @definition) + 2

            end

            if @create_pos > 0

            begin

                  set @as_pos = charindex(@CRLF+'AS'+@CRLF, @definition, @create_pos + 17)

                  if @as_pos > 0

                  begin

                        -- проверяем, нет ли уже за AS exec _Context.Push @@RPOCID

                        -- если нет - меняем текст процедуры

                        if substring(@definition, @as_pos+6, 29) <> 'EXEC _CONTEXT.PUSH @@PROCID'+@CRLF

                        begin

                             set @_definition = stuff(@_definition, @as_pos+6, 0, 'exec _Context.Push @@PROCID'+@CRLF)

                             set @_definition = stuff(@_definition, @create_pos, 6, 'alter')

                             begin try

                                   exec(@_definition)

                             end try

                             begin catch

                                   print @_definition

                              end catch

                        end

                  end

            end

      end

end

go

if object_id('_Context.pLevA') is not null drop procedure _Context.pLevA

go

-- В данной процедуре почему-то хочется видеть стек вызова

create procedure _Context.pLevA

as

begin

      select * from _Context.Stack()

      select 'level a' as [level]

end

go

-- Процедура, вызывающая ту, в которой хочется видеть стек

if object_id('_Context.pLevB') is not null drop procedure _Context.pLevB

go

create procedure _Context.pLevB

as

exec _Context.pLevA

select 'level b' as [level]

go

if object_id('_Context.pLevC') is not null drop procedure _Context.pLevC

go

-- Процедура, вызывающая процедуру, которая вызывает ту, в которой хочется видеть стек

create procedure _Context.pLevC

as

exec _Context.pLevB

select 'level c' as [level]

go

-- Добавляем Push в существующие процедуры

exec _Context.UpdateProcedures _Context

go

-- Проверяем

exec _Context.pLevC

go

Ссылки по теме


 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 09.02.2010 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Microsoft Office 365 для Дома 32-bit/x64. 5 ПК/Mac + 5 Планшетов + 5 Телефонов. Подписка на 1 год.
Microsoft Office 365 Бизнес. Подписка на 1 рабочее место на 1 год
Microsoft 365 Business Basic (corporate)
Microsoft Windows Professional 10, Электронный ключ
Microsoft 365 Apps for business (corporate)
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Безопасность компьютерных сетей и защита информации
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
Компьютерные книги. Рецензии и отзывы
Утиль - лучший бесплатный софт для Windows
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100