A Pun Test Em a 6

23
Tema 6. Programación de bases de datos 1 Introducción _________________________________________________________________ 2 2 Procedimientos almacenados y las tablas de permisos _______________________________ 2 3 Sintaxis de procedimientos almacenados __________________________________________ 2 3.1 CREATE PROCEDURE y CREATE FUNCTION ____________________________________________3 3.2 ALTER PROCEDURE y ALTER FUNCTION _______________________________________________5  3.3 DROP PROCEDURE y DROP FUNCTION _______________________________________________6 3.4 SHOW CREATE PROCEDURE y SHOW CREATE FUNCTION _________________________________6 3.5 SHOW PROCEDURE STATUS y SHOW FUNCTION STATUS _________________________________6  3.6 La sentencia CALL ________________________________________________________________6  3.7 Sentencia compuesta BEGIN... END __________________________________________________7  3.8 Sentencia DECLARE _______________________________________________________________7 3.9 Variables en procedimientos almacenados ____________________________________________7  3.9.1 Declarar variables locales con DECLARE _____________________________________________________ 7 3.9.2 Sentencia SET para variables ______________________________________________________________ 7 3.9.3 La sentenci a SELECT... INTO ____________________ ______________________ _____________________ 8 3.10 Conditions y Handlers _____________________________________________________________8  3.10.1 Condiciones DECLARE ______________________ ______________________ _____________________ 8 3.10.2 DECLARE handlers _____________________ ______________________ _____________________ ____ 8 3.11 Cursores________________________________________________________________________9 3.11.1 Declara r cursores ______________________ ______________________ _____________________ ___ 10 3.11.2 Sentencia OPEN del cursor ___ ______________________ ______________________ _____________ 10 3.11.3 Sentencia de cursor FETCH ____________________________________ ______________________ __ 10  3.11.4 Sentencia de cursor CLOSE _____________________________ ______________________ _________ 10 3.12 Constructores de control de flujo __________________________________________________ 10 3.12.1 Sentencia IF ____________________ _____________________ ______________________ _________ 10 3.12.2 La sentencia CASE ______________ ______________________ ______________________ _________ 10 3.12.3 Sentencia LOOP _____________________ ____________________ ______________________ ______ 11 3.12.4 Sentencia LEAVE ____________________________________________________________________ 11 3.12.5 La sentencia ITERATE ___________________ ______________________ ______________________ __ 11 3.12.6 Sentencia REPEAT ___________________________________________________________________ 11 3.12.7 Sentencia WHILE _____________________________________ ______________________ _________ 12 4 Registro binario de procedimientos almacenados y disparadores ______________________ 12 5 Disparadores o triggers _______________________________________________________ 15 5.1 Sintaxis de CREATE TRIGGER _____________________________________________________ 16 5.2 Sintaxis de DROP TRIGGER _______________________________________________________ 18 5.3 Utilización de disparadores ______________________________________________________ 18 6 Ejercicios ___________________________________________________________________ 21 

Transcript of A Pun Test Em a 6

Page 1: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 1/23

 

Tema 6. Programación de bases de datos

1  Introducción _________________________________________________________________ 2 

2  Procedimientos almacenados y las tablas de permisos _______________________________ 2 

3  Sintaxis de procedimientos almacenados __________________________________________ 2 

3.1  CREATE PROCEDURE y CREATE FUNCTION ____________________________________________3 

3.2  ALTER PROCEDURE y ALTER FUNCTION _______________________________________________5 

3.3  DROP PROCEDURE y DROP FUNCTION _______________________________________________6 

3.4  SHOW CREATE PROCEDURE y SHOW CREATE FUNCTION _________________________________6 

3.5  SHOW PROCEDURE STATUS y SHOW FUNCTION STATUS _________________________________6 

3.6  La sentencia CALL ________________________________________________________________6 

3.7  Sentencia compuesta BEGIN... END __________________________________________________7 3.8  Sentencia DECLARE _______________________________________________________________7 

3.9  Variables en procedimientos almacenados ____________________________________________7 

3.9.1  Declarar variables locales con DECLARE _____________________________________________________ 7 3.9.2  Sentencia SET para variables ______________________________________________________________ 7 3.9.3  La sentencia SELECT... INTO _______________________________________________________________ 8 

3.10  Conditions y Handlers _____________________________________________________________8 

3.10.1  Condiciones DECLARE _________________________________________________________________ 8 3.10.2  DECLARE handlers ____________________________________________________________________ 8 

3.11  Cursores ________________________________________________________________________9 

3.11.1  Declarar cursores ____________________________________________________________________ 10 3.11.2  Sentencia OPEN del cursor ____________________________________________________________ 10 3.11.3  Sentencia de cursor FETCH ____________________________________________________________ 10 3.11.4  Sentencia de cursor CLOSE ____________________________________________________________ 10 

3.12  Constructores de control de flujo __________________________________________________ 10 

3.12.1  Sentencia IF ________________________________________________________________________ 10 3.12.2  La sentencia CASE ___________________________________________________________________ 10 3.12.3  Sentencia LOOP _____________________________________________________________________ 11 3.12.4  Sentencia LEAVE ____________________________________________________________________ 11 3.12.5  La sentencia ITERATE _________________________________________________________________ 11 3.12.6  Sentencia REPEAT ___________________________________________________________________ 11 3.12.7  Sentencia WHILE ____________________________________________________________________ 12 

4  Registro binario de procedimientos almacenados y disparadores ______________________ 12 

5  Disparadores o triggers _______________________________________________________ 15 

5.1  Sintaxis de CREATE TRIGGER _____________________________________________________ 16 

5.2  Sintaxis de DROP TRIGGER _______________________________________________________ 18 

5.3  Utilización de disparadores ______________________________________________________ 18 

6  Ejercicios ___________________________________________________________________ 21 

Page 2: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 2/23

 

Tema 6. Programación de bases de datos Base de datos

2

 

1 Introducción

Los procedimientos almacenados y funciones son nuevas funcionalidades de la versión de MySQL 5.0. Un

procedimiento almacenado es un conjunto de comandos SQL que pueden almacenarse en el servidor. Una

vez que se hace, los clientes no necesitan relanzar los comandos individuales pero pueden en su lugar refe-

rirse al procedimiento almacenado.

Algunas situaciones en que los procedimientos almacenados pueden ser particularmente útiles:

Cuando múltiples aplicaciones cliente se escriben en distintos lenguajes o funcionan en distintas pla-

taformas, pero necesitan realizar la misma operación en la base de datos.

Cuando la seguridad es muy importante. Los bancos, por ejemplo, usan procedimientos almacena-

dos para todas las operaciones comunes. Esto proporciona un entorno seguro y consistente, y los

procedimientos pueden asegurar que cada operación se loga apropiadamente. En tal entorno, las

aplicaciones y los usuarios no obtendrían ningún acceso directo a las tablas de la base de datos, sólo

pueden ejecutar algunos procedimientos almacenados.

Los procedimientos almacenados pueden mejorar el rendimiento ya que se necesita enviar menos informa-

ción entre el servidor y el cliente. El intercambio que hay es que aumenta la carga del servidor de la base de

datos ya que la mayoría del trabajo se realiza en la parte del servidor y no en el cliente. Considere esto simuchas máquinas cliente (como servidores Web) se sirven a sólo uno o pocos servidores de bases de datos.

Los procedimientos almacenados le permiten tener bibliotecas o funciones en el servidor de base de datos.

Esta característica es compartida por los lenguajes de programación modernos que permiten este diseño

interno, por ejemplo, usando clases. Usando estas características del lenguaje de programación cliente es

beneficioso para el programador incluso fuera del entorno de la base de datos.

MySQL sigue la sintaxis SQL: 2003 para procedimientos almacenados, que también usa IBM DB2.

La implementación de MySQL de procedimientos almacenados está en progreso. Toda la sintaxis descrita en

este capítulo se soporta y cualquier limitación y extensión se documenta apropiadamente.

2 Procedimientos almacenados y las tablas de permisos

Los procedimientos almacenados requieren la tabla proc en la base de datos MySQL. Esta tabla se crea

durante la instalación de MySQL 5.0. Si está actualizando a MySQL 5.0 desde una versión anterior, asegúrese

de actualizar sus tablas de permisos para asegurar que la tabla proc existe.

Desde MySQL 5.0.3, el sistema de permisos se ha modificado para tener en cuenta los procedimientos alma-

cenados como sigue:

El permiso CREATE ROUTINE se necesita para crear procedimientos almacenados.

El permiso ALTER ROUTINE se necesita para alterar o borrar procedimientos almacenados. Este

permiso se da automáticamente al creador de una rutina.El permiso EXECUTE se requiere para ejecutar procedimientos almacenados. Sin embargo, este

permiso se da automáticamente al creador de la rutina. También, la característica SQL SECURITY 

