Lectura 8 - SQL

miércoles, 21 de enero de 2009

INTRODUCCIÓN
En esta lectura veremos la especialización de los procedimientos almacenados: los trigger o desencadenadores.
Además conoceremos su utilidad para actualizar tablas en cascada, mantener la integridad referencial y realizar auditoría de cambios.
Este texto nos va a servir para tomar ciertas decisiones sobre que instrucciones ejecutar en función de algún tipo de condición.

TRIGGERS
Los triggers serán llamados desencadenadores, estos consisten en una especialización de los procedimientos almacenados que se activa cuando se ejecutan sentencias que modifican los datos o sus estructuras de alguna manera. SQL Server incluye soporte para dos tipos de desencadenadores: DML Y DDL.

DESENCADENADORES DML
Se ejecutan específicamente ante instrucciones INSERT, UPDATE o DELATE sobre una tabla o vista y pueden incluir sentencias que se ejecutan dentro del desencadenador como una transacción. Estos desencadenadores son útiles para:
Ø Aplicar cambios en cascadas sobre otras tablas.
Ø Enviar sentencias maliciosas de INSERT, UPDATE y DELETE.
Ø Llevar auditoria en tablas al efecto, de los cambios realizados en la base de datos.
Ø Evaluar el estado de una tabla y después de los cambios.
Ø Mantener actualizadas tablas totalizadoras.
Ø Mantener actualizados campos calculados.

Existen otros tipos de desencadenadores DML:
· AFTER: se ejecutan después que la acción INSERT, UPDATE o DELETE se ejecutó. Estos desencadenadores solo pueden crearse sobre tablas.
· INSTEAD OF: se ejecutan en lugar de la acción disparada. Estos desencadenadores pueden crearse también mediante vistas.
· .NET: estos pueden ser de tipo AFTER o INSTEAD OF y, en lugar de ejecutar sentencias T-SQL, invocan uno o más métodos que son miembros de un ensamblado y están escritos en código administrado, como C#.

DESENCADENADORES DDL.
A diferencia de los DML, pueden tener alcance de base de datos o de servidor (reaccionan ante ciertos eventos disparados en ambos ámbitos).

DESENCADENADORES CLR.
La programación de desencadenadores CLR (Common Languaje Runtime), requiere las siguientes acciones:
o Definir el desencadenador como una clase en lenguaje de .NET.
o Registrar el ensamblado en SQL Server referenciado a aquél creado en el CLR.
Los desencadenadores CLR pueden tener acceso a las tablas INSERTED y DELETED a través de un objeto propio, el SqlCommand, del objeto SqlContext.
También podrá obtener la cantidad de registros modificados por una sentencia UPDATE a través de la propiedad ColumnsUpdate del objeto SqlTriggerContext.
La propiedad ColumnsUpdate tiene como función devolver un array de valores booleanos que representan cada columna en la tabla modificada. Un valor TRUE en el array indica que la columna fue modificada.
La información de los eventos que disparan el desencadenador quedará disponible en la propiedad EventData del objeto SqlTriggersContext. Esta propiedad contiene un valor en formato XML que tiene.
v Hora del evento.
v Identificación del proceso o de la conexión a partir de los cuales se disparó el evento.
v Tipo de evento que disparó el desencadenador.

CREACIÓN DE DESENCADENADORES DDL y DML.
Es posible controlar el momento de ejecución de un desencadenador de varias formas. En los desencadenadores AFTER, el desencadenador se dispara luego de la acción de INSERT, UPDATE o DELETE. Se puede reemplazar la sentencia AFTER por FOR. Los desencadenadores INSTEAD OF se ejecutan en lugar de la acción disparadora y antes del proceso de restricciones.

