Vous êtes sur la page 1sur 67

PROCEDIMIENTO

S ALMACENADOS
Y TRIGGERS

Procedimientos almacenados
Un procedimiento almacenado es un conjunto de sentencias
SQL y de control de flujo
Beneficios de los procedimientos almacenados:

Simplifican la ejecucin de tareas repetitivas


Corren ms rpido que las mismas instrucciones ejecutadas en
forma interactiva
Reducen el trfico a travs de la red
Pueden capturar errores antes que ellos puedan entrar a la base de
datos
Establece consistencia porque ejecuta las tareas de la misma
forma
Permite el desarrollo modular de aplicaciones
Ayuda a proveer seguridad
Puede forzar reglas y defaults complejos de los negocios

Tipos de procedimientos almacenados


Procedimientos almacenados definidos por el usuario
Son procedimientos definidos por el usuario que se
deben llamar explcitamente

Triggers

Son procedimientos definidos por el usuario que se


ejecutan automticamente cuando se modifica un dato en
una tabla

Procedimientos del sistema

Procedimientos suministrados por el sistema

Procedimientos extendidos

Procedimientos que hacen llamadas al sistema operativo


y ejecutan tareas a ese nivel

Interactive Execution

Creacin de un procedimiento almacenado

Ejecucin de un procedimiento almacenado

Ventajas en el rendimiento
Un procedimiento almacenado se ejecuta ms rpido que un
batch porque:
El procedimiento almacenado ya ha sido analizado
Ya se han resuelto las referencias a los objetos
referenciados en el procedimiento almacenado
No se necesita construir el rbol de bsqueda, l usa el que
se hace en el momento de compilarlo
No se necesita crear un plan de bsqueda, porque ya el
procedimiento tiene uno

Crear y borrar procedimientos almacenados


Sintaxis simplificada para create:
create proc procedure_name
as
statements
return

Ejemplo:
create proc proc_update_titles
as
update titles
set price = price * $0.95
where total_sales < 3000
return

Sintaxis simplificada para drop:


drop proc procedure_name

Ejemplo:
drop proc proc_update_titles

Ejecutar procedimientos almacenados


Sintaxis simplificada:

[exec | execute] procedure_name

Ejemplo:
execute proc_update_titles

Variables
Los procedimientos almacenados pueden crear y usar
variables locales
Las variables slo existen mientras exista el procedimiento
Las variables no las puede usar otro proceso

Ejemplo:
create proc proc_update_under_half_titles
as
declare @max_sales int, @half_max real
select @max_sales = max(total_sales)
from titles
select @half_max = @max_sales / 2
select title, total_sales from titles
where total_sales < @half_max
update titles
set price = price * $0.95
where total_sales < @half_max
return

Sentencias vlidas e invlidas


Un procedimiento almacenado puede:

Seleccionar y modificar datos


Crear tablas temporales y permanentes
Llamar otros procedimientos almacenados
Referenciar objetos de bases de datos

Un procedimiento almacenado no puede ejecutar:

use database
create view
create default
create rule
create procedure
create trigger

Procedimientos almacenados y permisos


Para permitir que otros usen un procedimiento
almacenado, el propietario debe dar los respectivos
permisos
Sintaxis simplificada:
grant execute
on procedure_name
to user_list

Ejemplo:
grant execute
on proc_update_titles
to tjovanka, vturlough, pbrown

Crear procedimientos almacenados


Crear un procedimiento almacenado sencillo:
create proc proc_hello
as
print "Hello, <your_name>"
return

Ver el cdigo fuente de un procedimiento:


sp_helptext proc_hello

Ejecutar el procedimiento:
exec proc_hello

Borrar los objetos de bases de datos:


drop proc proc_hello

Parmetros de entrada
An input Parmetro is a variable local to a
procedimiento almacenado that can
receive a value from the exec procedure
Sentencia

Definir parmetros de entrada


Sintaxis simplificada:

create procedure procedure_name


(parameter_name datatype default_value
[, parameter_name datatype default_value...] )
as
statements
return

Ejemplo:
create proc proc_author_info
(@lname varchar(40), @fname varchar(20))
as
-- lists the author and his or her books
select au_lname, au_fname, title
from authors, titles, titleauthor
where au_fname = @fname
and au_lname = @lname
and authors.au_id = titleauthor.au_id
and titles.title_id = titleauthor.title_id
return

Pasar parmetros
Dos mtodos para pasar valores a parmetros:
Paso de parmetros por posicin
Paso de parmetros por nombre

Paso de parmetros por posicin


Sintaxis para paso por posicin:

[exec | execute] procedure_name value [, value...]

