Sunteți pe pagina 1din 9

Estndares de programacin en PL SQL

Organizacin del cdigo


1.1Nomenclatura 1.1.1 Generalidades En la denominacin de los objetos de programacin de la base de datos es recomendable que aparezcan caracteres significativos de la aplicacin para la que se ha escrito el cdigo y caracteres identificativos de la funcin que desempean. Siguiendo estas reglas podremos identificar fcilmente el cdigo de varias aplicaciones desarrolladas en una misma instancia de base de datos, sobre todo si dependen del mismo esquema o propietario: <APLICACION>_<TIPO_DE_OBJETO>_<DESCRIPCION> Supongamos que desarrollamos la aplicacin de Gestin de Aumentos Salariales, a la que asignamos el acrnimo GAS. Los mtodos de nomenclatura seran PK PR FN<DESCRIPCION> SQ T

GAS

1.1.2 Objetos de cdigo 1.1.2.1Procedimientos Los procedimientos almacenados seguirn la nomenclatura anterior. La descripcin de los procedimientos deber contener INS, UPD, DEL, SEL como prefijo si el procedimientos de insercin de datos, actualizacin, borrado o recuperacin, seguido del nombre descriptivo de la tabla principal sobre la que se realiza la accin. En cualquier otro caso utilizaremos un nombre significativo de su funcin. Ejemplo: GAS_PR_SEL_EMPLEADOS, ser un procedimiento de la aplicacin GAS que recupera la informacin de la tabla GAS_T_EMPLEADOS. 1.1.2.2 Funciones Se aplican las mismas reglas que en el caso de procedimientos pero utilizando el identificador de funcin FN.

1.1.2.3 Packages El package siempre debe ser una entidad que engloba objetos de programacin de base de datos relacionados funcionalmente entre s. Es recomendable crear un Package para gestionar todo el mantenimiento de una tabla que se compondr tpicamente de 4 procedimientos. Insercin, Borrado, Actualizacin y Seleccin. Por ejemplo podramos crear el paquete GAS_PK_MTO_EMPLEADOS que contendr los procedimientos PR_INS_EMPLEADOS, PR_UPD_EMPLEADOS, PR_DEL_EMPLEADOS PR_SEL_EMPLEADOS
CREATE OR REPLACE PACKAGE GAS_PK_MTO_EMPLEADOS IS PROCEDURE PR_INS_EMPLEADOS; PROCEDURE PR_UPD_EMPLEADOS; PROCEDURE PR_DEL_EMPLEADOS; PROCEDURE PR_SEL_EMPLEADOS; END GAS_PK_MTO_EMPLEADOS;

En este caso hemos omitido de los procedimientos del package el prefijo de la aplicacin, GAS. Dentro de un package tambin se admite declarar los procedimientos sin hacer referencia a la tabla de mantenimiento:
CREATE OR REPLACE PACKAGE GAS_PK_MTO_EMPLEADOS IS PROCEDURE PR_INS; PROCEDURE PR_UPD; PROCEDURE PR_DEL; PROCEDURE PR_SEL; END GAS_PK_MTO_EMPLEADOS;

Con esta nomenclatura al llamar al procedure escribiramos GAS_PK_MTO_EMPLEADOS.PR_INS y queda igualmente claro que se trata del procedimiento de insercin sobre la tabla GAS_T_EMPLEADOS de la aplicacin GAS. 1.1.3 Elementos de programacin 1.1.3.1Variables Las variables vendrn precedidas por el prefijo v_ ms un identificador del tipo de dato ms un identificador significativo de la funcin que realiza. En el caso de que la variable almacene directamente el valor tipo nmero de un campo de la base de datos la denominacin de la variable ser vn_<nombre del campo>.

Ejemplo:
SELECT cod_empleado INTO vn_cod_empleado FROM gas_t_empleado WHERE

As, las variables quedaran de la siguiente manera: vn_nombre_variable, para datos tipo nmero vv_nombre_variable, para datos tipo cadena vd_nombre_variable, para datos tipo fecha vb_nombre_variable, para datos tipo boolean 1.1.3.2 Constantes Las constantes vendrn precedidas por el prefijo c_. Como en el caso de las variables cuando la constante est asociada directamente a un campo de tabla se identificar como c_ ms tipo de dato ms <nombre del campo>. Ejemplo:
SELECT cod_empleado INTO v_cod_empleado FROM gas_t_empleado WHERE cod_empleado = c_cod_empleado

