Pregunta

¿Hay una buena manera de saber quién creó un procedimiento almacenado en SQL Server 2005 (que también funciona en 2008)? En SQL Management Studio, puedo hacer clic con el botón derecho del ratón sobre las propiedades de un proceso para obtener la fecha y la hora creadas, ¿pero cómo descubro al creador?

¿Fue útil?

Solución

Puede que ya sea demasiado tarde para usted, pero puede hacer un seguimiento de la actividad de DDL.

Tenemos una tabla en nuestra base de datos administrativa que obtiene toda la actividad puesta en ella. Utiliza un disparador DDL, nuevo a 2005. Estos scripts crean una tabla en su base de datos de administración (SQL_DBA para mí), crean un disparador en la base de datos del modelo, crean disparadores en las bases de datos existentes. También creé una declaración sp_msforeachDB al final para deshabilitarlos a todos.

Una advertencia : sus bases de datos deben estar en modo de compatibilidad de 90 (en las opciones para cada db), de lo contrario, puede comenzar a recibir errores. La cuenta en EJECUTAR COMO parte de la declaración también necesita acceso para insertarla en la tabla de administració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'

Otros consejos

Creo que esto no está disponible en SQL 2005. Ciertamente, no está disponible en las propiedades de SQL Management Studio, y no está disponible en la tabla sys.objects ni en ningún otro que pueda ver.

Si no se creó hace mucho tiempo, intente esto:

DECLARE @path varchar(256)

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

SELECT *
FROM fn_trace_gettable(@path, 1)

Selecciona la traza predeterminada actual (fuera de la caja). Si se creó recientemente (y el servidor no se ha reiniciado recientemente), entonces el nombre del objeto del procedimiento almacenado y el nombre de inicio de sesión que lo creó estarán en los datos de rastreo.

Junto con la misma idea que la de Sam, puede usar un desencadenador DDL para capturar la información necesaria y luego enviar esos datos a una cola del agente de servicios SQL, que podría reenviarlos a la base de datos de administración (que podría estar en otro servidor si fuera necesario). ) que luego mantendría todos los cambios de DDL.

Esto eliminaría el problema de los permisos, ya que el desencadenador DDL estaría cargando datos en una cola de Service Broker en la base de datos local y SQL se encarga de mover el mensaje a la otra base de datos.

Habría un poco más de configuración con este método, pero una vez que funcionara funcionaría sin importar quién hizo el cambio de objeto.

Lo más probable es que no sea posible obtener esta información ex post (especialmente años más tarde).

Sin embargo, puede usar el Analizador de SQL Server para realizar un seguimiento de las acciones DDL. En Selección de eventos, compruebe los siguientes eventos:

Objetos / Objeto: Alterado

Objetos / Objeto: creado

Objetos / Objeto: Eliminado

También hay muchas opciones de personalización: puede guardar la salida en un archivo o tabla, filtrar la salida además de las columnas, etc. etc.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top