Procedimientos Almacenados y Funciones en MySQL
Procedimientos Almacenados y Funciones en MySQL
Procedimientos Almacenados y Funciones en MySQL
Una de las grandes novedades de la versin 5 de MySQL es sin dudas la inclusin de soporte para procesos almacenados. A continuacin veremos los fundamentos tericos y este tema ms algunos ejemplos bsicos. Si ya usamos bases de datos como Oracle, Interbase / Firebird, PostgreSQL, seguro escuchamos hablar de procedimientos almacenados. Sin embargo, en MySQL esto es toda una novedad y un paso enorme para que esta base de datos se convierta en un verdadero sistema gestor de bases de datos. Ahora bien, qu son en realidad los procedimientos almacenados? Luego de sumergirnos en este tema veremos que el nombre es plenamente identificatorio y casi explica lo que es un procedimiento almacenado. Los procedimientos almacenados son un conjunto de instrucciones SQL ms una serie de estructuras de control que nos permiten dotar de cierta lgica al procedimiento. Estos procedimientos estn guardados en el servidor y pueden ser accedidos a travs de llamadas, como veremos ms adelante. Para crear un procedimiento, MySQL nos ofrece la directiva CREATE PROCEDURE. Al crearlo ste es ligado o relacionado con la base de datos que se est usando, tal como cuando creamos una tabla, por ejemplo. Para llamar a un procedimiento lo hacemos mediante la instruccin CALL. Desde un procedimiento podemos invocar a su vez a otros procedimientos o funciones. Un procedimiento almacenado, al igual cualquiera de los procedimientos que podamos programar en nuestras aplicaciones utilizando cualquier lenguaje, tiene:
Un nombre. Puede tener una lista de parmetros. Tiene un contenido (seccin tambin llamada definicin del procedimiento: aqu se especifica qu es lo que va a hacer y cmo).
Ese contenido puede estar compuesto por instrucciones sql, estructuras de control, declaracin de variables locales, control de errores, etctera. MySQL sigue la sintaxis SQL:2003 para procedimientos almacenados, que tambin usa IBM DB2. En resumen, la sintaxis de un procedimiento almacenado es la siguiente:
view plainprint?
1. 2.
Puede haber ms de un parmetro (se separan con comas) o puede no haber ninguno (en este caso deben seguir presentes los parntesis, aunque no haya nada dentro). Los parmetros tienen la siguiente estructura: modo nombre tipo Donde: modo: es opcional y puede ser IN (el valor por defecto, son los parmetros que el procedimiento recibir), OUT (son los parmetros que el procedimiento podr modificar) INOUT (mezcla de los dos anteriores). nombre: es el nombre del parmetro. tipo: es cualquier tipo de dato de los provistos por MySQL.
Dentro de caractersticas es posible incluir comentarios o definir si el procedimiento obtendr los mismos resultados ante entradas iguales, entre otras cosas. definicin: es el cuerpo del procedimiento y est compuesto por el procedimiento en s: aqu se define qu hace, cmo lo hace y bajo qu circunstancias lo hace. As como existen los procedimientos, tambin existen las funciones. Para crear una funcin, MySQL nos ofrece la directiva CREATE FUNCTION. La diferencia entre una funcin y un procedimiento es que la funcin devuelve valores. Estos valores pueden ser utilizados como argumentos para instrucciones SQL, tal como lo hacemos normalmente con otras funciones como son, por ejemplo, MAX() o COUNT(). Utilizar la clusula RETURNS es obligatorio al momento de definir una funcin y sirve para especificar el tipo de dato que ser devuelto (slo el tipo de dato, no el dato). Su sintaxis es:
view plainprint?
1. 2. 3.
Puede haber ms de un parmetro (se separan con comas) o puede no haber ninguno (en este caso deben seguir presentes los parntesis, aunque no haya nada dentro). Los parmetros tienen la siguiente estructura:nombre tipo Donde: nombre: es el nombre del parmetro. tipo: es cualquier tipo de dato de los provistos por MySQL. Dentro de caractersticas es posible incluir comentarios o definir si la funcin devolver los mismos resultados ante entradas iguales, entre otras cosas. definicin: es el cuerpo del procedimiento y est compuesto por el procedimiento en s: aqu se define qu hace, cmo lo hace y cundo lo hace. Para llamar a una funcin lo hacemos simplemente invocando su nombre, como se hace en muchos lenguajes de programacin. Desde una funcin podemos invocar a su vez a otras funciones o procedimientos.
view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9.
mysql> delimiter // mysql> CREATE PROCEDURE procedimiento (IN cod INT) -> BEGIN -> SELECT * FROM tabla WHERE cod_t = cod; -> END -> // Query OK, 0 rows affected (0.00 sec) mysql> delimiter ; mysql> CALL procedimento(4);
En el cdigo anterior lo primero que hacemos es fijar un delimitador. Al utilizar la lnea de comandos de MySQL vimos que el delimitador por defecto es el punto y coma (;): en los procedimientos almacenados podemos definirlo nosotros. Lo interesante de esto es que podemos escribir el delimitador anterior; sin que el procedimiento termine. Ms adelante, en este mismo cdigo volveremos al delimitador clsico. Luego creamos el procedimiento con la sintaxis vista anteriormente y ubicamos el contenido entre las palabras reservadas BEGIN y END. El procedimiento recibe un parmetro para luego trabajar con l, por eso ese parmetro es de tipo IN. Definimos el parmetro como OUT cuando en l se va aguardar la salida del procedimiento. Si el parmetro hubiera sido de entrada y salida a la vez, sera de tipo denominado INOUT. El procedimiento termina y es llamado luego mediante la siguiente instruccin:
view plainprint?
1.
Otro ejemplo:
view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
CREATE PROCEDURE procedimiento2 (IN a INTEGER) BEGIN DECLARE variable CHAR(20); IF a > 10 THEN SET variable = mayor a 10; ELSE SET variable = menor o igual a 10; END IF; INSERT INTO tabla VALUES (variable); END
El procedimiento recibe un parmetro llamado a que es de tipo entero. Se declara una variable para uso interno que se llama variable y es de tipo char. Se implementa una estructura de control y si a es mayor a 10 se asigna a variable un valor. Si no lo es se le asigna otro. Se utiliza el valor final de variable en una instruccin SQL. Recordemos que para implementar el ultimo ejemplo se debern usar nuevos delimitadores, como se vio anteriormente. Observemos ahora un ejemplo de funciones:
view plainprint?
1. 2. 3. 4. 5. 6. 7.
mysql> delimiter // mysql> CREATE FUNCTION cuadrado (s SMALLINT) RETURNS SMALLINT -> RETURN s*s; -> // Query OK, 0 rows affected (0.00 sec) mysql> delimiter ; mysql> SELECT cuadrado(2);
Otras bases de datos como PostgreSQL implementan procedimientos almacenados y brindan la posibilidad de programarlos utilizando lenguajes como PHP o Java. En MySQL hay intenciones de implementar lo mismo y seguramente en las prximas versiones lo veremos, pero ms importante que utilizar un lenguaje u otro es entender para qu podran servirnos los procedimientos almacenados. En definitiva hemos dado un recorrido por el mundo de la programacin de procedimientos almacenados en MySQL. Es importante que se trata de un mundo que est en pleno desarrollo y que promete evolucionar.
Un procedimiento almacenado es un programa que se guarda fsicamente en una base de datos. Su implementacin vara de un gestor de bases de datos a otro. Este programa esta hecho con un lenguaje propio de cada Gestor de BD y esta compilado, por lo que la velocidad de ejecucin es muy rpida. Las principales ventajas son: El S.G.B.D. es capaz de trabajar ms rpido con los datos que cualquier programa externo, ya que posee acceso directo a los datos a manipular y slo necesita enviar el resultado final al usuario. Slo realizamos una conexin al servidor y este ya es capaz de realizar todas las comprobaciones sin tener que volver a establecer una conexin. Podemos reutilizar el procedimiento y este puede ser llamado desde diferentes aplicaciones y lenguajes. Slo lo programaremos una vez. La desventaja principal es que se guarda en la B.D., por o que si se corrompe podemos perder los procedimientos. La solucin como siempre en las BB.DD. es tener una buena poltica de copias de seguridad. Bueno dejemos la teora y vayamos a la prctica este es el ejemplo de un procedimiento almacenado:
> > > > > > > > > > DELIMITER // CREATE PROCEDURE addAutomovil(IN nombre VARCHAR(50),IN plazas INT) BEGIN IF plazas < 6 THEN INSERT INTO coche VALUES(nombre,plazas); ELSE INSERT INTO monovolumen VALUES(nombre,plazas); END IF; END; //
Este procedimiento almacenado recibe los parmatros de nombre y nmero de plazas y en funcin de las plazas del vehculo inserta los datos en la tabla coche o monovolumen. Es una funcin bien tonta, lo s, incluso podra ser ms lenta como procedimiento almacenado que como cdigo en nuestro programa. Pero es simplemente un ejemplo. Para hacer una llamada al procedimiento almacenado basta con usar la sentencia call:
> CALL addAutomovil("Nissan Serena",8);
De ahora en adelante, usaremos siempre este procedimiento para introducir automviles en la B.D. de forma que si un da se debe modificar slo deberemos corregir el procedimiento.
Bien como ya hemos visto los procedimientos almacenados son muy interesantes, aqu no hemos visto estructuras de control, como lo son IF, SWITCH, WHILE,VARIABLES, etc y creo que es bueno comenzar con esta ultima. VARIABLES
Esta tendr un mbito local y cuando se acabe el procedimiento no podr ser accedida. Una vez la variable es declarada, para cambiar su valor usaremos la sentencia SET como en el siguiente ejemplo:
SET edad = 56 ;
Para poder acceder a una variable a la finalizacin de un procedimiento se tiene que usar parmetros de salida como en el siguiente Cdigo: IF THEN ELSE
1 2 3 4 5 6 7 8 9 10 11 12 1 2 3 4 5 6 7 8 9 10 11 12
delimiter // CREATE procedure miProc(IN p1 int) /* Parmetro de entrada */ begin declare miVar int; /* se declara variable local */ SET miVar = p1 +1 ; /* se establece la variable */ IF miVar = 12 then INSERT INTO lista VALUES(55555); else INSERT INTO lista VALUES(7665); end IF; end; //
SWITCH
delimiter // CREATE procedure miProc (IN p1 int) begin declare var int ; SET var = p1 +2 ; case var when 2 then INSERT INTO lista VALUES (66666); when 3 then INSERT INTO lista VALUES (4545665); else INSERT INTO lista VALUES (77777777); end case; end; //
1 2 3 4 5 6 7 8 9 10
delimiter // CREATE procedure compara(IN cadena varchar(25), IN cadena2 varchar(25)) begin IF strcmp(cadena, cadena2) = 0 then SELECT "son iguales!"; else SELECT "son diferentes!!"; end IF; end; //
La funcin strcmp devuelve 0 si las cadenas son iguales, si no devuelve 0 es que son diferentes. USO DE WHILE
1 2 3 4 5 6 7 8 9 10 11
delimiter // CREATE procedure p14() begin declare v int; SET v = 0; while v < 5 do INSERT INTO lista VALUES (v); SET v = v +1 ; end while; end; //
1 2 3 4 5 6 7 8 9 10 11 12
delimiter // CREATE procedure p15() begin declare v int; SET v = 20; repeat INSERT INTO lista VALUES(v); SET v = v + 1; until v <= 1 end repeat; end; //
Como primer post le dejare y enseare a como crear un procedimiento Almacenado en MySQL puesto que un Amigo me molesto mucho para que me creara este Blog para compartir Conocimiento. Yo lo encontr super bueno porque como dice la bienvenida de este blog OPEN SOURCE para los desarrolladores de Hoy :).Bueno Comencemos con el Apunte de Store Procedure en MySQL En Primera Instancia en MySQL no es llegar y ponerse a programar la rutina con un CREATE PROCEDURE nombre_sp, ac debemos comenzar con las palabras DELIMITER // que no se olvide los / o si algn otro apunte en otra pgina aparece con signo $. entonces la estructura del cuerpo del SP seria as 1
DELIMITER //
2
CREATE PROCEDURE el_nombre_del_sp()
3 4
AS
5 6
BEGIN
7 8
END;
9 10 11 Ese seria el primer paso de como crear un sp, ahora procedemos a realizar una consulta SQL dentro del SP que seria algo as
DELIMITER//
1 2 3 4 5 6 7 8 9 10 11 12 13
DELIMITER //
AS
BEGIN
END;
DELIMITER//
Con est tipo de forma sera para realizar una consulta a toda una tabla con filtro pero les quiero pedir mucho OJO para finalizar la consulta SQL porque ac la consulta termina con ;, lo que es muy diferente a los otros motores de Base de Datos como por Ejemplo SQL SERVER, SYBASE, ORACLE. Ahora si queremos un procedimiento que requiera parametros de entradas debes declararlos de la siguiente forma. 1 2
DELIMITER //
3 4 5 6 7 8 9 10
IN tu_atributo1 varchar(50),
IN tu_atributo2 varchar(50)
11 12
AS
13 14
BEGIN
15 16
INSERT INTO tu_tabla values(tu_atributo1,tu_atributo2);
17 18 19 20 21
DELIMITER//
END;
Ac se reciben parmetro de Entradas para realizar una insercin simple directo a una tabla pero a esto surge una pregunta y si existe el atributo identificatorio como lo es el tu_atributo1? La Respuesta est pregunta es super simple solo debemos validar el procedimiento almacenado que seria una cosa as 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
BEGIN AS ) IN tu_atributo2 varchar(50) IN tu_atributo1 varchar(50), ( CREATE PROCEDURE el_nombre_del_sp
DELIMITER //
17 18 19 20 21 22 23 24
END IF;
END;
DELIMITER//
25 Para ejecutar y probar cada sp tienes que poner CALL nombre_sp asi el motor te lo ejecutara ejemplo: 1
CALL el_nombre_del_sp();
Y Eso seria por el momento. para validar la existencia de registros en rutinas SP de MySQL Esperando que el apunte le all gustado y lo compartan con mucha mas Gente, y pronto estar subiendo nuevos apuntes relacionados con est linda carrera como lo es la Informtica.
'Definicin de Objetos Dim cn As ADODB.Connection Dim cmd As ADODB.Command Dim rst As ADODB.Recordset Set cn = New ADODB.Connection With cn .ConnectionString = DB_CONNECT .Open End With Set cmd = New ADODB.Command With cmd .ActiveConnection = cn 'Activo la Conexin .NamedParameters = True .CommandType = adCmdStoredProc 'Defino el tipo de comando .CommandText = "proc_guardar_editar_usuario()" 'Defino los parmetros a enviar Set rst = .Execute 'Ejecuto el envio del procedimiento. End With If IsNull(Me.id_usuario) Then 'Pregunto si esta vacio el cuadro de texto id_usuario, si esta vacio entonces cargamos_ el dato devuelto por el procedimiento el id_usuario o se 1. Me.id_usuario = rst(0) rst.Close ' Cierro el recordset, para poder usarlo eventualmente en otros procedimientos. MsgBox "Se ha guardado con exito", vbInformation, "Guardar" Else ' De lo contrario el registro se esta editando. MsgBox "Se ha editado con xito", vbInformation, "Editar" End If cn.Close 'Cierro la conexin Set cmd = Nothing Set cn = Nothing