cn_nombre_variable, para datos tipo nmero cv_nombre_variable, para datos tipo cadena cd_nombre_variable, para datos tipo fecha cb_nombre_variable, para datos tipo boolean 1.1.3.3 Parmetros Los parmetros en la llamada de un procedure o funcin vendrn precedidos por el prefijo p_ ms el tipo de dato ms el tipo de entrada de la variable, donde i para parmetro de entrada, o para parmetro de salida. Como en el caso de las variables cuando el parmetro est asociada directamente a un campo de tabla se identificar como p_<nombre del campo>. Ejemplo:
CREATE OR REPLACE PROCEDURE PR_DEL_EMPLEADOS (pvi_COD_EMPLEADO IN VARCHAR2) IS BEGIN DELETE FROM GAS_T_EMPLEADOS WHERE COD_EMPLEADO = pvi_COD_EMPLEADO; END;

pni_nombre_variable, para parmetros de entrada tipo nmero pvi_nombre_variable, para parmetros de entrada tipo cadena pdi_nombre_variable, para parmetros de entrada tipo fecha pbi_nombre_variable, para parmetros de entrada tipo boolean

pno_nombre_variable, para parmetros de salida tipo nmero pvo_nombre_variable, para parmetros de salida tipo cadena pdo_nombre_variable, para parmetros de salida tipo fecha pbo_nombre_variable, para parmetros de salida tipo boolean 1.1.3.4 Cursores El identificador de cursores vendr precedido por el prefijo cur_ ms un nombre aclaratorio de su funcin. Si el cursor recupera datos directamente de una tabla es recomendable escribir cur_<nombre aclaratorio de la tabla>. Ejemplo:
CURSOR cur_EMPLEADOS IS SELECT COD_EMPLEADO ,SALARIO FROM GAS_T_EMPLEADOS ORDER BY SALARIO DESC;

Si utilizamos el cursor para modificar la tabla GAS_T_EMPLEADOS podemos escribir


CURSOR cur_EMPLEADOS IS SELECT COD_EMPLEADO ,SALARIO FROM GAS_T_EMPLEADOS ORDER BY SALARIO DESC for update;

En el caso de cursores implcitos la variable de registro se escribir: rg_<NOMBRE CURSOR (SIN cur_) > 1.1.3.5 Declaracin de variables Siempre que las variables estn relacionadas con un campo de una tabla se utilizar la sentencia %TYPE. Ejemplo:
vn_COD_EMPLEADO GAS_T_EMPLEADO.COD_EMPLEADO%TYPE := '';

En cualquier otro caso los tipos de variables a utilizar deben ser: CHAR., VARCHAR2, NUMBER, BINARY INTEGER y DATE. Para las variables NUMBER siempre designaremos los dgitos significativos y la precisin:
vn_TIPO_INCREMENTAL NUMBER(5,4) := 0.0000; cn_SALARIO_INICIAL NUMBER(14,3) := 1200.000;

1.1.3.6 Inicializacin de variables Todas las variables declaradas en un procedimiento tienen que estar inicializadas en el momento de su declaracin. A las constantes se asignar su valor definitivo. En las variables actuaremos como sigue: Variables VARCHAR2: Inicializaremos a cadena vaca :=; Variables NUMBER: Inicializaremos a 0 o a otro valor significativo. Variables DATE: Inicializaremos a una fecha significativa, utilizando SIEMPRE el conversor de formato: := TO_DATE(31129999,DDMMYYYY);. Ejemplo:
vn_TIPO_INCREMENTAL NUMBER(4,3) := 0.000; cn_FECHA_MAXIMA DATE :=TO_DATE('31129999','DDMMYYYY');

vv_LITERAL_CONTRATO VARCHAR2(255) := '';

1.1.4 Comentarios 1.1.4.1 Aclaraciones Por regla general cada sentencia DML tiene que estar comentada. El comentario ser un prrafo breve y claro en el que se describa la accin realizada y el porqu de los filtros utilizados. Ejemplo:
/* SELECCIONAMOS EL SALARIO DE TODOS LOS EMPLEADOS EXCEPTO LOS DEL DEPARTAMENTO 'FI075' QUE NO ESTAN GESTIONADOS POR LA APLICACIN GAS SI NO QUE SON RESPONSABILIDAD DIRECTA DE RR.HH.*/
SELECT SALARY INTO vn_SALARY FROM GAS_T_EMPLEADOS WHERE DEPNO<> 'FI075'

1.1.4.2 Cabecera del objeto La cabecera debe contener el nombre del procedimiento o funcin, el propsito del mismo, identificador del programador, fecha de realizacin y notas aclaratorias sobre su llamada. Tambin contendr el resumen de las versiones que se realizan en el mismo.
Ejemplo:

/*-----------------------------------------------------------------NOMBRE: GAS_PR_UPD_EMPLEADOS DESCRIPCIN: ACTUALIZA LA TABLA DE EMPLEADOS Y LA TABLA DE SITUACION ACTUAL DEL EMPLEADO DE ACUERDO CONLA INFORMACIN INTRODUCIDA. LLAMADA: FECHA CREACION: 25-MAYO-2010 AUTOR : ACME REVISIONES: CODIGO FECHA AUTOR DESCRIPCION -------------*/

1.1.4.3 Correcciones Las correcciones del cdigo fuente irn siempre inventariadas en la cabecera del procedimiento. Las lneas de cdigo errneas o sustituidas no se borrarn sino que se comentarn, con el correspondiente cdigo de correccin, seguidas de las lneas corregidas.

REVISIONES:
/*CODIGO FECHA AUTOR DESCRIPCION--------- ---------- -------- --------------------------CG0302#1 23/03/2002 ACME SUSTITUIMOS EL CODIGO DE DPTONO GESTIONADO POR LA APLICACINFI075 (ERRNEO) POR F1075--------------------------------------------------------------------*/
BEGIN

SELECT SALARY INTO v_SALARY FROM GAS_T_EMPLEADOS --CG0302#1 WHERE DEPNO <> 'FI075'WHERE DEPNO <> 'F1075'--CG0302#1 SUSTITUIMOS EL DPTO

ERRONEO;

1.1.5 Reglas de codificacin 1.1.5.1 Organizacin de sentencias DML Todas las sentencias DML tendrn que ir incluidas dentro de un bloque BEGINEXCEPTIONEND, uno por sentencia. Cada bloque BEGINEND tendr asignar un valor nico dentro del programa a una variable que identifique el bloque en el que nos encontramos. Esta variable se utilizar para depuracin del programa. Ejemplo:
CREATE OR REPLACE PROCEDURE GAS_PR_EJEMPLO IS vPASO VARCHAR2(10) := '';

-- VARIABLE QUE IDENTIFICA LA SENTENCIA DML


BEGIN BEGIN vPASO= 'SELECT 1';

/* SELECCIONAMOS EL NOMCRE DESCRIPTIVO DELDEPARTAMENTO DEL EMPLEADO*/


SELECT N_COD_DEPARTAMENTO INTO vn_N_COD_DEPARTAMENTO FROM GAS_T_DEPARTAMENTOS WHERE COD_DEPARTAMENTO=vn_COD_DEPARTAMENTO; EXCEPTION WHEN NO_DATA_FOUND THEN ... WHEN TOO_MANY_ROWS THEN ... WHEN OTHERS ... END ; ... IF vn_TIPO_DEPARTAMENTO=vn_DEPRTO_ESPECIAL THEN BEGIN vPASO:= 'INSERT 1';

/* INSERTAMOS ... */

INSERT INTO... ; EXCEPTION WHEN DUP_VAL_ON_INDEX THEN ... END ; ELSE

-- NO ES UN DEPTO ESPECIAL /* BORRAMOS... */


BEGIN vPASO:= 'DELETE 1';

-- v_TIPO_DEPARTAMENTO = v_DEPRTO_ESPECIAL
... EXCEPTION ... END GAS_PR_EJEMPLO;

DELETE FROM ... ; EXCEPTION WHEN OTHERS THEN .... END ; END IF;

1.1.5.2Clusula WHERE Las variables, constantes y OUTER joins irn siempre en el lado derecho del igual = WHERE (INNER joins de tablas)A.IDX=B.IDX AND (outer joins de tablas)B.INDEX =C.INDEX (+)AND/OR (Filtro de datos)A.IDX=c_IDX 1.1.5.3 Sentencia SELECT Cada sentencia SELECT deber tener la siguiente estructura: SELECT CAMPO1 ,CAMPO2 ,CAMPO3 ,... ,CAMPOn INTO v_CAMPO1 ,v_CAMPO2 ,v_CAMPO3 , ... ,v_CAMPOn FROMTABLA1 ALIAS_TABLA_1,TABLA2 ALIAS_TABLA_2, ...,TABLA1 ALIAS_TABLA_m WHERE (inner joins de tablas) (outer joins de tablas)AND/OR (Filtro de datos)GROUP BYORDER BY HAVING START WITH CONNECT BY UNION / INTERSECT / MINUS; Observemos que recomendamos poner la coma de separacin de campos o variables antes del campo. De esta manera se disminuye el riesgo de error al aadir un nuevo campo en la sentencia. Por la misma razn el punto y coma ; final se coloca en una nueva lnea. La misma recomendacin se hace para la suma o resta de campos con el smbolo + -- 1.1.5.4 Sentencia INSERT La sentencia INSERT seguir la siguiente estructura: INSERT INTO <nombre de tabla>(CAMPO1 ,CAMPO2,CAMPO3 ,... ,CAMPOn) VALUES (v_CAMPO1,v_CAMPO2,, vCAMPOn); 1.1.5.5 Sentencia UPDATE La sentencia UPDATE seguir la siguiente estructura: UPDATE <nombre de tabla> SET CAMPO1=c_CAMPO1 ,CAMPO2=v_CAMPO2 WHERE <ClusulaWhere > ; 1.1.5.6 Sentencia DELETE La sentencia DELETE seguir la siguiente estructura: DELETE FROM <nombre de tabla>WHERE <ClusulaWhere> 1.1.5.7 Sentencia SELECT * Est prohibida. 1.1.5.8 Sentencia INSERT INTO <TABLA> SELECT * Est prohibida.

