You are on page 1of 18

Introduccin

El PL_pgSQL es una herramienta de complemento para el SQL ya que este es un lenguaje estndar para la realizacin de consultas a un servidor de base de datos, el PL_pgSQL guarda mucha similitud con el lenguaje de Oracle PL_SQL. Segn Roberto Andrade Fonseca. ABL Consultores, S.A. de C.V. en su publicacin de 8 de Febrero de 2002; este explica que el PL_pgSQL es bastante fcil de utilizar, con el presente manual se dar a entender las sentencias mas frecuentes utilizadas para esta herramienta. Se tomaran ejemplos referenciales de las publicaciones de Roberto Andrade Fonseca Febrero del ao 2002 para la elaboracin del manual PL_pgSQL.y de igualmanera se tomaran ejemplos de la publicacin de Javier Jofre Gonzlez-Granda Junio del ao 2004.

Manejo de las Comillas


El cdigo de una funcin PL/pgSQL se especifica en CREATE FUNCTION como una cadena literal. Si usted escribe la cadena literal de la manera comn, con comillas sencillas como delimitadores, entonces cada comilla sencilla dentro del cuerpo de la funcin debe ser duplicada; de igual manera cualquier diagonal inversa debe ser Duplicada. La duplicacin de las comillas es, por lo menos, tedioso, y en los casos Complejos el cdigo se vuelve incomprensible, debido a que se pueden necesitar media Docena o ms de comillas sencillas contiguas. Es recomendable que mejor escriba el cuerpo de la funcin como una cadena literal dollar-quoted. Con el estilo dollarquoting Usted nunca necesitar duplicar las comillas, en cambio deber cuidar el uso de un delimitador dollar-quoting diferente para cada nivel de anidamiento que necesite. Por ejemplo, usted debe escribir el comando CREATE FUNCTION como: CREATE OR REPLACE FUNCTION testfunc(integer) RETURNS integer AS $PROC$ .... $PROC$ LANGUAGE plpgsql; Dentro de ste, usted puede usar comillas para las cadenas literales simples en los Comandos SQL y $$ para delimitar fragmentos de comandos SQL que est ensamblando. Para crear cadenas ms largas. Si necesita incluir en su texto $$, puede usar $Q$ y as consecutivamente. La siguiente tabla le muestra lo que debe hacer cuando escriba comillas sin delimitar su cadena con $$. Puede serle til cuando traduzca sus funciones hechas con cdigo en el que no se usaba $$ y para hacer ms claro el cdigo.

1 comilla
Para iniciar y finalizar el cuerpo de la funcin, por ejemplo: CREATE FUNCTION foo() RETURNS integer AS .... LANGUAGE plpgsql; En cualquier lugar dentro del cuerpo de la funcin delimitada por una comilla, las comillas deben aparecer en pares.

2 comillas
Para cadenas literales dentro del cuerpo de la funcin, por ejemplo: a_output := Blah; SELECT * FROM users WHERE f_name=foobar; Usando la tcnica de $$, usted debera escribir a_output := Blah; SELECT * FROM users WHERE f_name=foobar; que es exactamente lo que el analizador de PL/pgSQL vera en ambos casos.

4 comillas
Cuando requiera una comilla sencilla en una cadena constante dentro del cuerpo de la funcin, por ejemplo; a_output := a_output || AND name LIKE foobar AND xyz El valor realmente concatenado a a_output sera: AND name LIKE foobar AND xyz.Usando la tcnica de $$, usted escribira: a_output := a_output || $$ AND name LIKE foobar AND xyz$$ teniendo cuidado de que cualquiera de los delimitadores estilo dlar alrededor de esta cadena no sea ciertamente $$.

6 comillas
Cuando una comillas sencilla en una cadena dentro del cuerpo de la funcin sea adyacente al final de la cadena constante, por ejemplo: a_output := a_output || AND name LIKE foobar El valor concatenado a a_output sera entonces: AND name LIKE foobar. Con el estilo dlar se transformara en: a_output := a_output || $$ AND name LIKE foobar$$