por defecto para una rutina es DEFINER, lo que permite a los usuarios que tienen acceso a la base

de datos ejecutar la rutina asociada.

3 Sintaxis de procedimientos almacenados

Los procedimientos almacenados y rutinas se crean con comandos CREATE PROCEDURE y CREATE

FUNCTION. Una rutina es un procedimiento o una función. Un procedimiento se invoca usando un coman-

do CALL, y sólo puede pasar valores usando variables de salida. Una función puede llamarse desde dentro

de un comando como cualquier otra función (esto es, invocando el nombre de la función), y puede devolverun valor escalar. Las rutinas almacenadas pueden llamar otras rutinas almacenadas.

Page 3: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 3/23

 

Tema 6. Programación de bases de datos Base de datos

3

Desde MySQL 5.0.1, los procedimientos almacenados o funciones se asocian con una base de datos. Esto

tiene varias implicaciones:

Cuando se invoca la rutina, se realiza implícitamente USE db_name ( y se deshace cuando acaba la

rutina). Los comandos USE dentro de procedimientos almacenados no se permiten.

Puede calificar los nombres de rutina con el nombre de la base de datos. Esto puede usarse para re-

ferirse a una rutina que no esté en la base de datos actual. Por ejemplo, para invocar procedimientos

almacenados “p” o funciones “f” esto se asocia con la base de datos test, puede decir CALL

test.p() o test.f().

Cuando se borra una base de datos, todos los procedimientos almacenados asociados con ella tam-

bién se borran.

(En MySQL 5.0.0, los procedimientos almacenados son globales y no asociados con una base de datos. Here-

dan la base de datos por defecto del llamador. Si se ejecuta USE db_name desde la rutina, la base de datos

por defecto original se restaura a la salida de la rutina.)

MySQL soporta la extensión muy útil que permite el uso de comandos regulares SELECT (esto es, sin usar

cursores o variables locales) dentro de los procedimientos almacenados. El conjunto de resultados de estas

consultas se envía directamente al cliente. Comandos SELECT múltiples generan varios conjuntos de resul-

tados, así que el cliente debe usar una biblioteca cliente de MySQL que soporte conjuntos de resultados

múltiples. Esto significa que el cliente debe usar una biblioteca cliente de MySQL como mínimos desde 4.1.

3.1 CREATE PROCEDURE y CREATE FUNCTION

CREATE PROCEDURE sp_name ([parameter[,...]])[characteristic...] routine_body

CREATE FUNCTION sp_name ([parameter[,...]]) RETURNS type[characteristic...] routine_body

parameter:

[ IN | OUT | INOUT ] param_name type

type:

Any valid MySQL data type

characteristic:

LANGUAGE SQL| [NOT] DETERMINISTIC| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }| SQL SECURITY { DEFINER | INVOKER }| COMMENT 'string'

routine_body:

procedimientos almacenados o comandos SQL válidos

Estos comandos crean una rutina almacenada. Desde MySQL 5.0.3, para crear una rutina, es necesario tener

el permiso CREATE ROUTINE, y los permisos ALTER ROUTINE y EXECUTE se asignan automáticamente

a su creador. Si se permite logo binario necesita también los permisos.

Por defecto, la rutina se asocia con la base de datos actual. Para asociar la rutina explícitamente con una

base de datos, especifique el nombre como db_name.sp_name al crearlo.

Si el nombre de rutina es el mismo que el nombre de una función de SQL, necesita usar un espacio entre el

nombre y el siguiente paréntesis al definir la rutina, o hay un error de sintaxis. Esto también es cierto cuando

invoca la rutina posteriormente. La cláusula RETURNS puede especificarse sólo con FUNCTION, donde es

obligatorio. Se usa para indicar el tipo de retorno de la función, y el cuerpo de la función debe contener uncomando RETURN value.

Page 4: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 4/23

 

Tema 6. Programación de bases de datos Base de datos

4

La lista de parámetros entre paréntesis debe estar siempre presente. Si no hay parámetros, se debe usar una

lista de parámetros vacía. Cada parámetro es un parámetro IN por defecto. Para especificar otro tipo de

parámetro, use la palabra clave OUT o INOUT antes del nombre del parámetro. Especificando IN, OUT, o

INOUT sólo es válido para una PROCEDURE. El comando CREATE FUNCTION se usa en versiones anterio-

res de MySQL para soportar UDFs (User Defined Functions) (Funciones Definidas por el Usuario). Un UDF

puede tratarse como una función almacenada externa. Sin embargo, tenga en cuenta que los procedimien-

tos almacenados comparten su espacio de nombres con UDFs.Un marco para procedimientos almacenados externos se introducirá en el futuro. Esto permitirá escribir

procedimientos almacenados en lenguajes distintos a SQL. Uno de los primeros lenguajes a soportar será

PHP ya que el motor central de PHP es pequeño, con flujos seguros y puede empotrarse fácilmente. Como el

marco es público, se espera soportar muchos otros lenguajes.

Un procedimiento o función se considera “determinista” si siempre produce el mismo resultado para los

mismos parámetros de entrada, y “no determinista” en cualquier otro caso. Si no se da ni DETERMINISTIC 

ni NOT DETERMINISTIC por defecto es NOT DETERMINISTIC.

Para replicación, use la función NOW() (o su sinónimo) o RAND() no hace una rutina no determinista nece-

sariamente. Para NOW(), el log binario incluye el tiempo y hora y replica correctamente. RAND() también

replica correctamente mientras se invoque sólo una vez dentro de una rutina. Puede considerar el tiempo yhora de ejecución de la rutina y una semilla de número aleatorio como entradas implícitas que son idénticas

en el maestro y el esclavo.

Actualmente, la característica DETERMINISTIC se acepta, pero no la usa el optimizador. Sin embargo, si se

permite el logo binario, esta característica afecta si MySQL acepta definición de rutinas.

Varias características proporcionan información sobre la naturaleza de los datos usados por la rutina. 

CONTAINS SQL indica que la rutina no contiene comandos que leen o escriben datos. NO SQL indica que la

rutina no contiene comandos SQL. READS SQL DATA indica que la rutina contiene comandos que leen

datos, pero no comandos que escriben datos. MODIFIES SQL DATA indica que la rutina contiene coman-

dos que pueden escribir datos. CONTAINS SQL es el valor por defecto si no se dan explícitamente ninguna

de estas características.

La característica SQL SECURITY puede usarse para especificar si la rutina debe ser ejecutada usando los

permisos del usuario que crea la rutina o el usuario que la invoca. El valor por defecto es DEFINER. Esta

característica es nueva en SQL:2003. El creador o el invocador deben tener permisos para acceder a la base

de datos con la que la rutina está asociada. Desde MySQL 5.0.3, es necesario tener el permiso EXECUTE 

para ser capaz de ejecutar la rutina. El usuario que debe tener este permiso es el definidor o el invocador, en

función de cómo la característica SQL SECURITY.

MySQL almacena la variable de sistema sql_mode que está en efecto cuando se crea la rutina, y siempre

ejecuta la rutina con esta inicialización.

La cláusula COMMENT es una extensión de MySQL, y puede usarse para describir el procedimiento almace-nado. Esta información se muestra con los comandos SHOW CREATE PROCEDURE y SHOW CREATE

FUNCTION.

MySQL permite a las rutinas que contengan comandos DDL (tales como CREATE y DROP) y comandos de

transacción SQL (como COMMIT). Esto no lo requiere el estándar, y por lo tanto, es específico de la imple-

mentación.

Los procedimientos almacenados no pueden usar LOAD DATA INFILE.

Nota: Actualmente, los procedimientos almacenados creados con CREATE FUNCTION no pueden tener refe-

rencias a tablas. Esto puede incluir algunos comandos SET que pueden contener referencias a tablas, por

ejemplo SET a:= (SELECT MAX(id) FROM t), y por otra parte no pueden contener comandos

SELECT, por ejemplo SELECT 'Hello world!' INTO var1. Esta limitación se eliminará en breve.

Los comandos que devuelven un conjunto de resultados no pueden usarse desde una función almacenada.

Esto incluye comandos SELECT que no usan INTO para tratar valores de columnas en variables, comandos

Page 5: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 5/23

 

Tema 6. Programación de bases de datos Base de datos

5

SHOW y otros comandos como EXPLAIN. Para comandos que pueden determinarse al definir la función

para que retornen un conjunto de resultados, aparece un mensaje de error Not allowed to return

a result set from a function (ER_SP_NO_RETSET_IN_FUNC). Para comandos que puede

determinarse sólo en tiempo de ejecución si devuelven un conjunto de resultados, aparece el error PROCE-

DURE %s can't return a result set in the given context (ER_SP_BADSELECT).

