Auditando tablas y bases de datos en Sql Server


En Sql Server Central, publicaron un artículo donde se daban consejos para realizar una auditoría de base de da tos y realizar un seguimiento de los cambios realizados en una tabla.

La primera recomendación es agregar unos campos adicionales a la estructura de la tabla sometida a auditoría, algo como:

ModificadoPor varchar(40)
Modificado datetime
Accion char(1)

Con estos campos, que almacenan el valor de quién modificó la fila, la fecha y la acción realizada. De ese modo, se tenía un registro de los cambios en la tabla.

La segunda era crear una tabla espejo, es decir no modificar la tabla original, pero crear una tabla con la misma estructura. Digamos que si la tabla es Facturas, la tabla espejo sera Facturas_Auditoria, a la que hay que añadir los campos mencionados anteriormente. Para cada acción en la tabla original se graba una fila en la tabla de auditoría.

El creador del artículo, Steve Jones, menciona luego las ventajas y desventajas. La ventaja principal es que se puede llevar un historial fila por fila, de ese modo, se podrá saber los cambios hechos. La desventaja es una sobrecarga de transacciones, y un aumento del tamaño de la base de datos. Este tipo de auditoría también conlleva un estricto control en las aplicaciones para no obviar el paso, Jones lo recomienda para aplicaciones financieras, y no en todas las tablas, solo algunas, las más importantes.

Haz clic aquí para leer el artículo completo en inglés.

Visual Studio 2005: Acceso directos por teclado

Aquí adjunto un pdf con los atajos o acceso directos por teclado para Visual Studio 2005. A los que usamos más el teclado que el mouse, nos ayuda un montón.

Descarga el PDF haciendo clic aquí.

La mayoría de estos acceso directos por teclados funcionan también para la versión 2008.

Encontrar donde se usa una determinada columna

Cuando trabajamos con bases de datos Sql Server y necesitamos realizar un cambio en una columna, es necesario saber donde más la estamos usando. Con este script de Karen Gayda nos puede ayudar en eso, este script crea un procedimiento almacenado, llamado usp_FindColumnUsage, que se puede utilizar con la siguiente sintaxis:

usp_FindColumnUsage NombreTabla,NombreColumna

El script a continuación (he traducido el texto necesario a español como lo uso):