Ejemplo:
exec proc_author_info "Ringer", "Albert"
au_lname
-------Ringer
Ringer

au_fname
-------Albert
Albert

title
-----

Is Anger the Enemy?


Life Without Fear

Los parmetros se deben pasar en el mismo orden en que


ellos aparecen en la sentencia create procedure
Como este mtodo es ms propenso a errores, se aconseja
el paso por nombre

Paso de parmetros por nombre


Sintaxis para paso por nombre:

[exec | execute] procedure procedure_name


parameter_name = value [, parameter_name = value ]

Ejemplo:
exec proc_author_info
@lname = "Ringer", @fname = "Albert"
au_lname
-------Ringer
Ringer

au_fname
-------Albert
Albert

title
----Is Anger the Enemy?
Life Without Fear

Los nombres de los parmetros en la sentencia exec deben


concordar con los nombres de los parmetros usados en la
sentencia create procedure
Los parmetros pueden pasar en cualquier orden

Valores por default


Se puede asignar un valor por default a un parmetro cuando
l no se indica en la sentencia exec
Ejemplo:
create proc proc_state_authors
(@state char(2) = "CA")
as
select au_lname, au_fname, state
from authors
where state = @state
return
exec proc_state_authors

-- No state value passed

au_lname
-------White
Green
...

state
----CA
CA

au_fname
-------Johnson
Marjorie

Parmetros de entrada: errores comunes


Los valores que se pasan no tienen el mismo tipo de datos
que los parmetros definidos
En la misma sentencia, se pasa un parmetro por posicin
despus de haber pasado un parmetro por nombre
Aunque no es recomendado, es posible mezclar los dos mtodos
para pasar valores, sin embargo, despus de pasar un valor a un
parmetro por nombre, todos los restantes de deben pasar por
nombre

Olvido de uno o ms parmetros


El olvido de uno o ms valores para los parmetros, hace que se
usen los valores por default

Los valores para los parmetros se pasan en un orden errado

Parmetros de entrada: Ejemplo


create procedure proc_insert_sale
(@stor_idchar(4)= NULL,
@ord_num varchar(20)= NULL,
@date
datetime= NULL)
as
/* If no date is passed, use the current date. */
if (@date is NULL)
begin
select @date = getdate()
end
begin transaction
/* insert sales order */
insert sales (stor_id, ord_num, date)
values (@stor_id, @ord_num, @date)
if @@error <> 0
begin
rollback transaction
raiserror 24001 "Transaction failed"
return
end
commit transaction
return

Parmetros de entrada
Crear un procedimiento almacenado que tenga un parmetro de
entrada:
create proc proc_hello_param (@name varchar(30))
as
print "Hello %1!", @name
return

Ejecutar el procedimiento con y sin un valor para el parmetro


de entrada. Una sentencia fallar:
exec proc_hello_param
exec proc_hello_param "<yourname>"

Crear un procedimiento almacenado que tiene un valor por


default para un parmetro de entrada:
create proc proc_hello_def
(@name varchar(30) = "whoever you are")
as
print "Hello %1!", @name
return

Parmetros de entrada
Ejecutar el procedimiento con y sin un valor para el
parmetro de entrada:
exec proc_hello_def
exec proc_hello_def "<yourname>"

Cul procedimiento almacenado parece ser ms amigable?


Borrar los objetos de bases de datos creados:
drop proc proc_hello_param, proc_hello_def

Retorno de valores
A return Parmetro is a variable local to a
procedimiento almacenado that can send
a value to the exec procedure Sentencia

Crear parmetros que retornan valores


Sintaxis simplificada:

create procedure procedure_name


(parameter_name datatype output
[, parameter_name datatype output...] )
as
statements
return

Ejemplo:
create proc proc_new_price
(@title_id char(6),
@new_price money output)
as
select @new_price = price
from titles
where title_id = @title_id
select @new_price = @new_price * $1.15
return

Usar parmetros que retornan valores


Sintaxis simplificada:

[exec | execute] procedure_name variable output

Ejemplo:
declare @my_title char(6), @my_price money
select @my_title = "PC8888"
exec proc_new_price
@my_title, @my_price output
---------23.00

Los valores que retornan los parmetros se pasan


automticamente al conjunto respuesta
El retorno de valores se pueden pasar por nombre o por
posicin
Se recomienda el paso por nombre

Lmite de anidamiento para procedimientos


Los procedimientos almacenados pueden llamar otros
procedimientos almacenados
El mximo nivel de anidamiento es 16
La variable @@nestlevel contiene el nivel de anidamiento
actual

Si se excede el nivel mximo:


Se abortan los procedimientos pendientes
El servidor retorna un error

Planes de bsqueda
Un plan de bsqueda es un conjunto ordenado de etapas que se
requieren para acceder los datos, incluyendo informacin sobre:
Si usar o no un ndice
El ndice a usar
El orden en el cual las tablas se deben encadenar

Los planes de bsqueda son creados por el optimizador de bsquedas


El optimizador de bsquedas usa informacin acerca de los objetos de base de
datos para producir el plan

Los planes de bsqueda creados para los procedimientos, se reutilizan


Cuando se ejecuta un procedimiento almacenado, el servidor chequea el cach
del procedimiento para un plan no usado
Si hay un plan de bsqueda no utilizado, el servidor lo usa
Si no hay un plan de bsqueda no utilizado, el servidor genera uno nuevo del
rbol de bsqueda en sysprocedures

Planes de bsqueda sub-ptimos


El plan de bsqueda creado para la una ejecucin de un procedimiento
almacenado puede que no sea el plan de bsqueda ptimo para la
siguiente ejecucin del procedimiento almacenado
Las dos ejecuciones pueden usar parmetros de entrada muy diferentes
Se pueden haber aadido nuevos ndices entre las dos ejecuciones
El tamao de las tablas accedidas pueden haber cambiado significativamente
entre las dos ejecuciones

Hay tres formas para forzar al servidor a generar un nuevo plan de


bsqueda
Usar with recompile en el procedimiento
Usar with recompile cuando se ejecute el procedimiento
Usar sp_recompile

Crear procedimientos con recompile


En un procedimiento, usar la opcin with recompile para
forzar al servidor a crear un nuevo plan de bsqueda cada
vez que se ejecute el procedimiento
Sintaxis simplificada:
create proc procedure_name
with recompile
as
statements
return

Crear procedimientos con recompile


Ejemplo:
create proc proc_list_California_authors
(@early_name varchar(80), @late_name
varchar(80))
with recompile
as
select au_id, au_lname, au_fname
from authors
where au_lname between @early_name and
@late_name
and state = "CA"
order by au_lname
return

Ejecucin de procedimientos with recompile


Cuando se ejecute un procedimiento almacenado, usar la
opcin with recompile para forzar al servidor a crear un
nuevo plan de bsqueda para esa ejecucin del
procedimiento
Esta opcin se puede usar cuando se ejecuta cualquier
procedimiento almacenado
Sintaxis simplificada:
[exec | execute] procedure_name with recompile
Ejemplo:
execute proc_update_titles with recompile

sp_recompile
sp_recompile hace que cada procedimiento
almacenado (y trigger) que utilice la tabla indicada se
recompile la siguiente vez que l se ejecute
Sintaxis:
sp_recompile table_name
Ejemplo:
sp_recompile authors

Trigger
Un trigger es un procedimiento almacenado asociado
con una tabla, el cual se ejecuta automticamente
cuando se modifica un dato de esa tabla

User-Defined

Can It Be

Can It Be

Can It Use

Explicitly

Executed

Parameters?

Called?

Automatically?

Yes

No

Yes

No

Yes

No

Stored
Procedure
Trigger

Aplicaciones Tpicas de triggers


Hacer modificaciones en cascada sobre tablas
relacionadas
Deshacer cambios que violan la integridad de los datos
Forzar restricciones que son muy complejas para
reglas y restricciones
Mantener datos duplicados
Mantener columnas con datos derivados
Hacer ajustes de registros

Definicin de un trigger
Un trigger se define asociado con una tabla para una o
ms sentencias de manipulacin de datos
Un trigger se puede definir para insert, update, o delete o
cualquier combinacin de ellos

Activacin de un trigger
Cuando se modifica un dato en una tabla que tiene
declarado un trigger para esa sentencia, el trigger se
dispara
El trigger se dispara una vez, independientemente del nmero
de filas afectadas
El trigger se dispara aunque no hayan filas afectadas

Triggers and transacciones


Un trigger es parte de la transaccin que causa el
disparo
El trigger puede deshacer:
As mismo solamente
As mismo y la sentencia que causa el disparo
La transaccin total

Reglas para triggers


Los triggers pueden:
Declarar variables locales
Invocar procedimientos almacenados

Los triggers no pueden:

Llamarse directamente
Usar parmetros
Definirse sobre tablas temporales o vistas
Crear objetos permanentes de base de datos

Las operaciones con registro mnimo (como select into)


no disparan los triggers

Crear triggers
Sintaxis simplificada:

create trigger trigger_name


on table_name
for {insert | update | delete} [, {insert | update | delete} ...]
as
sql_statements

