You are on page 1of 37

Procedimientos almacenados en Transact SQL

Un procedimiento es un programa dentro de la base de datos que ejecuta una accin o conjunto de acciones especificas. Un procedimiento tiene un nombre, un conjunto de parmetros (opcional) y un bloque de cdigo. En Transact SQL los procedimientos almacenados pueden devolver valores (numerico entero) o conjuntos de resultados. Para crear un procedimiento almacenado debemos emplear la sentencia CREATE PROCEDURE.

CREATE PROCEDURE AS

nombre!procedure" #$param%

tipo", ...&

'' (entencias del procedure Para modificar un procedimiento almacenado debemos emplear la sentencia ALTER PROCEDURE.

ALTER PROCEDURE AS

nombre!procedure" #$param%

tipo", ...&

'' (entencias del procedure

El siguiente ejemplo muestra un procedimiento almacenado, denominado spu!add)liente que inserta un registro en la tabla *)+,E-.E(*.

CREATE PROCEDURE spu!add)liente $nombre varchar(%//), $apellido% varchar(%//), $apellido0 varchar(%//), $nif)if varchar(0/), $f1-aciento datetime

AS INSERT INTO )+,E-.E( (nombre, apellido%, apellido0, nifcif, f1nacimiento) VALUES ($nombre, $apellido%, $apellido0, $nif)if, $f1-aciento)

Para la ejecutar un procedimiento almacenado debemos utili2ar la sentencia EXEC. )uando la ejecucin del procedimiento almacenado es la primera instruccin del lote, podemos omitir el uso de EXEC. El siguiente ejemplo muestra la ejecucin del procedimiento almacenado anterior.

DECLARE $fec3a!nacimiento datetime set $fec3a!nacimiento 4 convert(datetime, 5%67/87%9:85, %/6) EXEC spu!add)liente 5Pedro5, 5;errarte5, 5(anc3e25, 5///////06065, $fec3a!nacimiento (iempre es deseable que las instrucciones del procedure esten dentro de un bloque TR CATC! y controlados por una transaccin.

ALTER PROCEDURE spu!add)liente $nombre varchar(%//), $apellido% varchar(%//), $apellido0 varchar(%//), $nif)if varchar(0/), $f1-aciento datetime AS "E#IN TR "E#IN TRAN INSERT INTO )+,E-.E(

(nombre, apellido%, apellido0, nifcif, f1nacimiento) VALUES ($nombre, $apellido%, $apellido0, $nif)if, $f1-aciento) CO$$IT END TR "E#IN CATC! ROLL"AC% PRINT E<<=<!>E((?@E() END CATC! (i queremos que los parmetros de un procedimiento almacenado sean de entrada' salida debemos especificarlo a travAs de la palabra clave OUTPUT , tanto en la definicin del procedure como en la ejecucin. El siguiente ejemplo muestra la definicin de un procedure con parmetros de salida.

CREATE PROCEDURE spu!=btener(aldo)uenta $num)uenta varchar(0/), $saldo decimal(%/,0) o&t'&t AS "E#IN SELECT $saldo 4 (?+B= (RO$ )UE-.?( )!ERE -U>)UE-.? 4 $num)uenta END

C para ejecutar este procedureD

DECLARE $saldo decimal(%/,0)

EXEC spu!=btener(aldo)uenta 50//:///////%5, $saldo o&t'&t PRINT $saldo Un procedimiento almacenado puede devolver valores numericos enteros a travAs de la instruccin <E.U<-. -ormalmente debemos utili2ar los valores de retorno para determinar si la ejecucin del procedimiento 3a sido correcta o no. (i queremos obtener valores se recomienda utili2ar parmetros de salida o funciones escalares (se vern mas adelante en este tutorial). El siguiente ejemplo muestra un procedimiento almacenado que devuelve valores.

CREATE PROCEDURE spu!EstaEn-umeros<ojos $num)uenta varchar(0/) AS "E#IN I( (SELECT (?+B= (RO$ )UE-.?( )!ERE -U>)UE-.? 4 $num)uenta) "E#IN RETURN % END ELSE RETURN / END El siguiente ejemplo muestra como ejecutar el procedure y obtener el valor devuelto. /

DECLARE $rv int EXEC $rv 4 spu!EstaEn-umeros<ojos 50//:///////%5 PRINT $rv =tra caracteristica muy interesante de los procedimientos almacenados en .ransact (E+ es que pueden devolver uno o varios conjuntos de resultados.

El siguiente ejemplo muestra un procedimiento almacenado que devuelve un conjunto de resultados.

CREATE PROCEDURE spu!>ovimientos)uenta $num)uenta varchar(0/) AS "E#IN SELECT $num)uenta, (?+B=!?-.E<,=<, (?+B=!P=(.E<,=<, ,>P=<.E, FG>=H,>,E-.= (RO$ >=H,>,E-.=( ,--E< I=,- )UE-.?( ON >=H,>,E-.=(.,B)UE-.? 4 )UE-.?(.,B)UE-.? )!ERE -U>)UE-.? 4 $num)uenta ORDER " END +a ejecucin del procedimiento se reali2a normalmente. FG>=H,>,E-.= DESC

EXEC spu!>ovimientos)uenta 50//:///////%5 El resultado de la ejecucion ... NUMCUENTA SALDO_ANTERIOR ------------ -----------------------------------200700000001 50.99 16:18:36.490 200700000001 0.99 16:20:41.183 200700000001 50.99 16:16:29.840 200700000001 0.99 16:14:05.900 SALDO_POSTERIOR IMPORTE FXMOVIMIENTO ---------------- ------100.99 50.99 0.99 50.99 50.00 50.00 50.00 50.00 2007-08-25 2007-08-23 2007-08-23 2007-08-23