Antes de crear un desencadenador, debemos tener en cuenta que:
Ø La sentencia CREATE TRIGGER debe ser la primera en la secuencia de comandos.
Ø Los permisos de creación de desencadenador son los de la tabla sobre la cual se está creando el desencadenador y no pueden ser transferidos a otros usuarios.
Ø Los desencadenadores DML son objetos de la base de datos y deben seguir las reglas de identificación de objetos.
Ø Solo se pueden crear desencadenadores en la base de datos en la que esta posicionado, aunque el desencadenador puede apuntar a objetos fuera de está.
Ø No se pueden crear desencadenadores sobre tablas temporarias o las tablas de sistema. Estás ultimas tampoco pueden ser referenciadas por un desencadenador. Por lo tanto, se deberán utilizar las vistas del esquema.
Ø Los desencadenadores INSTEAD OF DELETE e INSTEAD OF UODATE no pueden crearse en tablas que tienen definidas claves foráneas con acciones de UPDATE o DELETE.
Ø A pesar de que las sentencias TRUNCATE TABLE actúa como un DELETE, los desencadenadores definidos para DELETE no se dispararán, ya que la sentencia TRUNCATE no guarda su accionar en el registro de transacciones.
Para crear un desencadenador, se debe indicar:
1. El nombre.
2. La tabla sobre la cual ha de crearse.
3. Cuando se ha de disparar.
4. Las sentencias que lo activan.
5. Las sentencias de modificación de datos que lo componen.
Donde:
· Esquema: es el nombre del esquema al que pertenece el desencadenador.
· Nombre: es el nombre del desencadenador, conformado de acuerdo con las reglas de especificación de nombres de objetos.
· Tabla vistas: es el nombre de la tabla o vistas sobre la cual se está creando.
· DATABASE: aplica el alcance del desencadenador a la base de datos donde se está creando.
· ALL SERVER: aplica el alcance del desencadenador al servidor.
· WITH ENCRYPTION: encripta el texto del desencadenador, por lo cual no se podrá obtener su definición si se consulta la tabla sysmessages.
· EXCUTE AS: especifica el contexto de seguridad en el que se ejecuta el desencadenador.
· AFTER: indica que el desencadenador se disparará cuando todas las sentencias que actúan como disparadores del desencadenador se hayan ejecutado con éxito.
· INSTEAD OF: indica que el desencadenador se ejecutará en lugar de la sentencia disparadora.
· { [DELETE] [,] [INSERT] [,] [UPDATE] }: palabras reservadas que indican hacia que sentencias se disparará el desencadenador, debiéndose indicar por lo menos una acción.
· Tipo_evento: indica el nombre del evento T-SQL que, luego de su ejecución, provocará el disparo de un desencadenador DDL.
· Grupo_evento: grupo predefinido de eventos dentro de los cuales se agrupan las sentencias que actuarán como disparadores del desencadenador.
· WITH APPEND: indica que se deberá agregar un desencadenador de un tipo especificado. Se lo utiliza para mantener compatibilidad con versiones anteriores.
· NOT FOR REPLICATION: indica que el desencadenador no se disparará ante eventos disparados por procesos de replicación.
· AS: indica el inicio del bloque de sentencias SQL que ejecutará el desencadenador.
· Sentencia_sql: se utilizan para fijar las acciones y condiciones del desencadenador. En el caso de las condiciones, permite especificar situaciones en las que el desencadenador no ejecutará las sentencias definidas.
· Especificador_de_metodo: en el caso de desencadenador del CLR, indica el método de un ensamblado que se debe vincular al desencadenador.

FUNCIONES UPDATE () y COLUMNS_UPDATE ()
Se puede utilizar la función UPDATE () para determinar si una sentencia INSERT o UPDATE afectó una columna especifica de una tabla. La función devuelve TRUE o FALSE.
Por su parte COLUMNS_UPDATE permite evaluar varias columnas al mismo tiempo, devolviendo un patrón de bytes por las columnas modificadas. El operador varbinary, y para verificar este patrón, es necesario utilizar operadores binarios y una máscara.
El patrón de bytes estará ordenado de izquierda a derecha con el bit menos significativo en cada byte a la derecha. El bite mas a la derecha del byte mas a la izquierda del patrón representa la primera columna de la tabla. En consecuencia, la función COLUMNS_UPDATE devuelve varios bytes si la tabla tiene más de 8 columnas.
Si tenemos que verificar tablas que tienen más de 8 columnas, se debe utilizar la función SUBSTRING para analizar el bit retornado.

ANULAR LA ACCIÓN DE UN DESENCADENADOR
No es lo mismo ejecutar un ROLLBACK en un desencadenador que en una transacción normal dentro de un procedimiento almacenado.
En los procedimientos almacenados los ROLLBACK cancelará la transacción más externa del bloque, pero permitirá que el flujo de control del programa continúe en proceso.
En el caso de los desencadenadores, se cancelará la acción de toda la ejecución. Por este motivo se utiliza ROLLBACK sólo para el control de errores.
Los desencadenadores DDL se disparan para completar la acción iniciada con anterioridad. Por ejemplo ALTER_TABLE trigger se dispara cuando la tabla destino ha sido modificada con éxito; es por eso que no existen los desencadenadores DDL INSTEAD OF. Puede usar la sentencia ROLLBACK TRANSACTION para abortar la transacción y deshacer cualquier trabajo realizado.

DOCUMENTAR LOS DESENCADENADORES
En el caso de los desencadenadores encriptados, donde conviene documentar el código, se recomienda mantener al menos un gráfico de interacción entre desencadenadores y tablas afectadas, ya que puede resultar muy engorroso entender el funcionamiento del modelo de datos.