El siguiente es un ejemplo de un procedimiento almacenado que use un parámetro OUT. El ejemplo usa el

cliente MySQL y el comando delimiter para cambiar el delimitador del comando de ; a // mientras se

define el procedimiento. Esto permite pasar el delimitador ; usado en el cuerpo del procedimiento a través

del servidor en lugar de ser interpretado por el mismo MySQL.

 

MySQL> delimiter //MySQL> CREATE PROCEDURE simpleproc (OUT param1 INT)-> BEGIN-> SELECT COUNT(*) INTO param1 FROM t;-> END-> //Query OK, 0 rows affected (0.00 sec)MySQL> delimiter ;MySQL> CALL simpleproc(@a);Query OK, 0 rows affected (0.00 sec)MySQL> SELECT @a;+----+| @a |+----+| 3 |+----+1 row in set (0.00 sec)

Al usar el comando delimiter, debe evitar el uso de la antibarra ('\') ya que es el carácter de escape de

MySQL.

El siguiente es un ejemplo de función que toma un parámetro, realiza una operación con una función SQL, y

devuelve el resultado:

MySQL> delimiter //MySQL> CREATE FUNCTION hello (s CHAR(20)) RETURNS CHAR(50)

-> RETURN CONCAT('Hello, ',s,'!');-> //

Query OK, 0 rows affected (0.00 sec)MySQL> delimiter ;MySQL> SELECT hello('world');+----------------+| hello('world') |+----------------+| Hello, world! |

+----------------+1 row in set (0.00 sec)

Si el comando RETURN en un procedimiento almacenado devuelve un valor con un tipo distinto al especifi-

cado en la cláusula RETURNS de la función, el valor de retorno se transforma al tipo apropiado. Por ejemplo,

si una función devuelve un valor ENUM o SET, pero el comando RETURN devuelve un entero, el valor de-

vuelto por la función es la cadena para el miembro de ENUM correspondiente de un conjunto de miembros

SET.

3.2 ALTER PROCEDURE y ALTER FUNCTION

ALTER {PROCEDURE | FUNCTION} sp_name [characteristic...]

characteristic:

{ CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }| SQL SECURITY { DEFINER | INVOKER }

Page 6: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 6/23

 

Tema 6. Programación de bases de datos Base de datos

6

| COMMENT 'string'

Este comando puede usarse para cambiar las características de un procedimiento o función almacenada.

Debe tener el permiso ALTER ROUTINE para la rutina desde MySQL 5.0.3. El permiso se otorga automáti-

camente al creador de la rutina. Si está activado el logo binario, necesitará el permiso SUPER.

Pueden especificarse varios cambios con ALTER PROCEDURE o ALTER FUNCTION.

3.3 DROP PROCEDURE y DROP FUNCTION

DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name

Este comando se usa para borrar un procedimiento o función almacenados. Esto es, la rutina especificada se

borra del servidor. Debe tener el permiso ALTER ROUTINE para las rutinas desde MySQL 5.0.3. Este per-

miso se otorga automáticamente al creador de la rutina.

La cláusula IF EXISTS es una extensión de MySQL. Evita que ocurra un error si la función o procedimiento

no existe. Se genera una advertencia que puede verse con SHOW WARNINGS.

3.4 SHOW CREATE PROCEDURE y SHOW CREATE FUNCTION

SHOW CREATE {PROCEDURE | FUNCTION} sp_name

Este comando es una extensión de MySQL. Similar a SHOW CREATE TABLE, devuelve la cadena exacta

que puede usarse para recrear la rutina nombrada.

 

MySQL> SHOW CREATE FUNCTION test.hello\G*************************** 1. row ***************************Function: hellosql_mode:

 

Create Function: CREATE FUNCTION `test`.`hello`(s CHAR(20)) RETURNS CHAR(50)RETURN CONCAT('Hello, ',s,'!')

3.5 SHOW PROCEDURE STATUS y SHOW FUNCTION STATUSSHOW {PROCEDURE | FUNCTION} STATUS [LIKE 'pattern']

Este comando es una extensión de MySQL. Devuelve características de rutinas, como el nombre de la base

de datos, nombre, tipo, creador y fechas de creación y modificación. Si no se especifica un patrón, le lista la

información para todos los procedimientos almacenados, en función del comando que use.

MySQL> SHOW FUNCTION STATUS LIKE 'hello'\G*************************** 1. row ***************************Db: testName: helloType: FUNCTIONDefiner: testuser@localhostModified: 2004-08-03 15:29:37Created: 2004-08-03 15:29:37Security_type: DEFINER

 

Comment:

También puede obtener información de rutinas almacenadas de la tabla ROUTINES en INFORMA-

TION_SCHEMA.

3.6 La sentencia CALL

CALL sp_name([parameter[,...]])

El comando CALL invoca un procedimiento definido previamente con CREATE PROCEDURE.

Page 7: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 7/23

 

Tema 6. Programación de bases de datos Base de datos

7

CALL puede pasar valores al llamador usando parámetros declarados como OUT o INOUT. También “de-

vuelve” el número de registros afectados, que con un programa cliente puede obtenerse a nivel SQL llaman-

do la función ROW_COUNT() y desde C llamando la función de la API C MySQL_affected_rows().

3.7 Sentencia compuesta BEGIN... END

[etiqueta_inicio:] BEGIN[lista_sentencias]

END [etiqueta_fin]

La sintaxis BEGIN... END se utiliza para escribir sentencias compuestas que pueden aparecer en el inter-

ior de procedimientos almacenados y triggers. Una sentencia compuesta puede contener múltiples senten-

cias, encerradas por las palabras BEGIN y END. lista_sentencias es una lista de una o más senten-

cias. Cada sentencia dentro de lista_sentencias debe terminar con un punto y como (;) delimitador

de sentencias. lista_sentencias es opcional, lo que significa que la sentencia compuesta vacía BEGIN

END es correcta.

El uso de múltiples sentencias requiere que el cliente pueda enviar cadenas de sentencias que contengan el

delimitador ;. Esto se gestiona en el cliente de línea de comandos MySQL con el comando delimiter.

Cambiar el delimitador de fin de sentencia “;” (por ejemplo con //) permite utilizar ; en el cuerpo de unarutina.

Un comando compuesto puede etiquetarse. No se puede poner end_label a no ser que también esté

presente begin_label, y si ambos están, deben ser iguales.

La cláusula opcional [NOT] ATOMIC no está soportada todavía. Esto significa que no hay un punto tran-

saccional al inicio del bloque de instrucciones y la cláusula BEGIN usada en este contexto no tiene efecto en

la transacción actual.

3.8 Sentencia DECLARE

El comando DECLARE se usa para definir varios iconos locales de una rutina: las variables locales, condicio-nes y handlers y cursores. Los comandos SIGNAL y RESIGNAL no se soportan en la actualidad

DECLARE puede usarse sólo dentro de comandos compuestos BEGIN... END y deben ser su inicio, antes

de cualquier otro comando.

Los cursores deben declararse antes de declarar los handlers, y las variables y condiciones deben declararse

antes de declarar los cursores o handlers.

3.9 Variables en procedimientos almacenados

Pude declarar y usar una variable dentro de una rutina.

3.9.1 Declarar variables locales con DECLAREDECLARE var_name[,...] type [DEFAULT value]

Este comando se usa para declarar variables locales. Para proporcionar un valor por defecto para la variable,

incluya una cláusula DEFAULT. El valor puede especificarse como expresión, no necesita ser una constante.

Si la cláusula DEFAULT no está presente, el valor inicial es NULL.

La visibilidad de una variable local es dentro del bloque BEGIN... END donde está declarado. Puede usar-

se en bloques anidados excepto aquéllos que declaren una variable con el mismo nombre.

3.9.2 Sentencia SET para variables

SET var_name = expr [, var_name = expr]...

El comando SET en procedimientos almacenados es una versión extendida del comando general SET. Las

variables referenciadas pueden ser las declaradas dentro de una rutina, o variables de servidor globales.

Page 8: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 8/23

 

Tema 6. Programación de bases de datos Base de datos

8

El comando SET en procedimientos almacenados se implementa como parte de la sintaxis SET pre-

existente. Esto permite una sintaxis extendida de SET a=x, b=y,... donde distintos tipos de variables

(variables declaradas local y globalmente y variables de sesión del servidor) pueden mezclarse. Esto permite

combinaciones de variables locales y algunas opciones que tienen sentido sólo para variables de sistema; en

tal caso, las opciones se reconocen pero se ignoran.

3.9.3 La sentencia SELECT... INTO

SELECT col_name[,...] INTO var_name[,...] table_expr

Esta sintaxis SELECT almacena columnas seleccionadas directamente en variables. Por lo tanto, sólo un

registro puede devolverse.

 

SELECT id,data INTO x,y FROM test.t1 LIMIT 1;

3.10 Conditions y Handlers

Ciertas condiciones pueden requerir un tratamiento específico. Estas condiciones pueden estar relacionadas

con errores, así como control de flujo general dentro de una rutina.

3.10.1 Condiciones DECLAREDECLARE condition_name CONDITION FOR condition_value

condition_value:

SQLSTATE [VALUE] sqlstate_value| MySQL_error_code

Este comando especifica condiciones que necesitan tratamiento específico. Asocia un nombre con una con-

dición de error específica. El nombre puede usarse subsecuentemente utilizando el comando DECLARE

HANDLER.

Además de valores SQLSTATE, los códigos de error MySQL se soportan.

3.10.2 DECLARE handlers

DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement

handler_type:

CONTINUE| EXIT| UNDO

condition_value:

SQLSTATE [VALUE] sqlstate_value| condition_name

| SQLWARNING| NOT FOUND| SQLEXCEPTION

| MySQL_error_code

Este comando especifica handlers que pueden tratar una o varias condiciones. Si una de estas condiciones

ocurre, el comando especificado se ejecuta.

Para un handler CONTINUE, continúa la rutina actual tras la ejecución del comando del handler. Para un

handler EXIT, termina la ejecución del comando compuesto BEGIN...END actual. El handler de tipo UN-

DO todavía no se soporta.

SQLWARNING es una abreviación para todos los códigos SQLSTATE que comienzan con 01.

NOT FOUND es una abreviación para todos los códigos SQLSTATE que comienzan con 02.

SQLEXCEPTION es una abreviación para todos los códigos SQLSTATE no tratados por SQLWAR-

NING o NOT FOUND.

Page 9: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 9/23

 

Tema 6. Programación de bases de datos Base de datos

9

Además de los valores SQLSTATE, los códigos de error MySQL se soportan.

Por ejemplo:

 

MySQL> CREATE TABLE test.t (s1 int,primary key (s1));Query OK, 0 rows affected (0.00 sec)MySQL> delimiter //MySQL> CREATE PROCEDURE handlerdemo ()

-> BEGIN-> DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;-> SET @x = 1;-> INSERT INTO test.t VALUES (1);-> SET @x = 2;-> INSERT INTO test.t VALUES (1);-> SET @x = 3;-> END;-> //Query OK, 0 rows affected (0.00 sec)MySQL> CALL handlerdemo()//Query OK, 0 rows affected (0.00 sec)MySQL> SELECT @x//

+------+| @x |+------+| 3 |+------+1 row in set (0.00 sec)

Tenga en cuenta que @x es 3, lo que muestra que MySQL se ha ejecutado al final del procedimiento. Si la

línea DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1; no está presente,

MySQL habría tomado la ruta por defecto (EXIT) tras el segundo INSERT fallido debido a la restricción

PRIMARY KEY, y SELECT @x habría devuelto 2.

3.11 Cursores

Se soportan cursores simples dentro de procedimientos y funciones almacenadas. La sintaxis es la de SQL

empotrado. Los cursores no son sensibles, son de sólo lectura, y no permiten scrolling. No sensible significa

que el servidor puede o no hacer una copia de su tabla de resultados.

Los cursores deben declararse antes de declarar los handlers, y las variables y condiciones deben declararse

antes de declarar cursores o handlers.

Por ejemplo:

CREATE PROCEDURE curdemo()BEGIN

DECLARE done INT DEFAULT 0;

DECLARE a CHAR(16);DECLARE b,c INT;DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;OPEN cur1;OPEN cur2;REPEAT

FETCH cur1 INTO a, b;FETCH cur2 INTO c;IF NOT done THEN

IF b < c THENINSERT INTO test.t3 VALUES (a,b);

ELSE INSERT INTO test.t3 VALUES (a,c);END IF;END IF;

UNTIL done END REPEAT; -- problemas con el último registro

Page 10: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 10/23

 

Tema 6. Programación de bases de datos Base de datos

10

 

CLOSE cur1;CLOSE cur2;

END

3.11.1 Declarar cursores

DECLARE cursor_name CURSOR FOR select_statement

Este comando declara un cursor. Pueden definirse varios cursores en una rutina, pero cada cursor en unbloque debe tener un nombre único.

El comando SELECT no puede tener una cláusula INTO.

3.11.2 Sentencia OPEN del cursor

OPEN cursor_name

Este comando abre un cursor declarado previamente.

3.11.3 Sentencia de cursor FETCH

FETCH cursor_name INTO var_name [, var_name]...

Este comando trata el siguiente registro (si existe) usando el cursor abierto que se especifique, y avanza elpuntero del cursor.

Si no existen más registros disponibles, ocurrirá una condición de Sin Datos con el valor SQLSTATE 02000.

Puede configurar un manejador (handler) para detectar esta condición (o para una condición NOT FOUND).

3.11.4 Sentencia de cursor CLOSE

CLOSE cursor_name

Este comando cierra un cursor abierto previamente.

Si no se cierra explícitamente, un cursor se cierra al final del comando compuesto en que se declara.

3.12 Constructores de control de flujo

Los constructores IF, CASE, LOOP, WHILE, ITERATE, y LEAVE están completamente implementados.

Estos constructores pueden contener un comando simple, o un bloque de comandos usando el comando

compuesto BEGIN... END. Los constructores pueden estar anidados.

Los bucles FOR no están soportados.

3.12.1 Sentencia IF

IF search_condition THEN statement_list[ELSEIF search_condition THEN statement_list]...

[ELSE statement_list]END IF 

IF implementa un constructor condicional básico. Si search_condition se evalúa a cierto, el comando

SQL correspondiente listado se ejecuta. Si no coincide ninguna search_condition se ejecuta el coman-

do listado en la cláusula ELSE. statement_list puede consistir en varios comandos.

Tenga en cuenta que también hay una función IF(), que difiere del comando IF descrito aquí.

3.12.2 La sentencia CASE

CASE case_valueWHEN when_value THEN statement_list

[WHEN when_value THEN statement_list]...[ELSE statement_list]END CASE

Page 11: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 11/23

 

Tema 6. Programación de bases de datos Base de datos

11

O:

CASEWHEN search_condition THEN statement_list[WHEN search_condition THEN statement_list]...[ELSE statement_list]

END CASE

El comando CASE para procedimientos almacenados implementa un constructor condicional complejo. Si

una search_condition se evalúa a cierto, el comando SQL correspondiente se ejecuta. Si no coincide

ninguna condición de búsqueda, el comando en la cláusula ELSE se ejecuta.

Nota: La sintaxis de un comando CASE mostrado aquí para uso dentro de procedimientos almacenados di-

fiere ligeramente de la expresión CASE SQL. El comando CASE no puede tener una cláusula ELSE NULL y

termina con END CASE en lugar de END.

3.12.3 Sentencia LOOP

[begin_label:] LOOPstatement_list

END LOOP [end_label]LOOP implementa un constructor de bucle simple que permite ejecución repetida de comandos particulares.

El comando dentro del bucle se repite hasta que acaba el bucle, usualmente con un comando LEAVE.

Un comando LOOP puede llevar etiquetas. De esta manera, end_label no puede darse hasta que esté

presente begin_label, y si ambos lo están, deben ser el mismo.

3.12.4 Sentencia LEAVE

LEAVE label

Este comando se usa para abandonar cualquier control de flujo etiquetado. Puede usarse con BEGIN...

END o bucles.

3.12.5 La sentencia ITERATE

ITERATE label

ITERATE sólo puede aparecer en comandos LOOP, REPEAT, y WHILE. ITERATE significa “vuelve a hacer

el bucle.” 

Por ejemplo:

 

CREATE PROCEDURE doiterate(p1 INT)BEGIN

label1: LOOPSET p1 = p1 + 1;

IF p1 < 10 THEN ITERATE label1; END IF;LEAVE label1;END LOOP label1;

SET @x = p1;END

3.12.6 Sentencia REPEAT

[begin_label:] REPEATstatement_list

UNTIL search_conditionEND REPEAT [end_label]

El comando/s dentro de un comando REPEAT se repite hasta que la condición search_condition es

cierta.

Un comando REPEAT puede etiquetarse. end_label no puede darse a no ser que begin_label esté

presente, y si lo están, deben ser el mismo.

Page 12: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 12/23

 

Tema 6. Programación de bases de datos Base de datos

12

Por ejemplo:

 

MySQL> delimiter //MySQL> CREATE PROCEDURE dorepeat(p1 INT)-> BEGIN-> SET @x = 0;-> REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT;-> END

-> //Query OK, 0 rows affected (0.00 sec)MySQL> CALL dorepeat(1000)//Query OK, 0 rows affected (0.00 sec)MySQL> SELECT @x//+------+| @x |+------+| 1001 |+------+1 row in set (0.00 sec)

3.12.7 Sentencia WHILE

[begin_label:] WHILE search_condition DOstatement_list

END WHILE [end_label]

El comado/s dentro de un comando WHILE se repite mientras la condición search_condition es cierta.

Un comando WHILE puede etiquetarse. end_label no puede darse a no ser que begin_label también

esté presente, y si lo están, deben ser el mismo.

Por ejemplo:

CREATE PROCEDURE dowhile()BEGIN

DECLARE v1 INT DEFAULT 5;WHILE v1 > 0 DO...

SET v1 = v1 - 1;END WHILE;END

4 Registro binario de procedimientos almacenados y dispara-

 

dores

Esta sección describe cómo MySQL trata procedimientos almacenados (procedimientos o funciones) con

respecto a logo binario. La sección también se aplica a disparadores.El log binario contiene información sobre comandos SQL que modifican contenidos de base de datos. Esta

información se almacena en la forma de “eventos” que describen las modificaciones.

El log binario tiene dos propósitos importantes:

•  La base de replicación es que el maestro envía los eventos contenidos en su log binario a sus escla-

vos, que ejecuta estos eventos para hacer los mismos cambios de datos que se hacen en el maestro.

•  Ciertas operaciones de recuperación de datos necesitan usar el log binario. Tras hacer una restaura-

ción de un fichero de copia de seguridad, los eventos en el log binario que se guardaron tras hacer la

copia de seguridad se re-ejecutan. Estos eventos actualizan la base de datos desde el punto de la co-

pia de seguridad.

El logo de procedimientos almacenados difiere antes y después de MySQL 5.0.6. Antes de MySQL 5.0.6, los

comandos que crean y usan procedimientos almacenados no se escriben en el log binario, pero los coman-

dos invocados desde procedimientos almacenados se logan. Suponga que ejecuta los siguientes comandos:

Page 13: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 13/23

 

Tema 6. Programación de bases de datos Base de datos

13

 

CREATE PROCEDURE mysp INSERT INTO t VALUES(1);CALL mysp;

Para este ejemplo, sólo el comando INSERT aparecerá en el log binario. Los comandos CREATE PROCE-

DURE y CALL no aparecerán. La ausencia de comandos relacionados con rutinas en el log binario significa

que procedimientos almacenados no se replican correctamente. También significa que para operaciones de

recuperación de datos, re-ejecutar eventos en el log binario no recupera procedimientos almacenados.

Para tratar estos temas de replicación y recuperación de datos, se cambió el logo de procedimientos alma-cenados en MySQL 5.0.6. Sin embargo, este cambio provoca nuevos temas, que se presentan en la siguiente

discusión.

A no ser que se diga lo contrario, estas notas asumen que no ha activado el logo binario arrancando el servi-

dor con la opción --log-bin. Si el log binario no se activa, la replicación no es posible, ni está disponible el

log binario para replicación de datos.

Las características de logo binario para comandos de procedimientos almacenados se describen en la si-

guiente lista. Algunos de los iconos indican problemas que debería conocer, pero en algunos casos, hay ini-

cializaciones de servidor que puede modificar o soluciones que puede usar.

•  Los comandos CREATE PROCEDURE, CREATE FUNCTION, ALTER PROCEDURE, y ALTER

FUNCTION se escriben en el log binario, como lo son CALL, DROP PROCEDURE y DROP FUNC-

TION.

Sin embargo, hay implicaciones de seguridad para replicación: para crear una rutina, un usuario de-

be tener el permiso CREATE ROUTINE, pero un usuario que tenga este permiso puede escribir una

rutina para realizar cualquier acción en un servidor esclavo ya que el flujo SQL en el esclavo corre

con todos los permisos. Por ejemplo, si el maestro y el esclavo tienen valores de ID del servidor de 1

y 2 respectivamente, un usuario en el maestro puede crear e invocar procedimientos como sigue:

MySQL> delimiter //MySQL> CREATE PROCEDURE mysp ()-> BEGIN

-> IF @@server_id=2 THEN DROP DATABASE accounting; END IF;

 

-> END;-> //MySQL> delimiter ;MySQL> CALL mysp();

Los comandos CREATE PROCEDURE y CALL se escriben en el log binario, así que los ejecutará el

esclavo. Ya que el flujo SQL del esclavo tiene todos los permisos, borra la base de datos accoun-

ting.

Para evitar este peligro en servidores con logo binario activado, MySQL 5.0.6 introduce el requeri-

miento que los creadores de procedimientos almacenados y funciones deben tener el permiso SU-

PER, además del permiso CREATE ROUTINE requerido. Similarmente, para usar ALTER PROCE-

DURE o ALTER FUNCTION, debe tener el permiso SUPER además del permiso ALTER ROUTI-

NE. Sin el permiso SUPER ocurre un error:

ERROR 1419 (HY000): You do not have the SUPER privilege andbinary logging is enabled (you *might* want to use the less safelog_bin_trust_routine_creators variable)

Puede no querer forzar el requerimiento en los creadores de rutinas que deben tener el permiso

SUPER. Por ejemplo, todos los usuarios con el permiso CREATE ROUTINE en su sistema pueden

ser desarrolladores de aplicaciones con experiencia. Para desactivar el requerimiento de SUPER,

cambie la variable de sistema global log_bin_trust_routine_creators a 1. Por defecto,

esta variable vale 0, pero puede cambiarla así:

MySQL> SET GLOBAL log_bin_trust_routine_creators = 1;

Page 14: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 14/23

 

Tema 6. Programación de bases de datos Base de datos

14

Puede activar esta variable usando la opción --log-bin-trust-routine-creators al

arrancar el servidor.

Si el logo binario no está activado, log_bin_trust_routine_creators no se aplica y no se

necesita el permiso SUPER para creación de rutinas.

•  Una rutina no-determinista que realiza actualizaciones no es repetible, que puede tener dos efectos

no deseables:o  El esclavo será distinto al maestro.

o  Los datos restaurados serán distintos a los originales.

Para tratar estos problemas, MySQL fuerza los siguientes requerimientos: En un servidor maestro, la

creación y alteración de una rutina se rehúsa a no ser que la rutina se declare como determinista o

que no modifique datos. Esto significa que cuando crea una rutina, debe declarar que es determinis-

ta o que no cambia datos. Dos conjuntos de características de rutinas se aplica aquí:

o  DETERMINISTIC y NOT DETERMINISTIC indican si una rutina siempre produce el

mismo resultado para entradas dadas. Por defecto es NOT DETERMINISTIC si no se da

ninguna característica, así que debe especificar DETERMINISTIC explícitamente para de-

clarar que la rutina es determinista.El uso de las funciones NOW() (o sus sinónimos) o RAND() no hacen una rutina no-

determinista necesariamente. Para NOW(), el log binario incluye la fecha y hora y replica co-

rrectamente. RAND() también replica correctamente mientras se invoque sólo una vez de-

ntro de una rutina. Puede considerar la fecha y hora de ejecución de la rutina y la semilla de

números aleatorios como entradas implícitas que son idénticas en el maestro y el esclavo.

o  CONTAINS SQL, NO SQL, READS SQL DATA y MODIFIES SQL proporciona informa-

ción acerca de si la rutina lee o escribe datos. Tanto NO SQL o READS SQL DATA indican

que una rutina no cambia datos, pero debe especificar uno de estos explícitamente ya que

por defecto es CONTAINS SQL si ninguna de estas características se da.

Por defecto, para que un comando CREATE PROCEDURE o CREATE FUNCTION sea aceptado,DETERMINISTIC o NO SQL y READS SQL DATA deben especificarse explícitamente. De otro

modo ocurre un error:

 

ERROR 1418 (HY000): This routine has none of DETERMINISTIC, NO SQL,or READS SQL DATA in its declaration and binary logging is enabled(you *might* want to use the less safe log_bin_trust_routine_creators

 

variable)

Si asigna a log_bin_trust_routine_creators 1, el requerimiento que la rutina sea de-

terminista o que no modifique datos se elimina.

Tenga en cuenta que la naturaleza de una rutina se basa en la “honestidad” del creador: MySQL no

comprueba que una rutina declarada DETERMINISTIC no contenga comandos que produzcanproductos no deterministas.

•  Un comando CALL se escribe en el log binario si la rutina no devuelve error, pero no en otro caso.

Cuando una rutina que modifica datos falla, obtiene esta advertencia:

ERROR 1417 (HY000): A routine failed and has neither NO SQL norREADS SQL DATA in its declaration and binary logging is enabled; ifnon-transactional tables were updated, the binary log will miss theirchanges

Este logo del comportamiento tiene un potencial para causar problemas. Si una rutina modifica par-

cialmente una tabla no transaccional (tal como una tabla MyISAM ) y devuelve un error, el log bina-

rio no refleja estos cambios. Para protegerse de esto, debe usar tablas transaccionales en la rutina ymodificar las tablas dentro de transacciones.

Page 15: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 15/23

 

Tema 6. Programación de bases de datos Base de datos

15

Si usa la palabra clave IGNORE con INSERT, DELETE, o UPDATE para ignorar errores dentro de

una rutina, una actualización parcial puede ocurrir sin producir error. Tales comandos se logan y se

replican normalmente.

•  Si una función almacenada se invoca dentro de un comando tal como SELECT que no modifica da-

tos, la ejecución de la función no se escribe en el log binario, incluso si la función misma modifica da-

tos. Este comportamiento de logo tiene potencial para causar problemas. Suponga que una función

myfunc() se define así:

 

CREATE FUNCTION myfunc () RETURNS INTBEGIN

INSERT INTO t (i) VALUES(1);RETURN 0;

END;

Dada esta definición, el comando siguiente modifica la tabla t porque myfunc() modifica t, pero el

comando no se escribe en el log binario porque es un SELECT:

SELECT myfunc();

Una solución de este problema es invocar funciones que actualizan dentro de comandos que hacen

actualizaciones. Tenga en cuenta que aunque el comando DO a veces se ejecuta como efecto colate-

ral de evaluar una expresión, DO no es una solución aquí porque no está escrito en el log binario.

•  Los comandos ejecutados dentro de una rutina no se escriben en el log binario. Suponga que ejecuta

los siguientes comandos:

CREATE PROCEDURE mysp INSERT INTO t VALUES(1);CALL mysp;

Para este ejemplo, los comandos CREATE PROCEDURE y CALL aparecerán en el log binario. El

comando INSERT no aparecerá. Esto arregla el problema que ocurre antes de MySQL 5.0.6 en que

los comandos CREATE PROCEDURE y CALL no se logaron e INSERT se logó.

En servidores esclavos, la siguiente limitación se aplica cuando se determina qué eventos del maes-

tro se replican: reglas --replicate-*-table no se aplican a comandos CALL o a comandos

dentro de rutinas: Las reglas en estos casos siempre devuelven “replica!” 

Los disparadores son similares a los procedimientos almacenados, así que las notas precedentes también se

aplican a disparadores con las siguientes excepciones: CREATE TRIGGER no tiene una característica DE-

TERMINISTIC opcional, así que los disparadores se asumen como deterministas. Sin embargo, esta hipó-

tesis puede ser inválida en algunos casos. Por ejemplo, la función UUID() no es determinista (y no replica).

Debe ser cuidadoso acerca de usar tales funciones y disparadores.

Los disparadores actualmente no actualizan tablas, pero lo harán en el futuro. Por esta razón, los mensajes

de error similares a los de los procedimientos almacenados ocurren con CREATE TRIGGER si no tiene el

permiso SUPER y log_bin_trust_routine_creators es 0.

Los temas tratados en esta sección son resultado del hecho que el logo binario se hace a nivel de comandos

SQL. MySQL 5.1 introducirá logo binario a nivel de registro, lo que ocurre en un nivel más granular que espe-

cifica qué cambios hacer a registros individuales como resultado de ejecutar comandos SQL.

5 Disparadores o triggers

A partir de MySQL 5.0.2 se incorporó el soporte básico para disparadores (triggers). Un disparador es un

objeto con nombre dentro de una base de datos el cual se asocia con una tabla y se activa cuando ocurre en

ésta un evento en particular. Por ejemplo, las siguientes sentencias crean una tabla y un disparador para

sentencias INSERT dentro de la tabla. El disparador suma los valores insertados en una de las columnas de latabla:

MySQL> CREATE TABLE account (acct_num INT, amount DECIMAL(10,2));

Page 16: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 16/23

 

Tema 6. Programación de bases de datos Base de datos

16

 

MySQL> CREATE TRIGGER ins_sum BEFORE INSERT ON account-> FOR EACH ROW SET @sum = @sum + NEW.amount;

Este capítulo describe la sintaxis para crear y eliminar disparadores, y muestra algunos ejemplos de cómo

utilizarlos.

5.1 Sintaxis de CREATE TRIGGER

CREATE TRIGGER nombre_disp momento_disp evento_dispON nombre_tabla FOR EACH ROW sentencia_disp

Un disparador es un objeto con nombre en una base de datos que se asocia con una tabla, y se activa cuando

ocurre un evento en particular para esa tabla.

El disparador queda asociado a la tabla nombre_tabla. Esta debe ser una tabla permanente, no puede ser

una tabla TEMPORARY ni una vista.

momento_disp es el momento en que el disparador entra en acción. Puede ser BEFORE (antes) o AFTER 

(despues), para indicar que el disparador se ejecute antes o después que la sentencia que lo activa.

evento_disp indica la clase de sentencia que activa al disparador. Puede ser INSERT, UPDATE, o DE-

LETE. Por ejemplo, un disparador BEFORE para sentencias INSERT podría utilizarse para validar los valo-

res a insertar.

No puede haber dos disparadores en una misma tabla que correspondan al mismo momento y sentencia.

Por ejemplo, no se pueden tener dos disparadores BEFORE UPDATE. Pero sí es posible tener los dispara-

dores BEFORE UPDATE y BEFORE INSERT o BEFORE UPDATE y AFTER UPDATE.

sentencia_disp es la sentencia que se ejecuta cuando se activa el disparador. Si se desean ejecutar

múltiples sentencias, deben colocarse entre BEGIN... END, el constructor de sentencias compuestas.

Esto además posibilita emplear las mismas sentencias permitidas en rutinas almacenadas.

Note: Antes de MySQL 5.0.10, los disparadores no podían contener referencias directas a tablas por su nom-

bre. A partir de MySQL 5.0.10, se pueden escribir disparadores como el llamado testref, que se muestraen este ejemplo:

CREATE TABLE test1(a1 INT);CREATE TABLE test2(a2 INT);CREATE TABLE test3(a3 INT NOT NULL AUTO_INCREMENT PRIMARY KEY);

 

CREATE TABLE test4(a4 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,

 

b4 INT DEFAULT 0);DELIMITER |CREATE TRIGGER testref BEFORE INSERT ON test1FOR EACH ROW BEGIN

INSERT INTO test2 SET a2 = NEW.a1;DELETE FROM test3 WHERE a3 = NEW.a1;UPDATE test4 SET b4 = b4 + 1 WHERE a4 = NEW.a1;END|DELIMITER ;INSERT INTO test3 (a3) VALUES(NULL), (NULL), (NULL), (NULL), (NULL),(NULL), (NULL), (NULL), (NULL), (NULL);INSERT INTO test4 (a4) VALUES(0), (0), (0), (0), (0), (0), (0), (0), (0), (0);Si en la tabla test1 se insertan los siguientes valores:MySQL> INSERT INTO test1 VALUES

-> (1), (3), (1), (7), (1), (8), (4), (4);Query OK, 8 rows affected (0.01 sec)Records: 8 Duplicates: 0 Warnings: 0Entonces los datos en las 4 tablas quedarán así:

Page 17: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 17/23

 

Tema 6. Programación de bases de datos Base de datos

17

 

MySQL> SELECT * FROM test1;+------+| a1 |+------+| 1 || 3 || 1 |

| 7 || 1 || 8 || 4 || 4 |+------+8 rows in set (0.00 sec)MySQL> SELECT * FROM test2;+------+| a2 |+------+| 1 || 3 || 1 || 7 || 1 || 8 || 4 || 4 |+------+8 rows in set (0.00 sec)MySQL> SELECT * FROM test3;+----+| a3 |+----+| 2 || 5 || 6 || 9 || 10 |+----+5 rows in set (0.00 sec)MySQL> SELECT * FROM test4;+----+------+| a4 | b4 |+----+------+| 1 | 3 || 2 | 0 || 3 | 1 || 4 | 2 || 5 | 0 || 6 | 0 || 7 | 1 || 8 | 1 || 9 | 0 || 10 | 0 |+----+------+10 rows in set (0.00 sec)

Las columnas de la tabla asociada con el disparador pueden referenciarse empleando los alias OLD y NEW.

OLD.nombre_col hace referencia a una columna de una fila existente, antes de ser actualizada o borrada.

NEW.nombre_col hace referencia a una columna en una nueva fila a punto de ser insertada, o en una fila

existente luego de que fue actualizada.El uso de SET NEW.nombre_col = valor necesita que se tenga el privilegio UPDATE sobre la colum-

na. El uso de SET nombre_var = NEW.nombre_col necesita el privilegio SELECT sobre la columna.

Page 18: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 18/23

 

Tema 6. Programación de bases de datos Base de datos

18

Nota: Actualmente, los disparadores no son activados por acciones llevadas a cabo en cascada por las res-

tricciones de claves extranjeras.

Esta limitación se subsanará tan pronto como sea posible.

La sentencia CREATE TRIGGER necesita el privilegio SUPER. Esto se agregó en MySQL 5.0.2.

5.2 Sintaxis de DROP TRIGGERDROP TRIGGER [nombre_esquema.]nombre_disp

Elimina un disparador. El nombre de esquema es opcional. Si el esquema se omite, el disparador se elimina

en el esquema actual.

Anteriormente a la versión 5.0.10 de MySQL, se requería el nombre de tabla en lugar del nombre de esque-

ma, nom_tabla.nom_disp.

Nota: cuando se actualice desde una versión anterior de MySQL 5 a MySQL 5.0.10 o superior, se deben eli-

minar todos los disparadores antes de actualizar y volver a crearlos después, o DROP TRIGGER no funcio-

nará luego de la actualización.

La sentencia DROP TRIGGER necesita que se posea el privilegio SUPER y se introdujo en MySQL 5.0.2.

5.3 Utilización de disparadores

El soporte para disparadores se incluyó a partir de MySQL 5.0.2. Actualmente, el soporte para disparadores

es básico, por lo tanto hay ciertas limitaciones en lo que puede hacerse con ellos. Esta sección trata sobre el

uso de los disparadores y las limitaciones vigentes.

Un disparador es un objeto de base de datos con nombre que se asocia a una tabla, y se activa cuando ocu-

rre un evento en particular para la tabla. Algunos usos para los disparadores es verificar valores a ser inser-

tados o llevar a cabo cálculos sobre valores involucrados en una actualización.

Un disparador se asocia con una tabla y se define para que se active al ocurrir una sentenciaINSERT

,DE-LETE o UPDATE sobre dicha tabla. Puede también establecerse que se active antes o después de la senten-

cia en cuestión. Por ejemplo, se puede tener un disparador que se active antes de que un registro sea borra-

do, o después de que sea actualizado.

Para crear o eliminar un disparador, se emplean las sentencias CREATE TRIGGER y DROP TRIGGER.

Este es un ejemplo sencillo que asocia un disparador con una tabla para cuando reciba sentencias INSERT.

Actúa como un acumulador que suma los valores insertados en una de las columnas de la tabla.

La siguiente sentencia crea la tabla y un disparador asociado a ella:

 

MySQL> CREATE TABLE account (acct_num INT, amount DECIMAL(10,2));

 

MySQL> CREATE TRIGGER ins_sum BEFORE INSERT ON account

 

-> FOR EACH ROW SET @sum = @sum + NEW.amount;

La sentencia CREATE TRIGGER crea un disparador llamado ins_sum que se asocia con la tabla ac-

count. También se incluyen cláusulas que especifican el momento de activación, el evento activador, y qué

hacer luego de la activación:

• La palabra clave BEFORE indica el momento de acción del disparador. En este caso, el disparador debería

activarse antes de que cada registro se inserte en la tabla. La otra palabra clave posible aquí es AFTER.

• La palabra clave INSERT indica el evento que activará al disparador. En el ejemplo, la sentencia INSERT 

causará la activación. También pueden crearse disparadores para sentencias DELETE y UPDATE.

• La sentencia siguiente, FOR EACH ROW, define lo que se ejecutará cada vez que el disparador se active,

lo cual ocurre una vez por cada fila afectada por la sentencia activadora. En el ejemplo, la sentencia activadaes un sencillo SET que acumula los valores insertados en la columna amount. La sentencia se refiere a la

Page 19: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 19/23

 

Tema 6. Programación de bases de datos Base de datos

19

columna como NEW.amount, lo que significa “el valor de la columna amount que será insertado en el

nuevo registro.” 

Para utilizar el disparador, se debe establecer el valor de la variable acumulador a cero, ejecutar una senten-

cia INSERT, y ver qué valor presenta luego la variable.

 

MySQL> SET @sum = 0;MySQL> INSERT INTO account VALUES(137,14.98),(141,1937.50),(97,-100.00);MySQL> SELECT @sum AS 'Total amount inserted';+-----------------------+| Total amount inserted |+-----------------------+| 1852.48 |+-----------------------+

En este caso, el valor de @sum luego de haber ejecutado la sentencia INSERT es 14.98 + 1937.50 -

100, o 1852.48.

Para eliminar el disparador, se emplea una sentencia DROP TRIGGER. El nombre del disparador debe incluir

el nombre de la tabla:

MySQL> DROP TRIGGER account.ins_sum;

Debido a que un disparador está asociado con una tabla en particular, no se pueden tener múltiples dispara-

dores con el mismo nombre dentro de una tabla. También se debería tener en cuenta que el espacio de

nombres de los disparadores puede cambiar en el futuro de un nivel de tabla a un nivel de base de datos, es

decir, los nombres de disparadores ya no sólo deberían ser únicos para cada tabla sino para toda la base de

datos. Para una mejor compatibilidad con desarrollos futuros, se debe intentar emplear nombres de dispa-

radores que no se repitan dentro de la base de datos.

Adicionalmente al requisito de nombres únicos de disparador en cada tabla, hay otras limitaciones en los

tipos de disparadores que pueden crearse. En particular, no se pueden tener dos disparadores para una

misma tabla que sean activados en el mismo momento y por el mismo evento. Por ejemplo, no se pueden

definir dos BEFORE INSERT o dos AFTER UPDATE en una misma tabla. Es improbable que esta sea unagran limitación, porque es posible definir un disparador que ejecute múltiples sentencias empleando el cons-

tructor de sentencias compuestas BEGIN... END luego de FOR EACH ROW.

También hay limitaciones sobre lo que puede aparecer dentro de la sentencia que el disparador ejecutará al

activarse:

•  El disparador no puede referirse a tablas directamente por su nombre, incluyendo la misma tabla a

la que está asociado. Sin embargo, se pueden emplear las palabras clave OLD y NEW. OLD se refiere

a un registro existente que va a borrarse o que va a actualizarse antes de que esto ocurra. NEW se re-

fiere a un registro nuevo que se insertará o a un registro modificado luego de que ocurre la modifi-

cación.

•  El disparador no puede invocar procedimientos almacenados utilizando la sentencia CALL. (Estosignifica, por ejemplo, que no se puede utilizar un procedimiento almacenado para eludir la prohibi-

ción de referirse a tablas por su nombre).

•  El disparador no puede utilizar sentencias que inicien o finalicen una transacción, tal como START

TRANSACTION, COMMIT o ROLLBACK.

Las palabras clave OLD y NEW permiten acceder a columnas en los registros afectados por un disparador.

OLD y NEW no son sensibles a mayúsculas. En un disparador para INSERT, solamente puede utilizarse

NEW.nom_col; ya que no hay una versión anterior del registro. En un disparador para DELETE sólo pue-

de emplearse OLD.nom_col, porque no hay un nuevo registro. En un disparador para UPDATE se puede

emplear OLD.nom_col para referirse a las columnas de un registro antes de que sea actualizado y

NEW.nom_col para referirse a las columnas del registro luego de actualizarlo.

Una columna precedida por OLD es de sólo lectura. Es posible hacer referencia a ella pero no modificarla.

Una columna precedida por NEW puede ser referenciada si se tiene el privilegio SELECT sobre ella. En un

Page 20: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 20/23

 

Tema 6. Programación de bases de datos Base de datos

20

disparador BEFORE, también es posible cambiar su valor con SET NEW.nombre_col = valor si se

tiene el privilegio de UPDATE sobre ella. Esto significa que un disparador puede usarse para modificar los

valores antes que se inserten en un nuevo registro o se empleen para actualizar uno existente.

En un disparador BEFORE, el valor de NEW para una columna AUTO_INCREMENT es 0, no el número se-

cuencial que se generará en forma automática cuando el registro sea realmente insertado.

OLD y NEW son extensiones de MySQL para los disparadores.Empleando el constructor BEGIN... END, se puede definir un disparador que ejecute sentencias múlti-

ples. Dentro del bloque BEGIN, también pueden utilizarse otras sintaxis permitidas en rutinas almacenadas,

tales como condicionales y bucles. Como sucede con las rutinas almacenadas, cuando se crea un disparador

que ejecuta sentencias múltiples, se hace necesario redefinir el delimitador de sentencias si se ingresará el

disparador a través del programa MySQL, de forma que se pueda utilizar el carácter ';' dentro de la defini-

ción del disparador. El siguiente ejemplo ilustra estos aspectos. En él se crea un disparador para UPDATE,

que verifica los valores utilizados para actualizar cada columna, y modifica el valor para que se encuentre en

un rango de 0 a 100. Esto debe hacerse en un disparador BEFORE porque los valores deben verificarse antes

de emplearse para actualizar el registro:

 

MySQL> delimiter //MySQL> CREATE TRIGGER upd_check BEFORE UPDATE ON account

 

-> FOR EACH ROW-> BEGIN-> IF NEW.amount < 0 THEN-> SET NEW.amount = 0;-> ELSEIF NEW.amount > 100 THEN-> SET NEW.amount = 100;-> END IF;-> END;//MySQL> delimiter ;

Podría parecer más fácil definir una rutina almacenada e invocarla desde el disparador utilizando una simple

sentencia CALL. Esto sería ventajoso también si se deseara invocar la misma rutina desde distintos dispara-dores. Sin embargo, una limitación de los disparadores es que no pueden utilizar CALL. Se debe escribir la

sentencia compuesta en cada CREATE TRIGGER donde se la desee emplear.

MySQL gestiona los errores ocurridos durante la ejecución de disparadores de esta manera:

•  Si lo que falla es un disparador BEFORE, no se ejecuta la operación en el correspondiente registro.

•  Un disparador AFTER se ejecuta solamente si el disparador BEFORE (de existir) y la operación se

ejecutaron exitosamente.

•  Un error durante la ejecución de un disparador BEFORE o AFTER deriva en la falla de toda la sen-

tencia que provocó la invocación del disparador.

•  En tablas transaccionales, la falla de un disparador (y por lo tanto de toda la sentencia) debería cau-

sar la cancelación (rollback) de todos los cambios realizados por esa sentencia. En tablas no tran-saccionales, cualquier cambio realizado antes del error no se ve afectado.

Page 21: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 21/23

 

Tema 6. Programación de bases de datos Base de datos

21

 

6 Ejercicios

Dada el siguiente diagrama entidad/relación:

Dada la siguiente especificación de datos:

Tabla: CLIENTE

Atributo Tipo Restricción

codigo Entero sin signo Clave primaria

nombre Cadena de caracteres Máximo 100 caracteres

direccion Cadena de caracteres Máximo 100 caracteres

vecesMes Entero enano sin signo

horasVez Entero enano sin signo

telefono Cadena de caracteres 9 caracteres

fechaAlta Fecha

fechaBaja Fecha > fechaAlta

Tabla: EMPLEADO

Atributo Tipo Restricción

codigo Entero sin signo Clave primaria

nombre Cadena de caracteres Máximo 100 caracteres

eurosHora Decimal de 5 dígitos 2 para valores decimales

fechaAlta Fecha

fechaBaja Fecha > fechaAlta

fechaNacimiento FechaTabla: TRABAJO

Atributo Tipo Restricción

codigoCliente Entero sin signo

Clave primariacodigoEmpleado Entero sin signo

Fecha Fecha

numeroHoras Entero enano sin signo

A)  Crea la base de datos limpiaPlus.

B)  Crea las tablas según las especificaciones oportunas.