(&nciones en Transact SQL

(E+ (erver proporciona al usuario la posibilidad de definir sus propias funciones, conocidad como UBF (user defined functions). E1isiten tres tipos de funciones. Estas sonD Funciones escalares. Funciones en lJnea. Funciones en lJnea de multiples sentencias

Funciones escalares
+as funciones escalares devuelven un Knico valor de cualquier tipo de los datos tal como int, money, varc3ar, real, etc. +a sinta1is para una funcin escalar es la siguienteD

CREATE (UNCTION ( '' +ista de parmetros

(calar!Function!-ame, s*sname, Function-ame"

$Param%, s*sname, $p%"

Bata!.ype!For!Param%, , int", ...

) '' .ipo de datos que devuelve la funcin. RETURNS AS "E#IN ... END El siguiente ejemplo muestra como crear una funcin escalar. Function!Bata!.ype, ,int"

CREATE (UNCTION fn!>ultiplica(aldo ( $-um)uenta VARC!AR(0/), $>ultiplicador DECI$AL(%/,0)

) RETURNS DECI$AL(%/,0) AS "E#IN DECLARE $(aldo DECI$AL(%/,0), $<eturn DECI$AL(%/,0)

SELECT $(aldo 4 (?+B= (RO$ )UE-.?( )!ERE -U>)UE-.? 4 $-um)uenta

SET $<eturn 4 $(aldo L $>ultiplicador

RETURN $<eturn END Pueden ser utili2adas en cualquier sentencia .ransact (E+. Un aspecto a tener en cuenta, es que para utili2ar una funcin escalar debemos identificar el nombre de la funcin con el propietario de la misma. El siguiente ejemplo muestra como utili2ar la funcin anteriormente creada en una sentencia .ransact (E+. Un aspecto muy a tener en cuenta es que la funcin ejecutar sus sentencias (E+E). una ve2 por cada fila del conjunto de resultados devuelto por la consulta (E+E). principal.

SELECT ,B)UE-.?, -U>)UE-.?, (?+B=, FG?+.?,

'' Ejecucion de la funcionD

d+o.fn!>ultiplica(aldo( -U>)UE-.?, ,B)UE-.?) AS <E(U+.?B=


(RO$ )UE-.?( El siguiente ejemplo muestra como utili2ar una funcin escalar en un script .ransact (E+.

DECLARE $-um)uenta VARC!AR(0/), $<esultado DECI$AL(%/,0)

SET $-um)uenta 4 50//:///////%5 SET $<esultado 4 dbo.fn!>ultiplica(aldo($-um)uenta, 6/.8)

PRINT $<esultado +as funciones escalares son muy similares a procedimientosalmacenadoscon parmetros de salida, pero estas pueden ser utili2adas en consultas de seleccion y en la clausula M3ere de las mismas. +as funciones no pueden ejecutar sentencias ,-(E<. o UPB?.E.

Funciones en linea
+as funciones en linea son las funciones que devuelven un conjunto de resultados correspondientes a la eecucin de una sentencia (E+E).. +a sinta1is para una funcin de tabla en linea es la siguienteD

CREATE (UNCTION ( '' +ista de parmetros

,nline!Function!-ame, s*sname, Function-ame"

$param%, s*sname, $p%"

Bata!.ype!For!Param%, , int",...

) RETURNS TA"LE AS RETURN ( '' (entencia .ransact (E+ ) El siguiente ejemplo muestra como crear una funcin en linea.

CREATE (UNCTION fn!>ovimientos)uenta ( $-um)uenta VARC!AR(0/) ) RETURNS TA"LE AS RETURN ( SELECT >=H,>,E-.=(.L (RO$ >=H,>,E-.=( ,--E< I=,- )UE-.?( ON >=H,>,E-.=(.,B)UE-.? 4 )UE-.?(.,B)UE-.? )!ERE )UE-.?(.-U>)UE-.? 4 $-um)uenta ) -o podemos utili2ar la clausula =<BE< NC en la sentencia de una funcin el lJnea. +as funciones en linea pueden utili2arse dentro de joins o querys como si fueran una tabla normal.

SELECT L (RO$ fn!>ovimientos)uenta(50//:///////%5) SELECT L (RO$ )UE-.?( ,--E< I=,- )UE-.?(!)+,E-.E ON )UE-.?(!)+,E-.E.,B)UE-.? 4 )UE-.?(.,B)UE-.? ,--E< I=,- )+,E-.E( ON )+,E-.E(.id 4 )UE-.?(!)+,E-.E.,B)+,E-.E ,--E< I=,- fn!>ovimientos)uenta(50//:///////%5) ? ON ?.,B)UE-.?4 )UE-.?(.,B)UE-.?

Funciones en lJnea de multiples sentencias


+as funciones en lJnea de multiples sentencias son similares a las funciones en lJnea e1cepto que el conjunto de resultados que devuelven puede estar compuesto por la ejecucin de varios consultas SELECT, Este tipo de funcin se usa en situaciones donde se requiere una mayor lgica de proceso. +a sinta1is para una funciones de tabla de multi sentencias es la siguienteD

CREATE (UNCTION ( '' +ista de parmetros

.able!Function!-ame, s*sname, Function-ame"

$param%, s*sname, $p%" ) RETURNS

data!type!for!param%, , int", ...

'' variable de tipo tabla y su estructura $.able!Hariable!-ame, s*sname, $.able!Har" TA"LE ( )olumn!%, s*sname, c%" Bata!.ype!For!)olumn%, , int",

)olumn!0, s*sname, c0" ) AS "E#IN

Bata!.ype!For!)olumn0, , int"

'' (entencias que cargan de datos la tabla declarada RETURN END El siguiente ejemplo muestra el uso de una funcion de tabla de multi sentencias.

7L Esta funcion busca la tres cuentas con mayor saldo L y obtiene los tres Kltimos movimientos de cada una L de estas cuentas L7

CREATE (UNCTION fn!)uenta>ovimietos() RETURNS $datos TA"LE ( '' Estructura de la tabla que devuelve la funcion. -um)uenta varchar(0/), (aldo decimal(%/,0), (aldo!anterior decimal(%/,0), (aldo!posterior decimal(%/,0), ,mporte!>ovimiento decimal(%/,0), F1>ovimiento datetime )

AS "E#IN '' Hariables necesarias para la lgica de la funcion. DECLARE $idcuenta int, $numcuenta varchar(0/), $saldo decimal(%/,0)

'' )ursor con las 6 cuentas de mayor saldo DECLARE )B?.=( CURSOR (OR SELECT TOP 6 ,B)UE-.?, -U>)UE-.?, (?+B= (RO$ )UE-.?( ORDER " (?+B= DESC

OPEN )B?.=( (ETC! )B?.=( INTO $idcuenta, $numcuenta, $saldo

'' <ecorremos el cursor )!ILE ($$FE.);!(.?.U( 4 /) "E#IN '' ,nsertamos la cuenta en la variable de salida INSERT INTO $datos (-um)uenta, (aldo) VALUES ($numcuenta, $saldo)

'' ,nsertamos los tres Kltimos movimientos de la cuenta INSERT INTO $datos ((aldo!anterior, (aldo!posterior, ,mporte!>ovimiento, F1>ovimiento ) SELECT TOP 6 (?+B=!?-.E<,=<, (?+B=!P=(.E<,=<, ,>P=<.E, FG>=H,>,E-.= (RO$ >=H,>,E-.=( )!ERE ,B)UE-.? 4 $idcuenta ORDER " FG>=H,>,E-.= DESC

'' Hamos a la siguiente cuenta (ETC! )B?.=( INTO $idcuenta, $numcuenta, $saldo END

CLOSE )B?.=(O DEALLOCATE )B?.=(O

RETURN END Para ejecutar la funcinD

select L -rom fn!)uenta>ovimietos() C el resultado obtenido ...


NumCuenta -----------200700000002 NULL NULL NULL Saldo -----500.00 NULL NULL NULL Saldo_anterior --------------NULL 550.00 "00.00 "00.00 Saldo_posterior ---------------NULL 500.00 550.00 550.00 Importe_Movimiento ------------------NULL 50.00 50.00 50.00 FxMovimiento ----------------------NULL 2007-0 -25 !"#! #$".%&0 2007-0 -2$ !"#20#%!.! $ 2007-0 -2$ !"#!%#05.&00

20070000000! NULL NULL NULL

!00.&& NULL NULL NULL

NULL 50.&& 0.&& 50.&&

NULL !00.&& 50.&& 0.&&

NULL 50.00 50.00 50.00

NULL 2007-0 -25 !"#! #$".%&0 2007-0 -2$ !"#20#%!.! $ 2007-0 -2$ !"#!"#2&. %0

(&nciones inte.radas de Transact SQL /I0


SQL Server pone a nuestra disposicin multitud de funciones predefinidas que proporcionan un amplio abanico de posibilidades. >ostramos aqui algunas de las frecuentes. Podemos acceder al listado completo a travAs del siguiente enlaceDhttp://technet.microsoft.com/eses/library/ms187786.aspx

)ast y )onvert
)onvierten una e1presin de un tipo de datos en otro de forma e1plJcita. CAST y CONVERT proporcionan funciones similares. CONVERT ( data!type # ( lengt3 ) & , e1pression # , style & ) BondeD data!type, es el tipo de destino al que queremos convertir la e1presion e1presion, la e1presion que queremos convertir style, parametro opcional que especifica el formato que tiene e1presion. Por ejemplo, si queremos convertir un varc3ar a datetime, aqui debemos especificar el formato de la fec3a (el tipo varc3ar).

BE)+?<E $fec3a varc3ar(0/) '' )onvertimos un valor varc3ar a datetime '' El %/6 indica el formato en el que esta escrita la fec3a '' %/6 4" dd7mm7aa (E. $fec3a 4 )=-HE<.(datetime, 5%97/670//P5,%/6)

(E+E). $fec3a

BE)+?<E $fec3a datetime,

$fec3aFormateada varc3ar(0/) '' )onvertimos a3ora una fec3a a varc3ar y la formateamos '' 6 4" dd7mm7aa (E. $fec3a 4 @E.B?.E() (E. $fec3aFormateada 4 )=-HE<.(varc3ar(0/), $fec3a, 6)

(E+E). $fec3aFormateada

'' Un ejemplo utili2ando )?(. BE)+?<E $dato varc3ar(0), $dato0 int (E. $dato 4 50:5 (E. $dato0 4 cast($dato ?( int)

(E+E). $dato0 ? continuacin mostramos la tabla de cdigos de estilo (obtenida de >icro(oft).


Sin el si.lo /aa0 /10 Con el si.lo 2 /aaaa0 Est3ndar Entrada4salida /50

' 1 7 5 8 9

6 o 166 (%, 0) 161 167 165 168 169

Halor predeterminado EE.UU. ?-(, Nritnico7FrancAs ?lemn ,taliano

mes dd aaaa 33Dmia.m. (o p. m.) mm7dd7aaaa aa.mm.dd dd7mm7aa dd.mm.aa dd'mm'aa

: ; < ' 16 11 17 ' 18 ' '

16: 16; 16<

(%)

' ' ' Halor predeterminado Q milisegundos EE.UU. I?PR,(=

dd mes aa >es dd, aa 33DmiDss mes dd aaaa 33DmiDssDmmma.m. (o p. m.) mm'dd'aa aa7mm7dd aammdd

(%)

= o 16= (%, 0) 116 111 117 15 o 115 (%, 0) 118 76 o 176 (0) 71 o 171 (0)

Europeo predeterminado Q dd mes aaaa milisegundos 33DmiDssDmmm(0S3) ' =BN) cannico =BN) cannico (con milisegundos) ,(=PT/% 33DmiDssDmmm(0S3) aaaa'mm'dd 33DmiDss(0S3) aaaa'mm'dd 33DmiDss.mmm(0S3) aaaa'mm'dd.33DmiDss.mmm (sin espacios) aaaa'mm'dd.33DmiDss.mmmU (sin espacios) dd mes aaaa 33DmiDssDmmma.m. dd7mm7aa 33DmiDssDmmma.m.

'

17: (S)

17;(T, :)

,(=PT/% con 2ona 3oraria U.

' '

156 (%, 0) 151 (0)

;ijri (8) ;ijri (8)

,snull
Evalua una e1presion de entrado y si esta es -U++, reempla2a -U++ con el valor de reempla2o especificado. El valor de reempla2o debe ser del mismo tipo de datos que la e1presion a evaluar. ISNULL ( e1pression , replacement!value )

BE)+?<E $dato,nt int,

$datoHarc3ar varc3ar(%//)

(E. $dato,nt 4 -U++ (E. $datoHarc3ar 4 -U++

(E+E). ,(-U++($dato, '%), ,(-U++($datoHarc3ar, 5-o 3ay dato5)

)=?+E()E Dev&elve la 'rimera e>'resi?n distinta de NULL entre s&s ar.&mentos, Un as'ecto a tener en c&enta es @&e todos los ar.&mentos de+en ser del mismo ti'o, )=?+E()E / e>'ression A B,,,n C 0

BE)+?<E $dato% int, $dato0 int, $dato6 int, $datoS int, $dato8 int

(E. $dato% 4 null (E. $dato0 4 -U++ (E. $dato6 4 -U++ (E. $datoS 4 %// (E. $dato8 4 %08

'' Bevuelve %// (E+E). )=?+E()E($dato%,$dato0,$dato6,$datoS,$dato8)

@etBate y @etU.)Bate
#etDate devuelve la fec3a y 3ora actuales del sistema en el formato interno estndar de (E+ (erver 0//8 para los valoresdatetime, #etUTCDate devuelve el valor datetime que representa la 3ora U.) (3ora universal coordinada u 3ora del meridiano de @reenMic3) actual.

BE)+?<E $fec3a+ocal datetime, $fec3aU.) datetime

(E. $fec3a+ocal 4 getdate() (E. $fec3aU.) 4 @E.U.)B?.E()

(E+E). $fec3a+ocal, $fec3aU.)

Tri..ers en Transact SQL


Un trigger( o desencadenador) es una clase especial de procedimiento almacenado que se ejecuta automticamente cuando se produce un evento en el servidor de bases de datos. (E+ (erver proporciona los siguientes tipos de triggersD Trigger DML, se ejecutan cuando un usuario intenta modificar datos mediante un evento de lenguaje de manipulacin de datos (B>+). +os eventos B>+ son instrucciones ,-(E<., UPB?.E o BE+E.E de una tabla o vista. Trigger DDL, se ejecutan en respuesta a una variedad de eventos de lenguaje de definicin de datos (BB+). Estos eventos corresponden principalmente a instrucciones )<E?.E, ?+.E< y B<=P de .ransact'(E+, y a determinados procedimientos almacenados del sistema que ejecutan operaciones de tipo BB+.

.rigger B>+.
+os trigger B>+ se ejecutan cuando un usuario intenta modificar datos mediante un evento de lenguaje de manipulacin de datos (B>+). +os eventos B>+ son instrucciones ,-(E<., UPB?.E o BE+E.E de una tabla o vista. +a sinta1is general de un trigger es la siguiente.

CREATE TRI##ER ON

.rigger!-ame, s*sname, .rigger!-ame"

.able!-ame, s*sname, .able!-ame" Bata!>odification!(tatements, , INSERT,DELETE,UPDATE"

?F.E< AS "E#IN

'' (E. -=)=U-. =- added to prevent e1tra result sets from '' interfering Mit3 (E+E). statements. SET NOCOUNT ONO '' ,nsert statements for trigger 3ere END ?ntes de ver un ejemplo es necesario conocer las tablas inserted y deleted. +as instrucciones de triggers B>+ utili2an dos tablas especiales denominadas inserted y deleted. (E+ (erver 0//8 crea y administra automticamente ambas tablas. +a estructura de las tablas inserted y deleted es la misma que tiene la tabla que 3a desencadenado la ejecucin del trigger. +a primera tabla (inserted) solo est disponible en las operaciones ,-(E<. y UPB?.E y en ella estn los valores resultantes despues de la insercin o actuali2acin. Es decir, los datos insertados. Inserted estar vacia en una operacin BE+E.E. En la segunda (deleted), disponible en las operaciones UPB?.E y BE+E.E, estn los valores anteriores a la ejecucin de la actuali2acin o borrado. Es decir, los datos que sern borrados. Deleted estar vacia en una operacion ,-(E<.. V-o e1iste una tabla UPB?.EBW -o, 3acer una actuali2acin es lo mismo que borrar (deleted) e insertar los nuevos (inserted). +a sentencia UPB?.E es la Knica en la que inserted y deleted tienen datos simultaneamente. -o puede se modificar directamente los datos de estas tablas. El siguiente ejemplo, graba un 3istorico de saldos cada ve2 que se modifica un saldo de la tabla cuentas.

CREATE TRI##ER .<!)UE-.?( ON )UE-.?(

?F.E< UPDATE AS "E#IN '' (E. -=)=U-. =- impide que se generen mensajes de te1to '' con cada instruccin SET NOCOUNT ONO INSERT INTO ;)=!(?+B=( (,B)UE-.?, (?+B=, FG(?+B=) SELECT ,B)UE-.?, (?+B=, getdate() (RO$ ,-(E<.EB END +a siguiente instruccin provocar que el trigger se ejecuteD

UPDATE )UE-.?( SET (?+B= 4 (?+B= Q %/ )!ERE ,B)UE-.? 4 % Una consideracin a tener en cuenta es que el trigger se ejecutar aunque la instruccion B>+ (UPB?.E, ,-(E<. o BE+E.E ) no 3aya afectado a ninguna fila. En este caso inserted y deleted devolveran un conjunto de datos vacio. Podemos especificar a que columnas de la tabla debe afectar el trigger.

ALTER TRI##ER .<!)UE-.?( ON )UE-.?( ?F.E< UPDATE AS

"E#IN '' (E. -=)=U-. =- impide que se generen mensajes de te1to '' con cada instruccin SET NOCOUNT ONO

I( UPDATE((?+B=) '' (olo si se actuali2a (?+B= "E#IN INSERT INTO ;)=!(?+B=( (,B)UE-.?, (?+B=, FG(?+B=) SELECT ,B)UE-.?, (?+B=, getdate() (RO$ ,-(E<.EB END END +os trigger estn dentro de la transaccin original (,nsert, Belete o Update) por lo cual si dentro de nuestro trigger 3acemos un <ollNacX .ran, no solo estaremos ec3ando atrs nuestro trigger sino tambiAn toda la transaccinO en otras palabras si en un trigger ponemos un <ollNacX .ran, la transaccin de ,nsert, Belete o Update volver toda 3acia atrs.

ALTER TRI##ER .<!)UE-.?( ON )UE-.?( ?F.E< UPDATE AS "E#IN '' (E. -=)=U-. =- impide que se generen mensajes de te1to '' con cada instruccin

SET NOCOUNT ONO INSERT INTO ;)=!(?+B=( (,B)UE-.?, (?+B=, FG(?+B=) SELECT ,B)UE-.?, (?+B=, getdate() (RO$ ,-(E<.EB

ROLL"AC% END En este caso obtendremos el siguiente mensaje de errorD +a transaccin termin en el desencadenador. (e anul el lote. Podemos activar y desactivar .riggers a tarvAs de las siguientes instrucciones.

'' Besactiva el trigger .<!)UE-.?( DISA"LE TRI##ER .<!)UE-.?( ON )UE-.?( @= '' activa el trigger .<!)UE-.?( ENA"LE TRI##ER .<!)UE-.?( ON )UE-.?( @= '' Besactiva todos los trigger de la tabla )UE-.?( ALTER TA"LE )UE-.?( DISA"LE TRI##ER ?++ @= '' ?ctiva todos los trigger de la tabla )UE-.?( ALTER TA"LE )UE-.?( ENA"LE TRI##ER ?++

.rigger BB+
+os trigger BB+ se ejecutan en respuesta a una variedad de eventos de lenguaje de definicin de datos (BB+). Estos eventos corresponden principalmente a instrucciones )<E?.E, ?+.E< y B<=P de .ransact'(E+, y a determinados procedimientos almacenados del sistema que ejecutan operaciones de tipo BB+. +a sinta1is general de un trigger es la siguiente.

CREATE TRI##ER ON DATA"ASE (OR AS "E#IN ,,, END

trigger!name, s*sname, table!alter!drop!safety"

data!definition!statements, , B<=P!.?N+E, ?+.E<!.?N+E"

+a siguiente instruccin impide que se ejecuten sentencias B<=P .?N+E y ?+.E< .?N+E en la base de datos.

CREATE TRI##ER .<!(E@U<,B?B ON DATA"ASE (OR B<=P!.?N+E, ?+.E<!.?N+E AS "E#IN RAISERROR (5No est permitido borrar ni modificar tablas !5 , %T, %) ROLL"AC% TRANSACTION END

C&rsores en Transact SQL


Un cursor es una variable que nos permite recorrer con un conjunto de resultados obtenido a travAs de una sentencia (E+E). fila a fila.

)uando trabajemos con cursores debemos seguir los siguientes pasos. Beclarar el cursor, utili2ando DECLARE ?brir el cursor, utili2ando OPEN +eer los datos del cursor, utili2ando (ETC! ... INTO )errar el cursor, utili2ando CLOSE +iberar el cursor, utili2ando DEALLOCATE +a sinta1is general para trabajar con un cursor es la siguiente.

'' Beclaracin del cursor DECLARE (OR sentencia!sql" nombre!cursor" CURSOR

'' apertura del cursor OPEN nombre!cursor"

'' +ectura de la primera fila del cursor (ETC! nombre!cursor" INTO lista!variables"

)!ILE ($$FE.);!(.?.U( 4 /) "E#IN '' +ectura de la siguiente fila de un cursor (ETC! ... END '' Fin del bucle Y;,+E nombre!cursor" INTO lista!variables"

'' )ierra el cursor CLOSE nombre!cursor"

'' +ibera los recursos del cursor DEALLOCATE nombre!cursor"

El siguente ejemplo muestra el uso de un cursor.

'' Beclaracion de variables para el cursor DECLARE $,d int, $-ombre varchar(088), $?pellido% varchar(088), $?pellido0 varchar(088), $-if)if varchar(0/), $F1-acimiento datetime

'' Beclaracin del cursor DECLARE c)lientes CURSOR (OR SELECT ,d, -ombre, ?pellido%, ?pellido0, -if)if, F1-acimiento (RO$ )+,E-.E( '' ?pertura del cursor OPEN c)lientes '' +ectura de la primera fila del cursor (ETC! c)lientes INTO $id, $-ombre, $?pellido%, $?pellido0, $-if)if, $F1-acimiento

)!ILE ($$FE.);!(.?.U( 4 / ) "E#IN PRINT $-ombre Q 5 5 Q $?pellido% Q 5 5 Q $?pellido0 '' +ectura de la siguiente fila del cursor (ETC! c)lientes INTO $id, $-ombre, $?pellido%, $?pellido0, $-if)if, $F1-acimiento

END

'' )ierre del cursor CLOSE c)lientes '' +iberar los recursos DEALLOCATE c)lientes

)uando trabajamos con cursores, la funcion $$FE.);!(.?.U( nos indica el estado de la Kltima instruccin FE.); emitida, los valores posibles sonD
Valor dev&elto Descri'ci?n

/ '% '0

+a instruccin FE.); se ejecut correctamente. +a instruccin FE.); no se ejecut correctamente o la fila estaba ms all del conjunto de resultados. Falta la fila recuperada. En la apertura del cursor, podemos especificar los siguientes parmetrosD

DECLARE

nombre!cursor" CURSOR

# +=)?+ Z @+=N?+ & # F=<Y?<B!=-+C Z ()<=++ &

# (.?.,) Z [EC(E. Z BC-?>,) Z F?(.!F=<Y?<B & # <E?B!=-+C Z ()<=++!+=)[( Z =P.,>,(.,) & # .CPE!Y?<-,-@ & (OR sentencia!sql"

El primer conjunto de parmetros que podemos especificar es # +=)?+ Z @+=N?+ &. ? continuacin mostramos el significado de cada una de estas opciones. LOCAL Especifica que el mbito del cursor es local para el proceso por lotes, procedimiento almacenado o desencadenador en que se cre el cursor.

DECLARE c)lientes CURSOR +=)?+ (OR SELECT ,d, -ombre, ?pellido%, ?pellido0, -if)if, F1-acimiento (RO$ )+,E-.E( #LO"AL Especifica que el mbito del cursor es global para la cone1in. Puede 3acerse referencia al nombre del cursor en cualquier procedimiento almacenado o proceso por lotes que se ejecute en la cone1in.

DECLARE c)lientes CURSOR @+=N?+ (OR SELECT ,d, -ombre, ?pellido%, ?pellido0, -if)if, F1-acimiento (RO$ )+,E-.E( (i no se especifica @+=N?+ ni +=)?+, el valor predeterminado se controla mediante la configuracin de la opcin de base de datos default to local cursor. El siguiente conjunto de parmetros que podemos especificar es # F=<Y?<B!=-+C Z ()<=++ &. ? continuacin mostramos el significado de cada una de estas opciones. (OR)ARDDONL Especifica que el cursor slo se puede despla2ar de la primera a la Kltima fila. FE.); -EG. es la Knica opcin de recuperacin admitida.

DECLARE c)lientes CURSOR F=<Y?<B!=-+C (OR SELECT ,d, -ombre, ?pellido%, ?pellido0, -if)if, F1-acimiento (RO$ )+,E-.E(

SCROLL Especifica que estn disponibles todas las opciones de recuperacin (F,<(., +?(., P<,=<, -EG., <E+?.,HE, ?N(=+U.E). (i no se especifica ()<=++ en una instruccin BE)+?<E )U<(=< la Knica opcin de recuperacin que se admite es -EG.. -o es posible especificar ()<=++ si se incluye tambiAn F?(.!F=<Y?<B. (i se incluye la opcin ()<=++, la forma en la reali2amos la lectura del cursor varia, debiendo utili2ar la siguiente sinta1isD FE.); # -EG. Z P<,=< Z F,<(. Z +?(. Z <E+?.,HE Z ?N(=+U.E & F<=> ,-.=

'' Beclaracion de variables para el cursor DECLARE $,d int, $-ombre varchar(088), $?pellido% varchar(088), $?pellido0 varchar(088), $-if)if varchar(0/), $F1-acimiento datetime

'' Beclaracin del cursor DECLARE c)lientes CURSOR ()<=++ (OR SELECT ,d, -ombre, ?pellido%, ?pellido0, -if)if, F1-acimiento (RO$ )+,E-.E(

'' ?pertura del cursor OPEN c)lientes '' +ectura de la primera fila del cursor (ETC! -EG. (RO$ c)lientes INTO $id, $-ombre, $?pellido%, $?pellido0, $-if)if, $F1-acimiento

)!ILE ($$FE.);!(.?.U( 4 / ) "E#IN PRINT $-ombre Q 5 5 Q $?pellido% Q 5 5 Q $?pellido0 '' +ectura de la siguiente fila del cursor (ETC! -EG. (RO$ c)lientes INTO $id,$-ombre,$?pellido%,$?pellido0,$-if)if,$F1-acimiento END '' +ectura de la fila anterior (ETC! P<,=< (RO$ c)lientes INTO $id, $-ombre, $?pellido%, $?pellido0, $-if)if, $F1-acimiento PRINT $-ombre Q 5 5 Q $?pellido% Q 5 5 Q $?pellido0 '' )ierre del cursor CLOSE c)lientes '' +iberar los recursos DEALLOCATE c)lientes El siguiente conjunto de parmetros que podemos especificar es # (.?.,) Z [EC(E. Z BC-?>,) Z F?(.!F=<Y?<B &. ? continuacin mostramos el significado de cada una de estas opciones. STATIC Befine un cursor que 3ace una copia temporal de los datos que va a utili2ar. .odas las solicitudes que se reali2an al cursor se responden desde esta tabla temporal de tempdbO por tanto, las modificaciones reali2adas en las tablas base no se reflejan en

los datos devueltos por las operaciones de recuperacin reali2adas en el cursor y adems este cursor no admite modificaciones.

DECLARE c)lientes CURSOR (.?.,) (OR SELECT ,d, -ombre, ?pellido%, ?pellido0, -if)if, F1-acimiento (RO$ )+,E-.E( %E SET Especifica que la pertenencia y el orden de las filas del cursor se fijan cuando se abre el cursor. El conjunto de claves que identifica las filas de forma Knica est integrado en la tabla denominada Xeyset de tempdb.

DECLARE c)lientes CURSOR [EC(E. (OR SELECT ,d, -ombre, ?pellido%, ?pellido0, -if)if, F1-acimiento (RO$ )+,E-.E( D NA$IC Befine un cursor que, al despla2arse por Al, refleja en su conjunto de resultados todos los cambios reali2ados en los datos de las filas. +os valores de los datos, el orden y la pertenencia de las filas pueden cambiar en cada operacin de recuperacin. +a opcin de recuperacin ?N(=+U.E no se puede utili2ar en los cursores dinmicos.

DECLARE c)lientes CURSOR BC-?>,) (OR SELECT ,d, -ombre, ?pellido%, ?pellido0, -if)if, F1-acimiento (RO$ )+,E-.E( (ASTD(OR)ARD Especifica un cursor F=<Y?<B!=-+C, <E?B!=-+C con las optimi2aciones de rendimiento 3abilitadas. -o se puede especificar F?(.!F=<Y?<B si se especifica tambiAn ()<=++ o F=<!UPB?.E.

DECLARE c)lientes CURSOR F?(.!F=<Y?<B (OR SELECT ,d, -ombre, ?pellido%, ?pellido0, -if)if, F1-acimiento (RO$ )+,E-.E( En (E+ (erver 0///, las opciones de cursor F?(.!F=<Y?<B y F=<Y?<B!=-+C se e1cluyen mutuamente. (i se especifican ambas, se genera un error. En (E+ (erver 0//8, las dos palabras clave se pueden utili2ar en la misma instruccin BE)+?<E )U<(=<. El siguiente conjunto de parmetros que podemos especificar es # <E?B!=-+C Z ()<=++!+=)[( Z =P.,>,(.,) &. ? continuacin mostramos el significado de cada una de estas opciones. READDONL Evita que se efectKen actuali2aciones a travAs de este cursor. -o es posible 3acer referencia al cursor en una clusula Y;E<E )U<<E-. =F de una instruccin UPB?.E o BE+E.E. Esta opcin reempla2a la capacidad de actuali2ar el cursor.

DECLARE c)lientes CURSOR <E?B!=-+C (OR SELECT ,d, -ombre, ?pellido%, ?pellido0, -if)if, F1-acimiento (RO$ )+,E-.E( SCROLLDLOC%S Especifica que se garanti2a que las actuali2aciones o eliminaciones posicionadas reali2adas a travAs del cursor sern correctas. >icrosoft (E+ (erver bloquea las filas cuando se leen en el cursor para garanti2ar que estarn disponibles para futuras modificaciones. -o es posible especificar ()<=++!+=)[( si se especifica tambiAn F?(.!F=<Y?<B o (.?.,).

DECLARE c)lientes CURSOR ()<=++!+=)[( (OR SELECT ,d, -ombre, ?pellido%, ?pellido0, -if)if, F1-acimiento (RO$ )+,E-.E(

OPTI$ISTIC Especifica que las actuali2aciones o eliminaciones posicionadas reali2adas a travAs del cursor no se reali2arn correctamente si la fila se 3a actuali2ado despuAs de ser leJda en el cursor. (E+ (erver no bloquea las filas al leerlas en el cursor. En su lugar, utili2a comparaciones de valores de columna timestamp o un valor de suma de comprobacin si la tabla no tiene columnas timestamp, para determinar si la fila se 3a modificado despuAs de leerla en el cursor. (i la fila se 3a modificado, el intento de actuali2acin o eliminacin posicionada genera un error. -o es posible especificar =P.,>,(.,) si se especifica tambiAn F?(.!F=<Y?<B.

DECLARE c)lientes CURSOR =P.,>,(.,) (OR SELECT ,d, -ombre, ?pellido%, ?pellido0, -if)if, F1-acimiento (RO$ )+,E-.E( Por Kltimo, queda la opcin .CPE!Y?<-,-@ T PED)ARNIN# Especifica que se envJa un mensaje de advertencia al cliente si el cursor se convierte implJcitamente del tipo solicitado a otro.

DECLARE c)lientes CURSOR .CPE!Y?<-,-@ (OR SELECT ,d, -ombre, ?pellido%, ?pellido0, -if)if, F1-acimiento (RO$ )+,E-.E( Podemos especificar multiples parmetros en la apertura de cursor, pero unicamente un parmetro de cada grupo. Por ejemploD

DECLARE c)lientes CURSOR +=)?+ (.?.,) .CPE!Y?<-,-@ (OR SELECT ,d, -ombre, ?pellido%, ?pellido0, -if)if, F1-acimiento (RO$ )+,E-.E(

Para actuali2ar los datos de un cursor debemos especificar F=< UPB?.E despues de la sentencia (E+E). en la declaracin del cursor, y Y;E<E )U<<E-. =F nombre!cursor" en la sentencia UPB?.E tal y como muestra el siguiente ejemplo. '' Beclaracion de variables para el cursor DECLARE $,d int, $-ombre varchar(088), $?pellido% varchar(088), $?pellido0 varchar(088), $-if)if varchar(0/), $F1-acimiento datetime '' Beclaracin del cursor DECLARE c)lientes CURSOR (OR SELECT ,d, -ombre, ?pellido%, ?pellido0, -if)if, F1-acimiento (RO$ )+,E-.E( (OR UPDATE

'' ?pertura del cursor OPEN c)lientes '' +ectura de la primera fila del cursor (ETC! c)lientes INTO $id, $-ombre, $?pellido%, $?pellido0, $-if)if, $F1-acimiento

)!ILE ($$FE.);!(.?.U( 4 / ) "E#IN UPDATE )lientes SET ?PE++,B=0 4 isnull($?pellido0,55) Q 5 ' >odificado5

)!ERE CURRENT O( c)lientes '' +ectura de la siguiente fila del cursor (ETC! c)lientes INTO $id, $-ombre, $?pellido%, $?pellido0, $-if)if, $F1-acimiento END '' )ierre del cursor CLOSE c)lientes '' +iberar los recursos DEALLOCATE c)lientes

SQL din3mico en Transact SQL


.ransact (E+ permite dos formas de ejecutar (E+ dinamico(construir sentencias (E+ dinamicamente para ejecutarlas en la base de datos)D +a instruccin EXECUTE E o simplemente EXEC El procedimiento almacenado s'De>ec&tes@l Besde aquJ recomendamos la utili2acin de sp! e>ec&tes@l si bien vamos a mostrar la forma de trabajar con ambos mAtodos.

+a instruccin EGE)U.E
+a instruccin EGE)U.E ' o simplemente EGE) ' permite ejecutar una cadena de caracteres que representa una sentencia (E+. +a cadena de caracteres debe ser de tipo nvarchar . El siguiente ejemplo muestra como ejecutar una cadena de caracteres con la instruccin EXEC.

BE)+?<E $sql nvarc3ar(%///)

(E. $sql 4 5(E+E).

)=B!P?,(, -=>N<E!P?,(, ?).,H=, FG!?+.? F<=> P?,(E(5 EGE) ($sql) .ambiAn con (E+ dinamico podemos ejecutar sentencias de tipo BB+ (Bata Befinition +anguaje), como )<E?.E .?N+E.

BE)+?<E $sql nvarc3ar(%///) (E. $sql45)<E?.E .?N+E .E>P=<?+ ( ,B int ,BE-.,.C, B?.= varc3ar(%//))5 EGE) ($sql)

(E. $sql 4 5(E+E). L F<=> .E>P=<?+5 EGE) ($sql) El principal incoveniente de trabajar con la instruccin EXEC es que no permite el uso de parametros abriendo la puerta a potenciales ataques de (ql ,njections ' http://www.devjoker.com/contenidos/Articulos/45/Seguridaden-Internet-SQLInjections.aspx ?dems el uso de la instruccin EXEC es menos eficiente, en terminos de rendimiento, que s'De>ec&tes@l. Para solventar el problema debemos trabajar siempre con s@De>ec&tes@l, que permite el uso de parametros y con el que obtendremos un mejor rendimiento de nuestras consultas.

El procedimiento almacenado sp!e1ecutesql


Para ejecutar sql dinamico, se recomienda utili2ar el procedimiento almacenado s'De>ec&tes@l, en lugar de una instruccinEXECUTE.

s'De>ec&tes@l admite la sustitucin de parmetros s'De>ec&tes@l es ms seguro y verstil que EXECUTE s'De>ec&tes@l genera planes de ejecucin con ms probabilidades de que (E+ (erver los vuelva a utili2ar, es ms efica2 queEXECUTE. El siguiente ejemplo muestra el uso (muy simple) de s'De>ec&tes@l.

BE)+?<E $sql nvarc3ar(%///)

(E. $sql 4 5(E+E). )=B!P?,(, -=>N<E!P?,(, ?).,H=, FG!?+.? F<=> P?,(E(5

EGE) sp!e1ecutesql $sql s'De>ec&tes@l admite la sustitucin de valores de parmetros para cualquier parmetro especificado en la cadena .ransact'(E+ a ejecutar. El siguiente ejemplo muestra el uso de s'De>ec&tes@l con parmetrosD

BE)+?<E $sql nvarc3ar(%///), $paramBefinition nvarc3ar(088), $paramHalue c3ar(6)

(E. $paramBefinition 4 5$codPais c3ar(6)5

(E. $paramHalue 4 5E(P5 (E. $sql 4 5(E+E). )=B!P?,(, -=>N<E!P?,(, ?).,H=, FG!?+.? F<=> P?,(E( Y;E<E )=B!P?,( 4 $codPais5

EGE) sp!e1ecutesql $sql, $paramBefinition, $paramHalue

You might also like