Ejemplo:
create trigger trg_i_sales
on sales
for insert
as
if datename (dd,getdate()) = "Sun"
begin
raiserror 40070, "Sales cannot be
processed on Sunday."
rollback trigger
end

Borrar Triggers
Sintaxis simplificada:
drop trigger trigger_name

Ejemplo:
drop trigger trg_i_sales

Procedimientos del sistema para


procedimientos almacenados
sp_depends {table_name | trigger_name}

Cuando se da el nombre de tabla, lista todos los objetos


(incluyendo triggers) de la misma base de dtos
Cuando se da el nombre de trigger, lista todas las tablas
referencias

sp_help trigger_name

Muestra informacin del trigger

sp_helptext trigger_name

Muestra el cdigo usado para crear el trigger

sp_rename old_trigger_name, new_trigger_name


Cambia el nombre del trigger

Triggers - ejemplo
Crear dos tablas:
select * into myauthors
from pubs2..authors
create table myrecord (
mytime
myrows
)

datetime,
int

Crear un trigger que guarde la fecha y nmero de filas


afectadas por cada delete:
create trigger trg_d_myauthors
on myauthors
for delete
as
insert into myrecord
values (getdate(), @@rowcount)
return

Triggers - ejemplo
Ejecutar un delete y ver la tabla myrecords:
delete from myauthors
where state = "CA"
select * from myrecord

Ejecutar un delete que no afecta filas y ver la tabla


myrecords :
delete from myauthors
where 1 = 2
select * from myrecord

Borrar los objetos de base de datos creados:


drop table myauthors, myrecord

Las tablas inserted y deleted


inserted y deleted son dos tablas que se crean automticamente
cada vez que se dispara un trigger
inserted almacena cualquier fila que se vaya a aadir a la tabla
deleted almacena cualquier fila que se vaya a borrar de la tabla

Borrados
A delete adds rows to the deleted table

Uso de la tabla deleted - ejemplo


create trigger trg_d_publishers
on publishers
for delete
as
-- Exit trigger if no rows were modified.
if @@rowcount = 0
return
-- For deleted publishers, delete
-- corresponding titles
delete titles
from titles t, deleted d
where t.pub_id = d.pub_id
-- Appropriate actions would take place here
-- since a deleted publisher has far-reaching
-- effects throughout the database.
return

Inserciones
An insert adds rows to the inserted table

Uso de la tabla inserted - ejemplo


-- Make sure all au_ids match
if (select count(*) from authors a, inserted i
where a.au_id=i.au_id ) <> @num_rows
begin
raiserror 31114 "Attempt to insert
invalid au_id into titleauthor."
rollback transaction
return
end
return
go

Uso de la tabla inserted - ejemplo


-- Insert and update trigger on titleauthor
create trigger trg_iu_titleauthor
on titleauthor
for insert, update as
-- Find out how many rows were modified
declare @num_rows int
select @num_rows=@@rowcount
if @num_rows=0
return
-- Make sure all title_ids match
if (select count(*) from titles t, inserted i
where t.title_id=i.title_id) <> @num_rows
begin
raiserror 31113 "Attempt to insert
invalid title_id into titleauthor."
rollback transaction
return
end

Actualizaciones
An update adds rows to both tables

Uso de las tablas inserted y deleted


-- Insert, update, and delete trigger on salesdetail
create trigger trig_iud_salesdetail
on salesdetail
for insert, update, delete
as
-- Exit trigger if no rows were modified.
if @@rowcount = 0
return

Uso de las tablas inserted y deleted


-----

If a new quantity has been inserted or updated for a


given title_id, add the value to titles.total_sales. The
isnull function is used because titles.total_sales might
be NULL.

update titles
set total_sales = isnull(total_sales, 0) +
(select sum(qty)
from inserted
where titles.title_id = inserted.title_id)
where title_id in (select title_id from inserted)

Uso de las tablas inserted y deleted


-----

If an old quantity has been updated or deleted for a


given title_id, subtract the value from
titles.total_sales. The isnull function is used because
titles.total_sales might be NULL.

update titles
set total_sales = isnull(total_sales, 0) (select sum(qty)
from deleted
where titles.title_id = deleted.title_id)
where title_id in (select title_id from deleted)
return

Reglas para las tablas inserted y deleted


Ambas tablas tienen las mismas columnas que la tabla
asociada al trigger
El trigger puede consultar datos de las dos tablas
Otros procesos no pueden consultar datos de las dos tablas

El trigger no puede modificar datos en las dos tablas