10 comillas
Cuando requiera dos comillas sencillas en una cadena constante (que equivalen a 8 comillas) y sta es adyacente al final de la cadena constante (2 ms). Es probable que solamente necesite esto si est escribiendo una funcin que genera otras funciones. Por ejemplo: a_output := a_output || if v_ || referrer_keys.kind || like || referrer_keys.key_string || then return || referrer_keys.referrer_type || ; end if;; El valor de a_output sera entonces: if v_... like ... then return ...; end if; Con el estilo dlar quedara como a_output := a_output || $$ if v_$$ || referrer_keys.kind || $$ like $$ || referrer_keys.key_string || $$ then return $$ || referrer_keys.referrer_type || $$; end if;$$; en donde suponemos que solamente requerimos colocar una comilla dentro de a_output debido a que ser re-encomillado antes de usarse. Una variante es el escapar las comillas en el cuerpo de la funcin con una diagonal invertida en lugar de duplicarlas. Con este mtodo escribira cosas como \\ en lugar de . Algunas personas consideran esta tcnica ms sencilla, pero otras no.

La Estructura de PL/pgSQL
PL/pgSQL es un lenguaje estructurado a base de bloques. El texto completo de la definicin de una funcin debe ser un bloque. Un bloque est definido como: [ <<etiqueta>> ] [ DECLARE declaraciones ] BEGIN sentencias END; Cada declaracin y cada sentencia dentro de un bloque deben terminar con punto y coma. Un bloque que aparece dentro de otro bloque debe contar con un punto y coma despus de END, como se muestra abajo; sin embargo, el END final que cierra el cuerpo de una funcin no requiere el punto y coma. Todas la palabras reservadas y los identificadores pueden escribirse en maysculas, minsculas o una mezcla de ellas. Los identificadores son convertidos implicitamente a minsculas, a menos que estn encerradas en comillas dobles. Existen dos tipos de comentarios en PL/pgSQL. Un doble guin (--) marca el inicio de un comentario que se extiende hasta el final de la lnea. Los smbolos /* marcan el inicio de un bloque de un comentario que se extiende hasta la aparicin de /*. Los bloques de comentarios no pueden anidarse, pero los comentarios con doble guin pueden ocultar los delimitadores de un bloque de un comentario /* y */. Cualquier sentencia en la seccin de sentencias de un bloque puede ser un subbloque. Los subbloques pueden usarse para agrupamientos lgicos o para hacer locales las variables de un grupo de sentencias. Las variables declaradas en la seccin de declaraciones que precede a un bloque son inicializadas a su valor por omisin cada vez que se entra al bloque, no solamente una vez por llamada a la funcin. Por ejemplo: CREATE FUNCTION somefunc() RETURNS integer AS $$ DECLARE quantity integer := 30; BEGIN RAISE NOTICE Aqu, cantidad tiene el valor de %, quantity; -- Aqu, cantidad tiene el valor de 30 quantity := 50; --- Creamos un subbloque -DECLARE quantity integer := 80; BEGIN RAISE NOTICE Aqu, cantidad tiene el valor de %, quantity; -- Aqu, cantidad tiene el valor de 80 END; RAISE NOTICE Aqu, cantidad tiene el valor de %, quantity; -- Aqu, cantidad tiene el valor de 50 RETURN quantity; END; $$ LANGUAGE plpgsql; 4

Es importante no confundir el uso de BEGIN/END para agrupar sentencias en PL/pgSQL con los comandos de la base de datos para el control de las transacciones. Los comandos BEGIN/END de PL/pgSQL se usan solamente para agrupar; no inician ni terminan una transaccin. Las funciones y los procedimientos disparadores (trigger) siempre son ejecutados dentro de una transaccin establecida por una consulta externa no pueden iniciar o hacer que se ejecute un commit de esa transaccin, puesto que no existe un contexto para su ejecucin. Sin embargo, un bloque que contenga una clasula de EXCEPTION s genera una subtransaccin que puede echarse atrs (rolled back) sin afectar la transaccin externa. Para ms detalles puede ver la seccin de nombre Atrapar los Errores.