if exists (select * from dbo.sysobjects
where id = object_id(N'[dbo].[usp_FindColumnUsage]')
and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[usp_FindColumnUsage]
GO


CREATE PROCEDURE [dbo].[usp_FindColumnUsage]
@vcTableName varchar(100),
@vcColumnName varchar(100)
AS
/************************************************************************************************
DESCRIPTION: Creates prinatable report of all stored procedures, views, triggers
and user-defined functions that reference the
table/column passed into the proc.

PARAMETERS:
@vcTableName - table containing searched column
@vcColumnName - column being searched for
REMARKS:
To print the output of this report in Query Analyzer/Management
Studio select the execute mode to be file and you will
be prompted for a file name to save as. Alternately
you can select the execute mode to be text, run the query, set
the focus on the results pane and then select File/Save from
the menu.

This procedure must be installed in the database where it will
be run due to it's use of database system tables.

USAGE:

usp_FindColumnUsage 'jct_contract_element_card_sigs', 'contract_element_id'

AUTHOR: Karen Gayda
TRADUCTOR: Carlos Mayanga
WEB:http://ikanus3000.blogspot.com

DATE: 07/19/2007

MODIFICATION HISTORY:
WHO DATE DESCRIPTION
--- ---------- -------------------------------------------
*************************************************************************************************/
SET NOCOUNT ON



PRINT ''
PRINT 'REPORTE PARA DEPENDENCIAS PARA TABLA/COLUMNA:'
PRINT '----------------------------------------------'
PRINT @vcTableName + '.' +@vcColumnName


PRINT ''
PRINT ''
PRINT 'PROCEDIMIENTOS ALMACENADOS:'
PRINT ''

SELECT DISTINCT SUBSTRING(o.NAME,1,60) AS [Nombre del Procedimiento]
FROM sysobjects o
INNER JOIN syscomments c
ON o.ID = c.ID
WHERE o.XTYPE = 'P'
AND c.Text LIKE '%' + @vcColumnName + '%' + @vcTableName + '%'


ORDER BY [Nombre del Procedimiento]
PRINT CAST(@@ROWCOUNT as Varchar(5)) + ' procedimientos almacenados dependientes para la columna "' + @vcTableName + '.' +@vcColumnName + '".'



PRINT''
PRINT''
PRINT 'VISTAS:'
PRINT''
SELECT DISTINCT SUBSTRING(o.NAME,1,60) AS [Nombre de la Vista]
FROM sysobjects o
INNER JOIN syscomments c
ON o.ID = c.ID
WHERE o.XTYPE = 'V'
AND c.Text LIKE '%' + @vcColumnName + '%' + @vcTableName + '%'


ORDER BY [Nombre de la Vista]
PRINT CAST(@@ROWCOUNT as Varchar(5)) + ' vistas dependientes para la columna "' + @vcTableName + '.' +@vcColumnName + '".'


PRINT ''
PRINT ''
PRINT 'FUNCIONES:'
PRINT ''

SELECT DISTINCT SUBSTRING(o.NAME,1,60) AS [Nombre de la Función],
CASE WHEN o.XTYPE = 'FN' THEN 'Escalar'
WHEN o.XTYPE = 'IF' THEN 'En linea'
WHEN o.XTYPE = 'TF' THEN 'Tabla'
ELSE '?'
END
as [Tipo de Función]
FROM sysobjects o
INNER JOIN syscomments c
ON o.ID = c.ID
WHERE o.XTYPE IN ('FN','IF','TF')
AND c.Text LIKE '%' + @vcColumnName + '%' + @vcTableName + '%'


ORDER BY [Nombre de la Función]
PRINT CAST(@@ROWCOUNT as Varchar(5)) + ' funciones dependientes de la columna "' + @vcTableName + '.' +@vcColumnName + '".'

PRINT''
PRINT''
PRINT 'TRIGGERS:'
PRINT''

SELECT DISTINCT SUBSTRING(o.NAME,1,60) AS [Nombre del Trigger]
FROM sysobjects o
INNER JOIN syscomments c
ON o.ID = c.ID
WHERE o.XTYPE = 'TR'
AND c.Text LIKE '%' + @vcColumnName + '%' + @vcTableName + '%'


ORDER BY [Nombre del Trigger]
PRINT CAST(@@ROWCOUNT as Varchar(5)) + ' triggers dependientes para la columna "' + @vcTableName + '.' +@vcColumnName + '".'


GO

El script muestra el resultado como un reporte imprimible en el analizador de consultas, escogiendo la opción Resultados como Texto, del menú Consulta.

Fuente: Sql Server Central (en inglés).

PatIndex Versus CharIndex

Normalmente para encontrar un caracter dentro de una cadena utilizamos CharIndex. El 99% de las veces que usamos CharIndex podemos sustituirlo por PatIndex. El 1% restante le da la ventaja a PatIndex, ya que PatIndex es un CharIndex fusionado con Like. Podemos usar patrones para buscar un caracter. Algo mejor, no lo creen?.

Diferencia entre Truncate y Delete

¿Qué diferencia hay entre TRUNCATE y DELETE? Aparentemente son iguales, se usan para eliminar datos de una tabla, solo datos, la estructura se mantiene.

TRUNCATE

Este comando remueve todas las filas de una tabla sin registrar las eliminaciones individuales en el log de transacciones. Prácticamente hace lo mismo que DELETE sin modificar o borrar la estructura de la tabla, sin embargo no se puede utilizar la clausula WHERE. TRUNCATE no permite filtrar por filas, elimina todos los registros de una tabla.

Por ejemplo:

TRUNCATE TABLE Autores

Esto eliminará todos los registros de la tabla Autores.

DELETE

DELETE también remueve las filas de una tabla, pero registra las eliminaciones individuales en el log de transacciones. Podemos utilizar la clausula WHERE para filtrar las filas que necesitemos eliminar.

Ejemplo:

DELETE FROM Autores (elimina todas las filas de la tabla autores)

DELETE FROM Autores WHERE IdCiudad = 30 (elimina las filas de la tabla autores que coincide con la condición indicada)

DIFERENCIAS ENTRE TRUNCATE Y DELETE

Ahora que sabemos en que consiste cada sentencia, veamos las semejanzas y diferencias:

- Ambas eliminan los datos, no la estructura.
- Solo DELETE permite la eliminación condicional de los registros.
- DELETE es una operación registrada en el log de transacciones, basada en registrar cada eliminación individual.
- TRUNCATE es una operación registrada en el log de transacciones, pero como un todo, en conjunto, no por eliminación individual. TRUNCATE se registra como una liberación de las páginas de datos en las cuales existen los datos.
- TRUNCATE es más rápida que DELETE.
- Ambas se pueden deshacer con un ROLLBACK.
- TRUNCATE reiniciará el contador para una tabla que contenga una columna IDENTITY.
- DELETE mantendrá el contador de la tabla para una columna IDENTITY.
- TRUNCATE es un comando DDL(lenguaje de definición de datos) mientras que DELETE es un DML(lenguaje de manipulación de datos).
- TRUNCATE no desencadena un TRIGGER, DELETE sí.