C)  Inserta los siguientes valores en la tabla CLIENTE:

(1, "CENTRIFUGADORA ALEMANA S.L.", "C/ LOS JAZMINES, NAVE 5 - 23009 (JAEN)",12, 3, "953280992", '2002-02-23', NULL),

(2, "CONCESIONARIO FORD JAEN", "C/ LAS ROSAS, NAVE 3 - 23009 (JAEN)", 20, 2,"953089912", '2005-03-30', NULL),

Page 22: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 22/23

 

Tema 6. Programación de bases de datos Base de datos

22

(3, "AM SYSTEM", "CTRA. DE CORDOBA, 23 - 23007 (JAEN)", 8, 1, "953889811",'2005-05-30', '2005-12-15'),

(4, "LUIS PIÑA S.L.", "C/ CORDOBA - NAVE 1, POL.IND.DE ANDUJAR (JAEN)", 24, 4,"645127855", '2006-01-01', NULL),

(5, "AISLAMIENTOS FEDERICO", "C/ SOL, 4 - 3º D, TORREDELCAMPO (JAEN)", 12, 1,"662478512", '2006-02-12', '2008-06-22');

D)  Inserta los siguientes valores en la tabla EMPLEADO:

(1, "EUGENIO MARTINEZ DE ORUJO", 10.50, '2001-09-01', NULL, '1976-11-21'),(2, "LUCRECIA MERKEL GERMAIN", 9.00, '2002-12-21', NULL, '1985-02-05'),(3, "BLAS PATON SAN EPIFANIO", 15.25, '2005-01-03', NULL, '1978-05-10'),(4, "SUSANA BLANCO DE LUZ", 16.00, '2000-03-02', NULL, '1970-09-27');E)  Inserta los siguientes valores en la tabla TRABJAO:

(1, 1, '2005-03-05', 2),(1, 1, '2005-03-06', 3),(1, 1, '2005-03-08', 5),(1, 1, '2005-03-10', 1),(1, 1, '2005-03-15', 3),(1, 1, '2005-03-17', 4),(1, 1, '2005-03-18', 3),

(1, 1, '2005-03-20', 4),(1, 1, '2005-03-21', 4),(1, 1, '2005-03-23', 3),(1, 1, '2005-03-25', 3),(1, 1, '2005-03-26', 4),(1, 1, '2005-03-29', 4),(1, 1, '2005-03-30', 3),(2, 2, '2005-03-30', 3),(2, 3, '2005-03-31', 5),(3, 1, '2005-03-12', 1),(3, 3, '2005-03-15', 1),(3, 3, '2005-03-20', 2),

(3, 3, '2005-03-23', 1),(3, 3, '2005-03-29', 1),(4, 1, '2005-03-01', 4),(4, 1, '2005-03-02', 4),(4, 2, '2005-03-03', 5),(4, 3, '2005-03-04', 4),(4, 1, '2005-03-05', 5),(4, 2, '2005-03-06', 4),(4, 2, '2005-03-08', 4),(4, 3, '2005-03-09', 6),(4, 2, '2005-03-10', 4),(4, 1, '2005-03-11', 2),(4, 2, '2005-03-12', 4),