Declaraciones
Todas las variables usadas en un bloque deben ser declaradas en la seccin de declaraciones de ese bloque. (La nica excepcin es que la variable ndice de un ciclo FOR que itera sobre un rango de valores enteros es declarada automticamente como una variable entera). Las variables de PL/pgSQL pueden tener cualquier tipo de dato de SQL, tales como integer, varchar y char. Estos son algunos ejemplos de la declaracin de variables: user_id integer; cantidad numeric(5); url varchar; myrenglon nombretabla%ROWTYPE; mycampo nombretabla.nombrecolumna%TYPE; unrenglon RECORD; La sintaxis general de la declaracin de una variable es: nombre [ CONSTANT ] tipo [ NOT NULL ] [ { DEFAULT | := } expresin ]; La clusula DEFAULT, cuando existe, especifica el valor inicial asignado a la variable cuando se ingresa al bloque. Si la clasula DEFAULT no existe entonces la variable se inicializa al valor nulo de SQL. Si se especifica NOT NULL, la asignacin de un valor nulo dar por resultado un error en tiempo de ejecucin. Todas las variable declaradas como NOT NULL deben tener especificado un valor no nulo. El valor por omisin se evala cada vez que se entra al bloque. As, por ejemplo, el asignar now() a la variable de tipo timestamp causar que esa variable tenga la hora de la llamada a la funcin actual, no la hora en que la funcin fue precompilada. Ejemplos: cantidad integer DEFAULT 32; url varchar := http://misitio.com; user_id CONSTANT integer := 10;

Alias para los Parmetros de las Funciones


Los parmetros pasados a las funciones se nombran con los identificadores $1, $2, etc. Opcionalmente, se pueden declarar aliases para $n nombres de parmetros para una mayor claridad. Tanto el alias como su identificador numrico pueden ser usados para referirse al valor del parmetro. Existen dos maneras de crear un alias. La manera preferida es asignarle un nombre al parmetro en el comando CREATE FUNCTION, por ejemplo: CREATE FUNCTION impuesto_ventas(subtotal real) RETURNS real AS $$ BEGIN RETURN subtotal * 0.06; END; $$ LANGUAGE plpgsql; La otra manera, que era la nica disponible para versiones previas a PostgreSQL 8.0, es el declarar explcitamente un alias, usando la sintaxis de declaracin nombre ALIAS FOR $n; El mismo ejemplo en este estilo se vera as CREATE FUNCTION impuesto_ventas(real) RETURNS real AS $$ DECLARE subtotal ALIAS FOR $1; BEGIN RETURN subtotal * 0.06; END; $$ LANGUAGE plpgsql; Cuando el tipo regresado de una funcin PL/pgSQL se declara como de tipo polimrfico (anyelement o anyarray), se crea un parmetro especial $0. Su tipo de dato es el tipo de dato actual regresado por la funcin, el cual deduce de los tipos de entrada actuales. Esto permite a la funcin acceder a su tipo de retorno actual como se muestra en la seccin de nombre Copiando Tipos. La variable $0 se inicializa a nulo y puede ser modificada por la funcin, de tal manera que pueda ser usada para almacenar el valor de retorno si eso es lo que se desea, aunque esto no es necesario. A la variable $0 tambin se le puede dar un alias. Por ejemplo, esta funcin trabaja con cualquier tipo de dato que tenga un operador +: CREATE FUNCTION suma_tres_valores(v1 anyelement,v2 anyelement, v3 anyelement) RETURNS anyelement AS $$ DECLARE resultado ALIAS FOR $0; BEGIN resultado := v1 + v2 + v3; RETURN resultado; END; $$ LANGUAGE plpgsql;

Copiando Tipos
variable%TYPE %TYPE proporciona el tipo de dato de una variable o de una columna de una tabla. Puede utilizarla para declarar variables que almacenarn valores de la base de datos. Por ejemplo, supongamos que tiene una columna llamada id_usuario en su tabla usuarios. Para declarar una variable con el mismo tipo de dato que usuarios.id_usuario usted escribira: id_usuario usuarios.id_usuario%TYPE; Al usar %TYPE no necesita conocer el tipo de dato de la estructura a la que est haciendo referencia, y lo ms importante, si el tipo de dato del tem referido cambia en algn momento en el futuro (por ejemplo: si cambia el tipo de id_usuario de integer a real), usted no necesita cambiar la definicin en su funcin. %TYPE es particularmente til en las funciones polimrficas, puesto que los tipos de datos necesarios para las variables internas puede cambiar de una llamada a otra. Se pueden crear variables apropiadas aplicando %TYPE a los argumentos o a los comodines de los resultados de la funcin.