Cada anidamiento de triggers tiene sus propias tablas
inserted y deleted
Si un trigger modifica datos de su tabla asociada, esos
cambios no se reflejan en las tablas inserted and deleted de
ese trigger

Tablas inserted and deleted - ejemplo


Crear una tabla:
select * into myauthors
from pubs2..authors

Crear un trigger que use la funcin suser_name( ) para


listar la(s) fila(s) que se borraron y el nombre del usuario:
create trigger trg_d_myauthors
on myauthors
for delete
as
select suser_name(), "deleted these rows:"
select * from deleted
return

Ejecutar un delete que afecte ms de una fila:


delete from myauthors
where state = "CA"

Tablas inserted and deleted - ejemplo


Ejecutar un delete que no afecte filas:
delete from myauthors
where 1 = 2

Borrar los objetos de base de datos:


drop table myauthors

Triggers y rollbacks
Tres tipos de rollbacks:
Deshacer el trigger
Deshacer el trigger y la sentencia que lo dispar
Deshacer toda la transaccin

Deshacer un trigger
Para deshacer un trigger, declarar un punto de grabacin y luego hacer el rollback
Un rollback sin punto de grabacin deshace toda la transaccin

Procedimiento almacenado
Caso A

begin tran
...
insert ...
print "in sp"
...
commit tran
print "sp done"

Trigger
save tran s1
....
rollback tran s1
print tr done
return

Procedimiento almacenado
Caso B

(este caso
ocaciona un
error)

begin tran
...
insert ...
print "in sp"
...
commit tran
print "sp done"

Trigger
begin tran s2
....
rollback tran s2
print tr done
return

Deshacer un trigger
rollback trigger deshace el trigger y la sentencia que lo
dispar
Sintaxis:
rollback trigger [with raiserror error_number
[error_statement] ]

Ejemplo:
create trigger trg_i_publishers
on publishers
for insert
as
if @@rowcount > 1
begin
rollback trigger with raiserror 40031
"You cannot insert more than one
publisher at a time."
return
end

Deshacer un trigger
Procedimiento almacenado
Case C
begin tran
...
insert ...
print "in sp"
...
commit tran
print "sp done"

Trigger
....
....
rollback trigger
print tr done
return

Deshacer una transaccin


Para deshacer toda la transaccin donde est inmerso el trigger,
ejecutar un rollback sin un punto de grabacin
Trigger
Procedimiento almacenado
begin tran
Case D
begin tran
...
insert ...
print "in sp"
...
commit tran
print "sp done"

Procedimiento almacenado
Case E
begin tran
...
insert ...
print "in sp"
...
commit tran
print "sp done"

...
rollback tran
print "tr done
return

Trigger
....
....
Rollback tran
print tr done
return

Triggers anidados
Un trigger anidado es un trigger que se dispara en respuesta
a una modificacin hecha en un trigger

Nivel mximo de anidamiento: 16


Tanto los procedimientos almacenados como los triggers cuentan
en la determinacin del nivel mximo
@@nestlevel retorna el nivel de anidamiento

Triggers recursivos
Un trigger recursivo es aquel que se dispara cuando
modifica su propia tabla

Por default, un trigger que modifica su propia tabla no


causa un disparo recursivo del trigger

Mtodos para integridad de datos


Dos mtodos para implementar integridad de datos
Domain
Integrity

Entity Integrity

Referential
Integrity

Constraints

Check
constraints

Primary key
constraints,
unique
constraints

References
constraints

Database
Objects

Rules

Indexes

Triggers

Actualizacin de valores llave


Accin deseada

Restricciones

Triggers

Insertarar valor de llave primaria

Permitido

Permitido

Insertar valor de llave fornea

Permitido

Permitido

Actualizar valor de llave primaria

No permitido*

Permitido

Actualizar valor de llave fornea

Permitido

Permitido

Borrar valor de llave primaria

No permitido*

Permitido

Borrar valor de llave fornea

Permitido

Permitido

*Valores de llaves primarias se pueden actualizar o borrar si no estn


referencidos en llaves forneas

Solamente en triggers es posible borrar o actualizar una


llave primaria
Slo en triggers es posible hacer cambios en cascada

Restricciones vs triggers
Ventajas de las restricciones:
Las restricciones (y reglas) son ms rpidas que los triggers
Las restricciones no requieren codificacin adicional
Es mejor para chequear datos antes de ingresarlos a la base
de datos

Ventajas de los triggers:


Muy flexible
Los triggers pueden hacer cualquier cosa que se pueda codificar

Mejor para las reglas complejas del negocio que no se pueden


expresar como restricciones referenciales tales como
actualizaciones o borrados en cascada

Vous aimerez peut-être aussi