2009-03-03 3 views
8

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

+0

Хорошо, Митч. +1 – BuddyJoe

ответ

6

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

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

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

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' 
+0

Но если у вас есть правильные настройки/роли, как часто вам это нужно? –

+0

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

+0

+1 Прохладный концепции. Забыл все о DDL Triggers. Это может помочь будущему «наблюдению». Но Митч хорошо разбирается в безопасности. – BuddyJoe

3

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

3

Если он не был создан слишком давно, попробуйте следующее:

DECLARE @path varchar(256) 

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

SELECT * 
FROM fn_trace_gettable(@path, 1) 

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

+0

@Bruno Tyndall: как ты ушел? –

+0

Этот процесс был создан 3 года назад. Думаю, это не сработает. Кроме того, когда я пытался запустить его, я получил: «У вас нет разрешения на запуск« SYS.TRACES ». Думаю, я мог бы попросить администратора базы данных запустить его. Но... – BuddyJoe

+0

Я думаю, что вы говорите, информация о трассировке хороша только около дня, недели, может быть, месяца? – BuddyJoe

2

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

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

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

+0

+1 это звучит довольно многообещающе – BuddyJoe

+0

Это гораздо более гладкий. Теперь, если мы сделаем копию базы данных и передадим ее разработчику, они получат ошибки в моделях ddl. – Sam

0

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

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

Объекты/Объект: Altered

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

объектов/Object: Deleted

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