Tipos Rengln
nombre nombre_tabla%ROWTYPE; nombre nombre_tipo_compuesto; Una variable de un tipo compuesto se denomina una variable rengln (o tipo-renglon). Dicha variable puede almacenar un rengln completo resultado de una consulta SELECT o FOR, en tanto el conjunto de columnas de la consulta coincida con el tipo de la variable declarado. Los campos individuales del valor del rengln pueden accederse usando la notacin usual de punto, por ejemplo renglonvar.campo. Una variable rengln puede declararse para tener el mismo tipo que los renglones de una tabla o vista existente, usando la notacin nombre_tabla%ROWTYPE; o puede ser declarada dando el nombre de un tipo compuesto. (Puesto que todas las tablas tiene un tipo compuesto asociado del mismo nombre, en PostgreSQL realmente no importa si escribe %ROWTYPE o no. Pero la forma con %ROWTYPE es ms portable). Los parmetros de una funcin pueden ser de tipo compuesto (renglones de tablas completos). En ese caso, el identificador correspondiente $n ser un variable rengln, y pueden seleccionarse los campos a partir de l, por ejemplo $1.id_usuario. En una variable tipo-rengln, solamente son accesibles las columnas definidas por el usuario, no el OID u otras columnas del sistema (debido a que el rengln podra ser de una vista). Los campos del tipo rengln heredan el tamao o la precisin del campo de la tabla para datos tales como char(n).

Este es un ejemplo del uso de los tipos compuestos: CREATE FUNCTION merge_fields(t_row tablename) RETURNS text AS $$ DECLARE t2_row table2name%ROWTYPE; BEGIN SELECT * INTO t2_row FROM table2name WHERE ... ; RETURN t_row.f1 || t2_row.f3 || t_row.f5 || t2_row.f7; END; $$ LANGUAGE plpgsql; SELECT merge_fields(t.*) FROM tablename t WHERE ... ;

Tipos Registro
nombre RECORD; Las variables registro son similares a las variables tipo-rengln, pero no tienen una estructura predefinida. Toman la estructura actual del rengln al que son asignados durante un comando SELECT o FOR. La subestructura de una variable registro puede cambiar cada vez que es asignada. Una consecuencia de sto es que mientras una variable registro no sea asignada por primera vez, no tendr subestructura y cualquier intento de acceder a uno de sus campos generar un error en tiempo de ejecucin. Observe que RECORD no es realmente un tipo de dato, sino un comodn. Tambin debe darse cuenta que cuando una funcin PL/pgSQL se declara para regresar un tipo record, no es lo mismo que una variable registro, aunque tal variable pueda utilizar una variable registro para almacenar su resultado. En ambos casos la estructura actual del rengln es desconocida cuando se escribe la funcin, pero para una funcin que regresa un record la estructura actual se determina cuando se analiza la consulta solicitada, mientras que una variable record puede cambiar su estructura de renglnal instante.

Expresiones
Todas las expresiones usadas en sentencias de PL/pgSQL son procesadas usando el ejecutor SQL regular del servidor. De hecho, una consulta como SELECT expresin se ejecuta usando al administrador SPI. Antes de la evaluacin, las ocurrencias de los identificadores de variables de PL/pgSQL son reemplazados por los parmetros y el valor actual de las variables se pasa al ejecutor en el arreglo de parmetros. Esto permite que el plan de la consulta del SELECT sea preparado solamente una vez y despus reutilizado para las evaluaciones subsecuentes. La evaluacin hecha por el analizador (parser) pricipal de PostgreSQL tiene algunos efectos secundarios en la interpretacin de los valores constantes. En detalle existen diferencias entre lo que hacen estas dos funciones:
CREATE FUNCTION logfunc1(logtxt text) RETURNS timestamp AS $$ BEGIN INSERT INTO logtable VALUES (logtxt, now); RETURN now; END; $$ LANGUAGE plpgsql;

Y
CREATE FUNCTION logfunc2(logtxt text) RETURNS timestamp AS $$ DECLARE curtime timestamp; BEGIN curtime := now; INSERT INTO logtable VALUES (logtxt, curtime); RETURN curtime; END; $$ LANGUAGE plpgsql;

