Professional Documents
Culture Documents
- Conctate a Postgres y abre el pgAdminIII, selecciona la base de datos con la que trabajaras y busca
el campo Sequences, dale click derecho y elegi la opcin New Sequence.
- En la ventana que aparece New Sequence, debes rellenar el campo Name: nombre para la
secuencia, Owner: el propietario que hara uso de la secuencia, en mi caso se llama postgres,
Increment: el incremento, si lo dejas vacio, incrementara de 1 en 1, pero es mejor especificarlo, Start:
en que valor iniciara el incremento, tenemos otros valores para completar, pero por el momento lo que
tenemos es suficiente. Para terminar dale OK
- Para agregar esta secuencia en un campo de cualquier tabla, debemos darle un nombre a la columna,
en este caso sera tambien id, el tipo de dato Data Type sera Integer y en campo Default Value,
debemos agregar la secuencia que creamos en el paso anterior, de la siguiente
manera: NEXTVAL(secuencia_id), es decir:
El ejemplo que crearemos es muy simple, teniendo algunos registros en la tabla PERSONA, crearemos
una funcin que nos permita registrar participantes en la tabla TORNEO, con la restriccin de que si la
edad es mayor o igual de 18 aos, se registren en la categora Mayores, caso contrario si la edad es
menor de 18 aos, corresponden a la categora Menores. Un ejemplo muy simple, pero que nos sirve
para ver en su mayora las instruccin ms utilizadas en las funciones, parmetros, variables, consultas,
instrucciones condicionales, etc.
la funcin completa la tienes en el siguiente cdigo:
declare
-- se declaran las variables a utilizar
ci character(7); -- ID de tabla persona = CEDULA DE IDENTIDAD
edad integer; -- la edad del participante
--la funcion va entre BEGIN y END
begin
ci = $1 ; -- ci toma valor del parametro de entrada
-- el valor de edad, sera calculado mediante una consulta a la tabla persona
edad = ( select p."edad" from "persona" as p where p."CI" = ci );
-- de acuerdo al valor de EDAD registramos al participante en la categoria
-- >=18 Mayores <18 Menores sino, NO SE REGISTRA NADA
if( edad >= 18 ) then
insert into torneo( ci_participante, categoria ) values ( ci, 'Mayores' );
return 'Participante registrado en la categoria MAYORES';
elsif ( edad <18 ) then
insert into torneo( ci_participante, categoria ) values ( ci, 'Menores' );
return 'Participante registrado en la categoria MENORES';
else
return 'Error: No se pudo completar el registro';
end if;
end;
Vimos como ejecutar la funcin desde el propio postgreSQL/pgAdminIII, ahora veremos como
ejecutarlo desde java, el que conozca sobre procedimientos almacenados en MySQL sabr que para
ejecutar un PROCEDURE, se hace uso de CallableStatement, eso es totalmente vlido, sin embargo,
como nuestra funcin solo retorna un resultado, nosotros utilizaremos otra forma :), utilizaremos la
instruccin executeQuery();
Englobaremos todo en una sola clase la cual se llama, pgFunctions, el cdigo es:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* @web http://www.jc-mouse.net
* @author Mouse
*/
public class pgFunctions {
/* DATOS PARA LA CONEXION */
/** Nombre de la base de datos */
private String db = "dbTemp";
/** Usuario postgreSQL */
private String user = "postgres";
/** Contrasea postgreSQL */
private String password = "";
/** Cadena de conexin */
private String url = "jdbc:postgresql://localhost:5432/"+db;
/** Conexion a base de datos */
private Connection conn = null;
/** Para obtener los resultados de las consultas SQL de la base de datos */
private ResultSet resultSet = null;
System.out.println( pgf.CallFunction("1234567") );
Y una vez autenticados en nuestro servidor y seleccionada la base de datos en que trabajaremos
ejecutaremos el editor de consultas SQL que se encuentra en la barra de herramientas:
Y se nos mostrar el editor de consultas, en el que podremos ejecutar tanto cdigo PLSQL como SQL.
Una vez abierto nuestro editor el primer paso ser crear la tabla lista_paises y para ello deberemos
ejecutar el siguiente bloque SQL, modificando antes el userpostgre por el usuario que usas en tu
servidor.
?
1
2
3
4
5
6
7
8
9
10
Ya que tenemos la tabla comenzaremos a crear nuestra funcin. Para ello primero definimos el
encabezado, y aqu es importante mencionar que en este caso, donde vamos a devolver un recordset,
deberemos declarar tantos parmetros de salida como columnas tenga nuestra consulta:
?
CREATE OR REPL
1
( IN PV_OP
2
OUT colu
3
OUT colu
4
)
RETURNS
5
Dado que la funcin devolver un recordset conteniendo las columnas id y opcin, hemos agregado
ambos parmetros de salida a la funcin y hemos agregado el parmetro de entrada Pv_Opcion que
usaremos a manera de men de seleccin para decirle a la funcin que bloque deber ejecutar. Al final
del encabezado establecemos el tipo de dato que devolver la funcin que en este caso ser un
recordset o setof record.
Declarado el encabezado vamos a continuar con el cuerpo de la funcin que contendr las operaciones
a realizar:
?
1
$BODY$
begin
2
IF PV_OPCION = 'DAMETODOS' THEN
3
return query select id, opcion from lista_paises;
4
END IF;
5
IF PV_OPCION = 'DAMECINCO' THEN
6
return query select id, opcion from lista_paises limit 5;
7
END
IF;
8
return;
9
10 end;
11 $BODY$
12 LANGUAGE 'plpgsql';
Como podemos ver, el cdigo es muy parecido al usado en Mysql, con las variantes de que aqu
debemos establecer con return query el recordset a devolver, adems de tener que indicar el lenguaje a
usar y el inicio y fin del cuerpo de la funcin.
Para ejecutar el procedimiento almacenado ejecutaremos la sentencia que nos devolver el listado:
?
1
16
17
$BODY$
LANGUAGE 'plpgsql';
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
nombre_funcion([ [ argmodo ]
[ argnombre ] argtipo [, ...] ])
RETURNS tipo AS $$
[ DECLARE ]
[ declaraciones de variables ]
BEGIN
aqu va el cuerpo de la funcin:
el codigo
END;
$$ LANGUAGE plpgsql
| IMMUTABLE | STABLE | VOLATILE
| CALLED ON NULL INPUT | RETURNS
NULL ON NULL INPUT | STRICT
| [ EXTERNAL ] SECURITY INVOKER
| [ EXTERNAL ] SECURITY DEFINER
| COST execution_cost
| ROWS result_rows
| SET configuration_parameter
{ TO value | = value | FROM CURRENT }
;
No se desanimen si parece mucho cdigo seguid leyendo que describiremos las opciones y valores ms
importantes.
argmodo: El modo de un argumento puede ser IN, OUT, or INOUT. Por defecto se usa IN si no se
define.
argtipo: Los tipos que podemos utilizar son todos los disponibles en PostgreSQL y todos los definidos
por el usuario
declaraciones de variables: Las declaraciones de variables se pueden realizar de la siguiente manera ($n
= orden de declaracin del argumento.):
nombre_variable ALIAS FOR $n;
nombre_variable [ CONSTANT ] tipo [
1
NOT NULL ] [ { DEFAULT | := }
2
expresion ];
cdigo: la parte del codigo lo veremos unas lineas ms abajo. Pero adelanto que es lo que realmente
queremos hacer (el procedimiento en s).
IMMUTABLE | STABLE | VOLATILE:
IMMUTABLE: Indica que la funcin no puede alterar a la base de datos y que siempre devolver el
mismo resultado, dados los mismos valores como argumentos. Este tipo de funciones no pueden
realizar consultas en la base de datos.
STABLE: Indica que la funcin no puede alterar a la base de datos y que siempre devolver el mismo
resultado en una consulta individual de una tabla, dados los mismos valores como argumentos. El
resultado podria cambiar entre sentencias SQL.
VOLATILE: Indica que la funcin puede devolver diferentes valores, incluso dentro de una consulta
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
llamamos a la secuencia
codpais INT4 NOT NULL,
nombres VARCHAR(20) NOT NULL,
apellidos VARCHAR(50) NOT NULL,
email VARCHAR(50) NOT NULL,
clave VARCHAR(20) NOT NULL,
estado CHAR(1) NOT NULL,
FOREIGN KEY(codpais) REFERENCES pais
(codpais) ON DELETE CASCADE ON UPDATE
CASCADE
);
-- insertamos registros
INSERT INTO pais(pais) VALUES
('Per');
INSERT INTO pais(pais) VALUES
('Argentina');
INSERT INTO pais(pais) VALUES
('Brasil');
INSERT INTO pais(pais) VALUES
('Inglaterra');
INSERT INTO usuarios (codpais,
nombres, apellidos, email, clave,
estado ) VALUES (1,'mittaus',
'ragio', 'mittaus@gmail.com',
'admin', 'A' );
INSERT INTO usuarios (codpais,
nombres, apellidos, email, clave,
estado ) VALUES (2,'andrea',
'montes', 'andrea@gmail.com',
'unodos', 'A' );
INSERT INTO usuarios (codpais,
nombres, apellidos, email, clave,
estado ) VALUES (4,'sonia',
'marisol', 'sonia@gmail.com',
'123456', 'A' );
INSERT INTO usuarios (codpais,
nombres, apellidos, email, clave,
estado ) VALUES (3,'zeze', 'souza',
'zeze@gmail.com', 'loquesea', 'I' );
/* Ejemplo de funciones simples*/
-- Funcin sumar uno
CREATE OR REPLACE FUNCTION adduno(INT)
RETURNS INT AS
$$
BEGIN
RETURN $1 + 1;
/* ************************* BEGIN
FUNCIONES EN PL/pgSQL
*****************************/
-- Funcin SELECT: El parmetro es
el nombre cursor que nos traer los
datos
-- Si usamos variables con nombres
combinados de Maysculas y
Minsculas debemos ponerlos entre
comillas dobles (" ").
-- Ejemplo: CREATE FUNCTION
"verAllUsuarios" ...
CREATE OR REPLACE FUNCTION
verusuarios(refcursor) RETURNS
refcursor AS
$BODY$
BEGIN
OPEN $1 FOR SELECT * FROM usuarios;
RETURN $1;
END;
$BODY$ LANGUAGE 'plpgsql' VOLATILE;
--Selecciona las 6 primeras filas
BEGIN
SELECT verusuarios('hola') AS Answer;
FETCH FORWARD 6 in "hola"; -- Si no
existe 6 nos devuelve solo las que
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
encuentre
COMMIT;
--Selecciona las 3 primeras filas y
la fila anterior de la seleccin
(ose la fila 2)
select verusuarios('micursor');
FETCH FORWARD 3 in micursor;
FETCH BACKWARD 1 in miCursor;
-- SELECT: El primer parmetro es el
nombre cursor que nos traer los
datos, y el segundo el campo por el
que haremos la busqueda
CREATE OR REPLACE FUNCTION
usuariosbyname(refcursor,text)
RETURNS refcursor AS
$BODY$
BEGIN
OPEN $1 FOR SELECT * FROM usuarios
WHERE nombres LIKE $2 || '%';
RETURN $1;
END;
$BODY$ LANGUAGE 'plpgsql' VOLATILE;
BEGIN
SELECT
usuariosbyname('otrocursor','m');
FETCH ALL IN otrocursor;
COMMIT;
-- Funcin INSERT: Insertamos un
registro a la tabla
CREATE OR REPLACE FUNCTION
insertar_usuarios(INT, VARCHAR(20),
VARCHAR(50),
VARCHAR(50),VARCHAR(20), CHAR(1))
RETURNS VOID AS
$BODY$
BEGIN
INSERT INTO usuarios (codpais,
nombres, apellidos, email, clave,
estado )
VALUES ($1, $2, $3, $4, $5,$6);
END;
$BODY$ LANGUAGE 'plpgsql' VOLATILE;
BEGIN
SELECT insertar_usuarios(1,'martin',
'dino', 'martin@gmail.com',
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
'mariquin', 'A' )
COMMIT;
SELECT * FROM usuarios;
-- Funcin UPDATE: Actualizamos un
registro por el campo Cdigo,
devolvemos TRUE si se actualiza
CREATE OR REPLACE FUNCTION
update_usuarios(INT, INT,
VARCHAR(20), VARCHAR(50),
VARCHAR(50),VARCHAR(20), CHAR(1))
RETURNS BOOL AS
$BODY$
DECLARE
codigo ALIAS FOR $1;
registro usuarios%ROWTYPE;
BEGIN
SELECT * INTO registro FROM
usuarios WHERE codusuario = codigo;
IF FOUND THEN
UPDATE usuarios SET
codpais = $2, nombres = $3,
apellidos = $4, email = $5, clave =
$6, estado = $7 WHERE codusuario =
codigo;
RETURN TRUE;
END IF;
RETURN FALSE;
END;
$BODY$ LANGUAGE 'plpgsql' VOLATILE;
SELECT update_usuarios(14,3,'marin',
'kino', 'marin@gmail.com', 'marin',
'I' )
SELECT * FROM usuarios;
-- Funcin DELETE: Si se elimina un
registro devolvemos TRUE
CREATE OR REPLACE FUNCTION
del_usuariobycod(INT) RETURNS BOOL AS
$$
DECLARE codigo ALIAS FOR $1;
BEGIN
DELETE FROM usuarios WHERE
codusuario = codigo;
IF FOUND THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
END; $$ LANGUAGE plpgsql;
SELECT * FROM del_usuariobycod(14);
SELECT * FROM usuarios;
-- Funcin SELECT usando RECORD
CREATE OR REPLACE FUNCTION
traer_usuarios() RETURNS SETOF record
AS
$$
DECLARE rec record;
BEGIN
FOR rec IN SELECT * FROM usuarios
LOOP
return next rec;
END LOOP;
RETURN;
END; $$ LANGUAGE plpgsql;
BEGIN
SELECT * FROM traer_usuarios() AS
(codusuario INT,codpais INT, nombres
VARCHAR(50), apellidos VARCHAR(50),
email VARCHAR(50), clave
VARCHAR(50), estado CHAR(1) );
COMMIT;
/* ************************* END
FUNCIONES EN PL/pgSQL
*****************************/
Las funciones que hemos escrito se pueden haber escrito de otros modos. Los que ya tienen algn
tiempo en esto me darn la razn. Pero pienso que para empezar esta bien. Y en los otros posts usar
otras sintxis por ejemplo como adelanto cambiemos la funcin del_usuariobycod. En lugar de los
simbolos $$ pudimos haber usado la comilla simple [ ], tambin asignar defrente el parmetro, fijense
tambin la seccin del IF
1
2
3
4
5
6
7
8
9
10
11
12
13