DESHABILITAR DESENCADENADORES
Para eliminar un desencadenador, se debe ejecutará la sentencia:
DISABLE TRIGGER [esquema .] nombre ON {nombre_objeto DATABASE SERVER } [;]

MODIFICAR DESENCADENADORES
Al igual que los procedimientos almacenados, la modificación de desencadenador exige la sentencia ALTER y la reescritura de toda su definición.

DESENCADENADORES ANIDADOS Y RECURSIVOS
Se considera que un desencadenador esta anidado cuando es disparado por acción de otro desencadenador. Los desencadenadores pueden anidarse hasta 32 niveles y su configuración puede modificarse por medio de la opción de configuración de servidor nested Triggers.
Por otra parte, los desencadenadores recursivos son aquellos sobre los cuales está permitida la llamada a sí mismos mediante la configuración de la opción RECURSIVE_TRIGGERS de la base de datos.
Existen dos tipos de recursividad:
Recursividad directa: se presenta cuando un desencadenador dispara una acción que provoca que el desencadenador se vuelva a ejecutar.
Recursividad indirecta: sucede cuando un desencadenador ejecuta una acción que dispara otro desencadenador, y este último, a su vez, vuelve a disparar el primero.
La opción de configuración de base de datos RECURSIVE_TRIGGERS solo previene contra la recursividad directa cuando está fijado en OFF. Los desencadenadores es INSTEAD OF no son contemplados por esta opción.

SQL AVANZADO

INSTRUCCIONES DE CONTROL EN T-SQL

IF..ELSE
La instrucción IF en T-SQL y SQL ANSI no utiliza THEN como bien podemos observar, ya que esta queda contenida entre el primer par de BEGIN…END que sucede a la instrucción IF y antecede la instrucción ELSE, por tal motivo no se le escribe.

En este ejemplo el IF modifica la gestión del proceso en función que se satisfaga la condición de ella.

CASE…WHEN…ELSE
Esta instrucción se utiliza para evaluar un conjunto de condiciones, y en función de cuál de ellas se cumpla, devolver un resultado entre muchos resultados posibles.

LA INSTRUCCIÓN BETWEEN
Permite abreviar la consulta de rango entre dos valores dados. Supongamos que usted desea saber cuántos empleados de la empresa poseen un número de legajo mayor a 1000 y menor a 5000. O sea, si están en el rango de legajos entre 1000 y 5000, usted podría hacer la consulta de dos formas diferentes, una sin la instrucción BETWEEN y la otra con la instrucción BETWEEN.

Sin BETWEEN

Con BETWEEN

USO DE CURSORES Y LA ISNTRUCCIÓN WHILE
El uso de la instrucción WHILE es independiente del uso de los cursores.
La instrucción WHILE se utiliza como un ciclo de control repetitivo que permite la ejecución de un conjunto de instrucciones de T-SQL de forma repetida, mientras que la condición que se evalúa con el ciclo WHILE sea verdadera (TRUE) y se interrumpe la repetición en el momento que dicha condición se evalúa como falsa (FALSE).

Los cursores son las estructuras que nos permiten trabajar de a un registro por vez de las diferentes consultas que se realicen a la base de datos. Poseen ciertas características parecen importantes:
El uso de los cursores amplia el procesamiento de los resultados debido a que permiten posicionarse en una fila determinada del conjunto de resultados.
Se pueden modificar los datos de la fila en la que se encuentra posicionado sin ningún tipo de inconvenientes.
Permite definir los distintos niveles de visibilidad de las modificaciones que está realizando usted u otro usuario sobre los datos en cuestión.
Se puede utilizar en procedimientos almacenados, triggers, o en secuencia de instrucciones de T-SQL.

COMBINACIONES DE TABLAS
Para combinar tablas se debe comparar una o más columnas (campos) de una tabla con una o más columnas de otra tabla. Como resultado se obtendrá un conjunto de filas (registros) que poseen columnas seleccionadas de cada una de las tablas combinadas que cumplen con la o las condiciones de combinación.

COMBINACIONES INTERNAS
Las combinaciones conectan dos tablas al cumplir una condición de combinación que devuelve como resultado un conjunto de registros que cumplen con dicha condición, que si desea puede asignar en una nueva tabla. Estas combinaciones devuelven información equivalente cuando se encuentra en ambas tablas información equivalente. Los tipos de combinaciones internas son las equivalentes y las naturales.

COMBINACIONES EQUIVALENTES
Primero veamos el código a aplicar en cada caso. La sintaxis en SQL SERVER es:

La sintaxis de ANSI SQL es:

Obtendremos como resultado lo siguiente:

COMBINACIONES NATURALES

Sintaxis de SQL SERVER