En en caso de logfunc1, el analizador principal de PostgreSQL sabe cuando preparar el plan para el INSERT, que la cadena now debe interpretarse como timestamp debido a que su columna objetivo de logtable es de ese tipo. As, crear una constante con ella en este momento y su valor constante ser utilizado en todas las invocaciones de logfunc1 durante la vida de la sesin. No es necesario decir que esto no es lo que el programador deseaba hacer En el caso de logfunc2, el analizador principal de PostgreSQL no sabe que tipo debe tener now y entonces regresa un valor de tipo text que contiene la cadena now. Durante la asignacin subsiguiente a la variable local curtime, el intrprete de PL/pgSQL transforma esta cadena al tipo timestamp llamando a las funciones text_out y timestamp_in para la conversin. As, la hora y la fecha calculadas en cada ejecucin es la que espera el programador La naturaleza mutable de las variables registro presentan un problema en este mbito. Cuando los campos de una variable registro son usados en expresiones o sentencias, los tipos de datos de los campos no deben cambiar entre llamadas de una misma expresin, puesto que la expresin ser planeada usando los tipos de dato que estn presentes cuando la expresin sea alcanzada por primera vez. Tenga en cuenta esto al escribir procedimientos disparadores que manejen eventos para ms de una tabla.(Cuando se necesario, puede utilizar EXECUTE para evitar este problema). 9

Asignacin
Una asignacin de una valor a una variable o campo de un rengln/registro se escribe como: identificador := expresin; Tal como se escribi arriba, la expresin en tal sentencia es evaluada por medio de un comando SQL SELECT enviado a la mquina de la base de datos principal. La expresin debe producir un valor nico. Si el tipo de dato del resultado de la expresin no coincide con el tipo de dato de la variable, o la variable tiene un tamao/precisin especfico (como char(20)), el valor resultante ser convertido implcitamente por el intrprete de PL/pgSQL usando el tipo de resultado de la funcin de salida (output_function) y el tipo de variable de la funcin de entrada (input_function). Observe que esto puede resultar potencialmente en un error en tiempo de ejecucin generado por la funcin de entrada, si la forma de la cadena del valor resultante no es aceptable para la funcin de entrada. Ejemplos: id_usuario := 20; impuesto := subtotal * 0.15;

SELECT INTO
El resultado de un comando SELECT que produce columnas mltiples (pero slo un rengln) puede ser asignado a una variable registro, variable tipo-rengln o una lista de variables escalares. Esto se realiza con: SELECT INTO meta expresiones_select FROM ...; en donde meta puede ser una variable registro, una variable rengln o una lista de variables simples y campos registro/rengln separados por comas. Las expresiones_select y el resto del comando son iguales que en el SQL regular. Observe que es muy diferente de la interpretacin normal de SELECT INTO de PostgreSQL, en donde la meta INTO es una tabla recin creada. Si desea crear una tabla a partir de una resultado de un SELECT dentro de una funcin PL/pgSQL, use la sintaxis CREATE TABLE ... AS SELECT. Si un rengln o una lista de variables se usa como meta, los valores seleccionados deben coincidir exactamente con la estructura de la meta, u ocurrir un error en tiempo de ejecucin. Cuando la meta es una variable registro, automticamente se configura siguiendo la estructura del tipo rengln de la columnas del resultado de la consulta. Las sentencia SELECT es la misma que el comando SELECT normal y puede utilizarse con todo su poder, con la excepcin de la clasula INTO. La clasula INTO puede aparecer casi en cualquier lugar en la sentencia SELECT. Suele escribirse ya sea antes de SELECT como se muestra arriba o justo antes de FROM es decir, justo antes o justo despus de la lista de las expresiones_select. Si la consulta regresa cero renglones, se asignan valores nulos a la(s) meta(s). Si la consulta regresa mltiples renglones, se asigna el primer 10

rengln a la(s) meta(s) y el resto se descarta. (Observe que el primer rengln no est bien definido a menos que haga uso de ORDER BY). Puede verificar la variable especial FOUND (vea la seccin de nombre Obteniendo el Estado del Resultado) despus de una sentencia SELECT INTO para determinar si la Asignacin fue correcta, es decir, que la consulta regres al menos un rengln. Por ejemplo: SELECT INTO mireg * FROM emp WHERE empnombre= minombre; IF NOT FOUND THEN RAISE EXCEPTION no se encontr al empleado %, minombre; END IF; Para probar si un resultado registro/rengln es nulo puede usar la condicional IS NULL. Sin embargo, no existe una manera de decir si han sido descartados algunos renglones adicionales. Aqu hay un ejemplo que maneja el caso en que no se han regresado renglones: DECLARE reg_usuarios RECORD; BEGIN SELECT INTO reg_usuarios * FROM usuarios WHERE id_usuario=3; IF reg_usuarios.homepage IS NULL THEN -- El usuario no digit un homepage, regresar "http://" RETURN http://; END IF; END;