1.1.5.9 Operaciones aritmticas en SELECT Siempre que realicemos operaciones aritmticas en sentencias SELECT, bsicamente sumas, ya sea a nivel de fila o de columnas diferentes utilizaremos la funcin NVL para evitar resultados globales nulos debidos a campos particulares en nulo. Ejemplo
SELECT SUM (NVL (SALARY, 0)) INTO v_SALARIO_TOTAL FROM GAS_T_EMPLEADOS;

1.1.5.10 Cursores implcitos Siempre que sea posible escribiremos cursores implcitos, ahorrando las sentencias OPEN, CLOSE y FETCH, adems del control de datos en el cursor. De esta manera el cdigo es ms claro, rpido de codificar y ejecutar y fcil de seguir. Ejemplo
CURSOR cur_EMPLEADOS(p_COD_DEPARTAMENTO IN VARCHAR2) IS SELECT COD_EMPLEADO FROM GAS_T_EMPLEADOS WHERE COD_DEPARTAMENTO=p_COD_DEPARTAMENTO ORDER BY COD_EMPLEADO; BEGIN FOR reg_EMPLEADOS IN cur_EMPLEADOS(v_COD_dEPARTAMENTO) LOOP ... END LOOP cur_EMPLEADOS;

Observemos que la sentencia LOOP se sita en una nueva lnea debajo de FOR.En la sentencia END LOOP se etiqueta con el nombre del CURSOR. 1.1.5.11 Existencia de filas Para comprobar la existencia de una fila NO utilizaremos COUNT(*) sino o bien un bloque BEGIN...EXCEPTION...END controlando el ERROR WHEN_NO_DATA_FOUND O bien la sentencia:
V_INDICADOR := 1; BEGIN SELECT '1' INTO v_INDICADOR FROM DUAL WHERE EXISTS (SELECT COD_EMPLEADO FROM GAS_T_EMPLEADOS WHERE COD_EMPLEADO = '045A6'); EXCEPTION WHEN ... END;

1.1.5.12 SQL dinmico Para la ejecucin de sentencias DDL utilizaremos por claridad la sentencia:
EXECUTE IMMEDIATE<SENTENCIA>USING<VARIABLES HOST>;

Para la ejecucin de sentencias DML utilizaremos la utilidad DBMS_SQL siempre realizando el BIND de las variables. Con esto evitamos hacer el PARSE, que es el comando ms costoso en CPU. Ejemplo:

V_SENTENCIA := 'SELECT SALARY FROM GAS_T_EMPLEADOS WHERE COD_EMPLEADO= :COD_EMPLEADO'; DBMS_SQL.define_column(source_cursor, 1,v_SALARIO); DBMS_SQL.PARSE(source_cursor, v_SENTENCIA, DBM_SQL.NATIVE); FOR reg_EMPLEADOS IN cur_EMPLEADOS LOOP DBMS_SQL.BIND_VARIABLE(source_cursor, ':COD_EMPLEADO',reg_EMPLEADOS.COD_EMPLEADO); v_ROWS := DBMS_SQL.EXECUTE_AND_FETCH(source_cursor); END LOOP cur_EMPLEADOS;

1.1.5.13 Control de Errores El control de errores se realiza de manera diferente si se trata de un programa en tiempo real que un programa por lotes. En el primer caso se puede utilizar la utilidad RAISE_APPLICATION_ERROR siempre dentro de un bloque EXCEPTION, si se trata de errores en la sentencia DML. En todo caso el texto del RAISE_APPLICATION_ERROR deber contener: Descripcin del error, parmetro nico de la sentencia en la que se ha producido el error, accin correctiva, cdigo nativo de error, SQLCODE. Previamente se realizar un ROLLBACK de la accin. En el caso de programas BATCH el error se enviar a un procedure de tratamiento de errores. Ejemplo:
EXCEPTION WHEN OTHERS THEN ROLLBACK; GAS_PR_ERRORES (v_PROCEDURE_NAME,SQLCODE,SQLERRM,v_SENTENCIA_ERROR, USER); RETURN; END;

S-ar putea să vă placă și