(4, 4, '2005-03-13', 3),(4, 3, '2005-03-15', 4),(4, 3, '2005-03-16', 4),(4, 2, '2005-03-17', 4),(4, 1, '2005-03-18', 5),(4, 4, '2005-03-19', 4),(4, 4, '2005-03-20', 7),(4, 3, '2005-03-21', 4),(4, 2, '2005-03-23', 5),(4, 2, '2005-03-24', 4),(4, 3, '2005-03-25', 4),(4, 2, '2005-03-26', 3),(4, 4, '2005-03-27', 4),

(4, 2, '2005-03-28', 6),(4, 3, '2005-03-30', 4),(4, 2, '2005-03-31', 4),(5, 4, '2005-03-01', 1),

Page 23: A Pun Test Em a 6

5/17/2018 A Pun Test Em a 6 - slidepdf.com

http://slidepdf.com/reader/full/a-pun-test-em-a-6 23/23

 

Tema 6. Programación de bases de datos Base de datos

23

(5, 2, '2005-03-03', 2),(5, 4, '2005-03-05', 1),(5, 1, '2005-03-08', 2),(5, 4, '2005-03-10', 1),(5, 4, '2005-03-12', 1),(5, 4, '2005-03-15', 1),(5, 2, '2005-03-17', 1),