No Hacer Absolutamente Nada


Algunas veces una sentencia comodn que no hace nada es til. Por ejemplo, puede indicar que una rama del una cadena if/then/else se encuentra vaca deliberadamente. Para hacer esto, use la sentencia NULL: NULL; Por ejemplo, los siguientes dos fragmentos de cdigo son equivalentes: BEGIN y := x / 0; EXCEPTION WHEN division_by_zero THEN NULL; -- ignore el error END; BEGIN y := x / 0; EXCEPTION WHEN division_by_zero THEN -- ignore el error END; Dejamos a su eleccin el que quiera usar. Nota: En el PL/SQL de Oracle las sentencias vacias no estn permitidas, as que las sentencias NULL son requeridas para situaciones como sas. PL/pgSQL permite, en cambio, el escribir nada. 11

Ejecucin de Comandos Dinmicos


Con frecuencia tendr necesidad de generar comandos dinmicos dentro de sus funciones PL/pgSQL, esto es, comandos que involucren diferentes tablas o diferentes tipos, cada vez que son ejecutados. Los intentos normales de PL/pgSQL para guardar los planes para los comandos no trabajarn es tales escenarios. Para manejar esa clase de problemas se proporcion el comando EXECUTE: EXECUTE cadena-de-comando; En donde cadenade-comando es una expresin que da como resultado una cadena (de tipo text), la cual contiene el comando a ser ejecutado. Esta cadena se alimenta, literalmente, a la mquina SQL. Observe en particular que no se realiza ninguna sustitucin de variables PL/pgSQL en la cadena de comando. Los valores de las variables deben ser insertados en la cadena de comando al momento de construirse. A diferencia de otros comandos en PL/pgSQL, un comando ejecutado por una sentencia EXECUTE no se prepara y guarda slo una vez durante la vida de la sesin. En cambio, el comando se prepara cada vez que se ejecuta la sentencia. La cadena de comando puede se creada dinmicamente dentro de la funcin para ejecutar acciones en diferentes tablas y columnas. Los resultados de un SELECT son descartados por el comando EXECUTE y el SELECT INTO no est soportado actualmente dentro de EXECUTE. As que no hay manera de extraer un resultado de un SELECT creado dinmicamente usando el comando EXECUTE simple. Sin embargo, existen otras maneras de hacerlo: una implica el usar la forma del ciclo FOR-IN-EXECUTE descrita en la seccin de nombre Ciclos a Travs de Resultados de Consultas, y la otra es utilizar un cursor con OPENFOR-EXECUTE, como se describe en la seccin de nombre Apertura de Cursores. Cuando trabaje con comandos dinmicos tendr que contender frecuentemente con el escape de las comillas sencillas. El mtodo recomendado para entrecomillar texto fijo en el cuerpo de su funcin es el entrecomillar con el signo de dlares. (Si tiene cdigo heredado que no use el entrecomillado con el signo de dlares, refirase a la visin general en la seccin de nombre Manejo de las Comillas, la cual de ahorrar algunos esfuerzos al traducir dicho cdigo a un esquema ms razonable). Los valores dinmicos que se van a insertar dentro de la consulta construida requieren un manejo especial, puesto que ellos mismos pueden contener comillas. Un ejemplo (presupone que usted est usando entrecomillado con el signo de dlares para toda la funcin, de tal manera que las comillas no necesitan ser dobles): EXECUTE UPDATE tbl SET || quote_ident(nombrecol) || = || quote_literal(nuevovalor) || WHERE llave= || quote_literal(llavevalor);

12

Este ejemplo ilustra el uso de las funciones quote_ident(text) y quote_literal(text). Por seguridad, las variables que contienen valores que deben ser cadenas literales en el comando construido deben pasarse a quote_literal. Ambas siguen los pasos apropiados para regresar el texto de entrada encerrado en comillas sencillas o dobles respectivamente, con cualquier carcter especial embebido escapado de la manera correcta. Observe que el entrecomillado con el smbolo de dlares es til solamente para entrecomillar texto fijo. Sera muy mala idea el tratar de hacer el ejemplo anterior como: EXECUTE UPDATE tbl SET || quote_ident(nombrecol) || = $$ || nuevovalor || $$ WHERE llave= || quote_literal(llavevalor); Debido a que podra fallar si el contenido de nuevo valor contiene $$. La misma objecin podra aplicarse a cualquier otro delimitador del tipo dlar que usara. Asi que, para entrecomillar de manera segura el texto que no conozca de inicio, debe usar quote_literal.

