Microsoft SQL Server-кто создал хранимую процедуру?

есть ли хороший способ узнать, кто создал хранимую процедуру в SQL Server 2005 (которая также работает в 2008 году)? В SQL Management Studio я могу правая мышь / свойства на proc, чтобы получить созданную дату / время, но как я могу обнаружить создателя?

5 ответов


теперь может быть слишком поздно, но вы можете отслеживать активность DDL.

у нас есть таблица в нашей административной базе данных, которая получает все действия, помещенные в нее. Он использует триггер DDL, новый для 2005. Эти скрипты создают таблицу в вашей БД администратора (SQL_DBA для меня), создают триггер на модели БД, создают триггеры на существующих базах данных. Я также создал оператор sp_msforeachDB в конце, чтобы отключить их все.

один нюанс - баз данных необходимо быть в режиме совместимости 90 (в настройках для каждой БД), иначе вы можете начать получать ошибки. Учетная запись в инструкции EXECUTE как часть инструкции также нуждается в доступе для вставки в таблицу администратора.

USE [SQL_DBA]
GO
/****** Object:  Table [dbo].[DDL_Login_Log]    Script Date: 03/03/2009 17:28:10 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[DDL_Login_Log](
    [DDL_Id] [int] IDENTITY(1,1) NOT NULL,
    [PostTime] [datetime] NOT NULL,
    [DB_User] [nvarchar](100) NULL,
    [DBName] [nvarchar](100) NULL,
    [Event] [nvarchar](100) NULL,
    [TSQL] [nvarchar](2000) NULL,
    [Object] [nvarchar](1000) NULL,
 CONSTRAINT [PK_DDL_Login_Log] PRIMARY KEY CLUSTERED 
(
    [DDL_Id] ASC,
    [PostTime] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--This creates the trigger on the model database so all new DBs get it
USE [model]
GO
/****** Object:  DdlTrigger [ddl_DB_User]    Script Date: 03/03/2009 17:26:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [ddl_DB_User] 
ON DATABASE
FOR DDL_DATABASE_SECURITY_EVENTS
AS 

DECLARE @data XML
declare @user nvarchar(100)

SET @data = EVENTDATA()
select @user = convert(nvarchar(100), SYSTEM_USER)

execute as login='domain\sqlagent'
INSERT sql_dba.dbo.DDL_Login_Log 
   (PostTime, DB_User, DBName, Event, TSQL,Object) 
   VALUES 
   (@data.value('(/EVENT_INSTANCE/PostTime)[1]', 'nvarchar(100)'), 
   @user,
    db_name(),
    @data.value('(/EVENT_INSTANCE/EventType)[1]', 'nvarchar(100)'), 
   @data.value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarchar(max)'),
    @data.value('(/EVENT_INSTANCE/ObjectName)[1]', 'nvarchar(1000)')
)

GO
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER OFF
GO


--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--CREATE TRIGGER IN ALL NON SYSTEM DATABASES

DECLARE @dataname varchar(255),
@dataname_header varchar(255),
@command VARCHAR(MAX),
@usecommand VARCHAR(100)
SET @command = '';
DECLARE datanames_cursor CURSOR FOR SELECT name FROM sys.databases 
WHERE name not in ('master', 'pubs', 'tempdb', 'model','msdb')
OPEN datanames_cursor
FETCH NEXT FROM datanames_cursor INTO @dataname
WHILE (@@fetch_status = 0)
BEGIN

PRINT '----------BEGIN---------'

PRINT 'DATANAME variable: ' + @dataname;

EXEC ('USE ' + @dataname);

PRINT 'CURRENT db: ' + db_name();

SELECT @command = 'CREATE TRIGGER DBA_Audit ON DATABASE
FOR DDL_DATABASE_LEVEL_EVENTS
AS
DECLARE @data XML
DECLARE @cmd NVARCHAR(1000)
DECLARE @posttime NVARCHAR(24)
DECLARE @spid NVARCHAR(6)
DECLARE @loginname NVARCHAR(100)
DECLARE @hostname NVARCHAR(100)
SET @data = EVENTDATA()
SET @cmd = @data.value(''(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]'', ''NVARCHAR(1000)'')
SET @cmd = LTRIM(RTRIM(REPLACE(@cmd,'''','''')))
SET @posttime = @data.value(''(/EVENT_INSTANCE/PostTime)[1]'', ''DATETIME'')
SET @spid = @data.value(''(/EVENT_INSTANCE/SPID)[1]'', ''nvarchar(6)'')
SET @loginname = @data.value(''(/EVENT_INSTANCE/LoginName)[1]'',
    ''NVARCHAR(100)'')
SET @hostname = HOST_NAME()
INSERT INTO [DBA_AUDIT].dbo.AuditLog(Command, PostTime,HostName,LoginName)
 VALUES(@cmd, @posttime, @hostname, @loginname);'

 EXEC (@command);
 FETCH NEXT FROM datanames_cursor INTO @dataname;
PRINT '----------END---------'
END
CLOSE datanames_cursor
DEALLOCATE datanames_cursor

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

----Disable all triggers when things go haywire
sp_msforeachdb @command1='use [?]; IF  EXISTS (SELECT * FROM sys.triggers WHERE name = N''ddl_DB_User'' AND parent_class=0)disable TRIGGER [ddl_DB_User] ON DATABASE'

Я считаю, что это недоступно в SQL 2005. Конечно, он недоступен в свойствах в SQL Management Studio и недоступен в sys.таблица объектов или любые другие, которые я вижу.


, если он не был создан так давно, попробуйте это:

DECLARE @path varchar(256)

SELECT @path = path
FROM sys.traces
where id = 1

SELECT *
FROM fn_trace_gettable(@path, 1)

он выбирает текущую (из коробки) трассировку по умолчанию. Если он был создан недавно (и сервер не был перезапущен недавно), то имя объекта хранимой процедуры и имя Входа, которое его создало, будут в данных трассировки.


по той же идее, что и Сэм, вы можете использовать триггер DDL для захвата необходимой информации, а затем отправить эти данные в очередь SQL Service broker, которая может переслать ее в базу данных администратора (которая может быть на другом сервере, если это необходимо), которая затем будет содержать все изменения DDL.

Это устранит проблему с разрешениями, поскольку триггер DDL будет загружать данные в очередь Service Broker в локальной базе данных, а SQL обрабатывает перемещение сообщения в другую база данных.

с этим методом будет немного больше настройки, но после настройки он будет работать независимо от того, кто сделал изменение объекта.


Как получить эту часть информации ex post (особенно годы спустя), скорее всего, невозможно.

однако для отслеживания действий DDL можно использовать SQL Server Profiler. При выборе события, проверьте следующие события:

Объекты / Объект: Изменено

Объекты / Объект: Создано

Объекты / Объект: Удалено

есть также много вариантов настройки: вы можете сохранить вывод в файл или таблицу, фильтровать вывод, кроме того основанный на любых столбцах etc. так далее.