(5, 2, '2005-03-19', 3),(5, 1, '2005-03-22', 1),(5, 3, '2005-03-24', 1),(5, 2, '2005-03-26', 2);F)  Crea función esPrimo que reciba como parámetro un número entero y devuelva TRUE si es primo

y, FALSE, si no lo es.

G)  Crea el procedimiento nPrimos, que, pasando como parámetro un entero positivo, realice las si-

guientes operaciones:

a.  Crear la tabla primos con los siguientes datos:

i.  numero. Número entero secuencial que indica el orden de primos que se ha encon-

trado.

ii.  primo. Número primo encontrado.

iii.  iteraciones. Número de iteraciones (saltos) que se han dado desde que se en-

contró el primo anterior.

Así, por ejemplo, para una llamada nPrimos(5), el resultado será:

numero primo iteraciones

1 2 0

2 3 1

3 5 2

4 7 2

5 11 4

b.  inserta en la tabla los N primeros número primos. Se aconseja utilizar la función esPrimo 

realizada en el ejercicio anterior.

c.  Muestra los resultados por pantalla.

d.  Elimina la tabla temporal primos.

H)  Crea la función calculaHoras que, a partir del código de un cliente y un mes, devuelva el número

de horas que se han trabajado para un cliente durante ese mes.

I)  Crea la función calculaEuros que, a partir del código de un cliente y un mes, devuelva la canti-

dad de dinero que ha pagado cada cliente en ese mes.J)  Crea la función trabajoMas que, a partir del código de un cliente y un mes, devuelva TRUE si se

trabaja más que para las horas que tiene contratado y que devuelva FALSE en otro caso.

K)  Crea el procedimiento necesitaMas que realice las siguientes acciones:

a.  Cree la tabla temporal