Estructuras de Control
Las estructuras de control son probablemente la parte ms til (e importante) de PL/pgSQL. Con las estructuras de control de PL/pgSQL puede manipular los datos de PostgreSQL de una manera flexible y poderosa. Regreso de una Funcin existen dos comandos que le permiten regresar datos desde una funcin: RETURN Y RETURN NEXT.

13

RETURN RETURN expresin; RETURN con una expresin termina la funcin y regresa el valor de expresin a quin la est llamando. Esta forma debe ser usada para las funciones PL/pgSQL que no regresan un conjunto. Cuando se regresa un tipo escalar puede usarse cualquier expresin. El resultado de la expresin ser transformado (cast) automticamente al tipo de retorno de la funcin, tal como se defini en la asignacin. Para regresar un valor compuesto (rengln) debe escribir una variable registro o rengln como la expresin. El valor de retorno de una funcin no puede quedarse indefinido. Si el control alcanza el final de bloque ms externo de la funcin sin encontrar una sentencia RETURN, se producir un error en tiempo de ejecucin. Si declar que la funcin regrese void, tambin debe proporcionar una sentencia RETURN, pero en este caso la expresin que sigue a RETURN ser opcional y ser ignorada si est presente. RETURN NEXT RETURN NEXT expresin; Cuando se declara que una funcin PL/pgSQL regrese SETOF algn tipo, el procedimiento a seguir es ligeramente diferente. En este caso, los items individuales a retornar se especifican en comandos RETURN NEXT, y despus un comando final RETURN sin argumentos se utiliza para indicar que la funcin ha terminado de ejecutarse. RETURN NEXT puede usarse con tipos escalares y compuestos; en el ltimo caso, sera regresado una tabla completa de resultados. Las funciones que usan RETURN NEXT deben se llamadas de la siguiente manera: SELECT * FROM alguna_func(); Es decir, las funciones deben se usadas como una tabla fuente en una clusula FROM. RETURN NEXT realmente no regresa de la funcin, simplemente almacena el valor de la expresin. Despus, contina la ejecucin de la siguiente sentencia en la funcin PL/pgSQL. Al ejecutarse los comandos sucesivos RETURN NEXT, se va armando el resultado. Un RETURN final, sin argumentos, ocasiona que el control salga de la funcin. La implementacin actual de RETURN NEXT para PL/pgSQL almacena el conjunto resultante completo antes de regresar de la funcin, como es explica arriba. Esto significa que si una funcin PL/pgSQL produce un conjunto resultante muy grande, el desempeo puede empobrecerse: los datos sern escritos en el disco para evitar el consumo de memoria, pero la funcin misma no regresar hasta que todo el conjunto resultante haya sido generado. Una versin futura de PL/pgSQL puede permitir a los usuarios el definir funciones que regresen conjuntos que no tengan esa limitante. Por lo pronto, el momento en que los datos empiezan a escribirse en el disco es controlado por la variable de configuracin work_mem. Los administradores que cuenten con suficiente memoria para almacenar conjuntos resultantes ms grandes en la memoria, deben considerar el aumentar este parmetro.

14

Condicionales
Las sentencias IF le permiten ejecutar comandos cuando se dan ciertas condiciones. PL/pgSQL tiene cinco formas de IF: IF ... THEN IF ... THEN ... ELSE IF ... THEN ... ELSE IF IF ... THEN ... ELSIF ... THEN ... ELSE IF ... THEN ... ELSEIF ... THEN ... ELSE IF-THEN IF expresin-lgica THEN sentencias END IF; Las sentencias IF-THEN son las formas ms simples de IF. Las sentencias entre THEN y END IF sern ejecutadas si la condicin es verdadera. De otra manera, sern ignoradas. Ejemplo: IF v_id_usuario <> 0 THEN UPDATE usuarios SET email = v_email WHERE id_usuario= v_id_usuario; END IF; IF-THEN-ELSE IF expresin-lgica THEN sentencias ELSE sentencias END IF; Las sentencias IF-THEN-ELSE aaden funcionalidad a IF-THEN permitindole especificar un conjunto de sentencias alternativo que debe ejecutarse si la condicin produce un valor de falso. Ejemplo: IF parentid IS NULL OR parentid = THEN RETURN fullname; ELSE RETURN hp_true_filename(parentid) || / || fullname; END IF; IF v_cuenta> 0 THEN INSERT INTO usuarios_cuenta(count) VALUES (v_cuenta); RETURN t; ELSE RETURN f; END IF;