Sintaxis de ANSI SQL

Y esta tabla es la que obtendríamos

COMBINACIONES CRUZADAS O SIN RESTRICCIÓN
Este tipo de combinaciones devuelve como resultado una combinación de todas las filas de todas las tablas involucradas. Una combinación de este tipo no posee cláusula WHERE en la sintaxis de combinación de SQL Server de dos o más tablas, y utiliza la palabra clave CROSS JOIN en el caso de la sintaxis de combinación ANSI.
Este tipo de combinación devuelve como resultado el producto cartesiano de las tablas involucradas. Esto quiere decir que si la tabla A posee N filas y la tabla B posee M filas una combinación cruzada de la tabla A con la B devolverá una tabla de N*M filas.
En general, este tipo de combinaciones no es de mucha utilidad a no ser que uno desee saber cuáles son todas las combinaciones posibles para realizar algún tipo de análisis estadístico o matemático.
La sintaxis de SQL Server es:

La sintaxis ANSI SQL es:

COMBINACIONES EXTERNAS
Por medio de estas combinaciones puede restringir en el conjunto de resultados las filas de una tabla, mientras que permite todas las de la otra tabla. Estas combinaciones sirve para buscar filas huérfanas.
Existen diferentes tipos de operadores de combinación
En SQL Server puede utilizar los siguientes tipos de operadores:
Incluye todas las filas de la primera tabla y solo las filas que coinciden de la segunda tabla (es lo mismo que utilizar un LEFT OUTER JOIN)
Incluye todas las mismas de la segunda tabla y solo las filas que coincidan de la primera tabla (es lo mismo que realizar un RIGHT OUTER JOIN)
El inconveniente de estos operadores es que no se puede garantizar que siempre el conjunto de resultados sea correcto. Suele ocurrir errores cuando alguna de las tablas existen valores NULL en los campos de combinación. Por lo tanto al utilizar la combinación externa se sugiere que use sintaxis del ANSI SQL.

En ANSI SQL se utiliza la siguiente sintaxis:
LEFT OUTER JOIN: incluye todas las filas de la primera tabla (la de la izquierda) y solo las filas que coinciden de la segunda tabla.
RIGHT OUTER JOIN: incluye todas las filas de la segunda tabla (la de la derecha) y solo las filas que coincidan de la primera tabla.
FULL OUTER JOIN: incluye todas las filas no coincidentes de ambas tablas.
Las combinaciones externas LEFT OUTER JOIN y RIGHT OUTER JOIN pueden devolver el mismo conjunto de resultados dependiendo del orden de las tablas.

AUTOCOMBINACIONES
Como lo sugiere el nombre, una autocombinación relaciona las filas de una tabla con otras filas de la misma tabla. Para la mayoría de las autocombinaciones se emplean consultas de comparación. Por ejemplo, si se desea una lista de los contactos de los clientes agrupados por el cargo que poseen y ordenado por él.

CONSULTAS DE AGRUPACIÓN
Este tipo de consultas nos permite obtener información agrupada de una o más tablas. Por ejemplo, saber la cantidad de clientes para un año determinado, las ventas promedio para un determinado lapso de tiempo; son todas consultas de agrupación de datos. La información obtenida con este tipo de consultas es cuantitativa y no cualitativa.
Si se deseara saber la cantidad de contactos que poseen el mismo cargo para cada cargo ordenado por cargo, la consulta sería la siguiente:

La consulta anterior utiliza tres nuevas instrucciones:
Count (*): es una función incorporada en SQL y por ende en T-SQL que cuenta cuantas filas satisfacen la selección. Además el argumento de dichas funciones no tiene porque ser el *, sino que puede ser un campo o conjunto de campos predeterminados.
También parece la instrucción GROUP BY que agrupa por el campo o conjunto de campos que se describan después de ella.
Y la instrucción ORDER BY, que ordena por el campo o conjunto de campo o conjunto de campos que aparecen luego de ella.
Podría hacer una selección más fina y querer ver los cargos que poseen más de un contacto con lo cual la consulta sería:

Como consecuencia de realizar la consulta anterior, obtendríamos la tabla de resultados que se muestra:

CONCLUSIÓN
Tenemos que mencionar que debemos de tener cuidado al trabajar con desencadenadores anidados, ya que si un desencadenador dispara a otro de los que están en la cadena de ejecución, el procesamiento superará la cantidad de desencadenadores anidados permitidos (32) y concluirá su ejecución.
Por eso en esta lectura se dieron a conocer las formas de tener cuidado con los desencadenadores.

BIBLIOGRAFÍA
Rosa (2005). Cap. 10 Triggers
Rozic (2004). Cap. 9 SQL Avanzado

0 Comments: