2009-03-03 53 views
8

Có cách nào tốt để cho biết ai đã tạo một thủ tục lưu sẵn trong SQL Server 2005 (cũng hoạt động trong năm 2008)? Trong SQL Management Studio tôi có thể chuột phải/thuộc tính trên một proc để có được ngày/thời gian tạo ra nhưng làm thế nào để tôi khám phá ra người sáng tạo?Microsoft SQL Server - Ai đã tạo thủ tục lưu trữ?

+0

Tốt nhất, Mitch. +1 – BuddyJoe

Trả lời

6

Hiện tại bạn có thể đã quá muộn, nhưng bạn có thể theo dõi hoạt động DDL.

Chúng tôi có một bảng trong cơ sở dữ liệu quản trị của chúng tôi để đưa tất cả hoạt động được đưa vào đó. Nó sử dụng một kích hoạt DDL, mới đến năm 2005. Các kịch bản này tạo ra một bảng trong DB quản trị của bạn (SQL_DBA cho tôi), tạo ra một kích hoạt trên mô hình db, tạo ra các trigger trên các cơ sở dữ liệu hiện có. Tôi cũng tạo ra một câu lệnh sp_msforeachDB ở cuối để vô hiệu hóa tất cả chúng.

Một caveat - cơ sở dữ liệu của bạn cần ở chế độ tương thích 90 (tùy chọn cho mỗi db), nếu không bạn có thể bắt đầu gặp lỗi. Tài khoản trong phần EXECUTE AS của câu lệnh cũng cần quyền truy cập để chèn vào bảng quản trị của bạn.

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

Nhưng nếu bạn có quyền/vai trò của bạn được thiết lập chính xác, cách bạn có cần nó không? –

+0

Nếu bạn đã tắt hệ thống, bạn có thể không cần điều này. Tôi có danh sách này được gửi cho tôi hàng ngày cho mục đích của riêng tôi mà tôi sẽ không tham gia. – Sam

+0

+1 Khái niệm thú vị. Quên tất cả về Trình kích hoạt DDL. Điều đó có thể giúp cho "xem" trong tương lai. Nhưng Mitch đưa ra một điểm tốt về an ninh. – BuddyJoe

3

Tôi tin rằng điều này không có sẵn trong SQL 2005. Chắc chắn nó không có sẵn trong các thuộc tính trong SQL Management Studio, và không có sẵn trong bảng sys.objects hoặc bất kỳ người nào khác mà tôi có thể nhìn thấy.

3

Nếu nó không được tạo ra cách đây quá lâu, hãy thử này:

DECLARE @path varchar(256) 

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

SELECT * 
FROM fn_trace_gettable(@path, 1) 

Nó chọn hiện tại (out of the box) dấu vết mặc định. Nếu nó được tạo gần đây (và máy chủ chưa được khởi động lại gần đây), thì tên đối tượng thủ tục được lưu trữ và tên đăng nhập đã tạo nó sẽ có trong dữ liệu theo dõi.

+0

@Bruno Tyndall: vậy bạn đã đi như thế nào? –

+0

Proc này được tạo ra cách đây 3 năm. Đoán điều này sẽ không hoạt động. Ngoài ra, khi tôi cố gắng chạy nó tôi đã nhận "Bạn không có quyền chạy 'SYS.TRACES'." Đoán tôi có thể yêu cầu DBA để chạy nó. Nhưng... – BuddyJoe

+0

Tôi nghĩ rằng những gì bạn đang nói là thông tin dấu vết chỉ tốt cho khoảng một ngày, một tuần, có thể một tháng? – BuddyJoe

2

Dọc theo ý tưởng giống như Sam, bạn có thể sử dụng một kích hoạt DDL để nắm bắt những thông tin cần thiết, sau đó gửi dữ liệu đó để một hàng đợi môi giới dịch vụ SQL, mà có thể chuyển tiếp nó vào cơ sở dữ liệu quản lý (mà có thể là trên một máy chủ khác nếu cần), sau đó sẽ giữ tất cả các thay đổi của DDL.

Điều này sẽ loại bỏ vấn đề quyền khi kích hoạt DDL sẽ tải dữ liệu vào Hàng đợi dịch vụ môi giới tại cơ sở dữ liệu cục bộ và SQL xử lý việc di chuyển thư đến cơ sở dữ liệu khác.

Sẽ có thiết lập nhiều hơn một chút với phương pháp này, nhưng sau khi thiết lập nó sẽ hoạt động bất kể ai đã thay đổi đối tượng.

+0

+1 điều này nghe có vẻ khá hứa hẹn – BuddyJoe

+0

Đó là nhiều hơn nữa trơn. Bây giờ, nếu chúng ta tạo một bản sao của một cơ sở dữ liệu và đưa nó cho nhà phát triển, họ sẽ gặp lỗi trên các mod ddl. – Sam

0

Cách nhận đoạn thông tin cũ này (đặc biệt là năm sau) rất có thể là không thể.

Tuy nhiên, bạn có thể sử dụng SQL Server Profiler để theo dõi hành động DDL. Trong tổ chức sự kiện lựa chọn, kiểm tra các sự kiện sau đây:

Objects/Object: Altered

Objects/Object: Tạo

Objects/Object: Deleted

Ngoài ra còn có rất nhiều lựa chọn tùy biến: bạn có thể lưu đầu ra vào một tệp hoặc bảng, lọc đầu ra hơn nữa dựa trên bất kỳ cột nào, v.v.

Các vấn đề liên quan