15

IF-THEN-ELSE IF Las sentencias IF pueden anidarse, como se muestra en el siguiente ejemplo: IF demo_renglon.sexo = m THEN pretty_sex := hombre; ELSE IF demo_renglon.sexo = f THEN pretty_sex := mujer; END IF; END IF; IF-THEN-ELSIF-ELSE IF expresin-lgica THEN sentencias [ ELSIF expresin-lgica THEN sentencias [ ELSIF expresin-lgica THEN sentencias ...]] [ ELSE sentencias ] END IF; IF-THEN-ELSIF-ELSE proporciona un mtodo ms conveniente para revisar varias alternativas en una sentencia. Formalmente es equivalente a los comandos anidados. IF-THEN-ELSE-IF-THEN, pero solo se necesita un END IF. A continuacin en ejemplo: IF numero = 0 THEN resultado := cero; ELSIF numero > 0 THEN resultado := positivo; ELSIF numero < 0 THEN resultado := negativo; ELSE -- hmm, la nica otra posibilidad que el nmero sea nulo resultad := NULL; END IF;

16

Ciclos Simples
Con las sentencia LOOP, EXIT, WHILE y FOR, usted puede hacer que en sus funciones PL/pgSQL se repitan una serie de comandos. LOOP [<<etiqueta>>] LOOP Sentencias END LOOP; LOOP define un ciclo incondicional que se repite indefinidamente hasta que encuentra alguna sentencia EXIT o RETURN. La etiqueta opcional puede usarse por las sentencias. EXIT En los ciclos anidados para especificar que nivel de anidamiento debe terminarse. EXIT [ etiqueta ] [ WHEN expresin ]; Si no se proporciona una etiqueta se termina el ciclo ms interno y se ejecuta a continuacin la sentencia posterior a END LOOP. Si se define una etiqueta, sta debe ser la etiqueta del nivel actual o de algn otro ms externo del ciclo anidado o del bloque. Entonces, el ciclo o bloque nombrado se termina y el control contina con la sentencia posterior al END del ciclo/bloque correspondiente. Si WHEN est presente, la salida del ciclo ocurre solo si la condicin especificada es verdadera, de otra manera, el control pasa a la sentencia despus del EXIT. EXIT puede utilizarse para provocar una salida temprana de todo tipo de ciclos; no est limitado al uso de ciclos condicionales. Ejemplos:
LOOP -- algun procesamiento IF count > 0 THEN EXIT; -- salir del ciclo END IF; END LOOP; LOOP -- algn procesamiento EXIT WHEN count > 0; -- mismo resultado que en el ejemplo anterior END LOOP; BEGIN -- algn procesamiento IF stocks > 100000 THEN EXIT; -- causa la salida del bloque BEGIN END IF; END;

17

WHILE [<<etiqueta>>] WHILE expresin LOOP sentencia END LOOP; La sentencia WHILE repite una secuencia de sentencias tanto como la expresin de la condicin produzca un valor de verdadero. La condicin se revisa justo antes de cada entrada al cuerpo del ciclo. Por ejemplo: WHILE cantidad_adeudo > 0 AND balance_certificado_regalo > 0 LOOP -- algn procesamiento END LOOP; WHILE NOT expresin_lgica LOOP -- algn procesamiento END LOOP; FOR (variante con enteros) [<<etiqueta>>] FOR nombre IN [ REVERSE ] expresin .. expresin LOOP sentencias END LOOP; Esta forma de FOR crea un ciclo que itera sobre un rango de valores enteros. La variable nombre se define de manera automtica como de tipo integer y existe solo dentro del ciclo. Las dos expresiones que generan los lmites inferiores y superior del rango, son evaluados una sola vez al entrar al ciclo. El paso de la iteracin es 1 generalmente, pero es -1 cuando se especifica REVERSE. Algunos ejemplos de ciclos enteros FOR: FOR i IN 1..10 LOOP -- algn procesamiento aqu RAISE NOTICE i es %, i; END LOOP; FOR i IN REVERSE 10..1 LOOP -- algn procesamiento aqu END LOOP;

18

You might also like