lunes, 2 de octubre de 2017

Oracle SQL Developer 17.3 disponible




La nueva release trimestral de SQL Developer fue liberada el viernes pasado, y se encuentra disponible para descargar aquí.

Conjuntamente con SQL Developer, se encuentra disponible como descarga adicional SQLcl, la herramienta de linea de comando que reemplaza a SQL*Plus.

Oracle 12c R2 - LISTAGG y OVERFLOW

En Oracle 11gR2 se introdujo una nueva función analítica, LISTAGG, la cual ordena los datos dentro de cada grupo especificado en la cláusula ORDER BY y luego concatena los valores de la columna o expresión seleccionados.

Por ejemplo, si queremos obtener una lista de las tablas a las que tenemos acceso, junto con una lista de todas las columnas, ordenadas por nombre de columna, de cada una de tablas, podemos ejecutar la siguiente consulta:

SELECT table_name,
       LISTAGG(column_name, ',') WITHIN GROUP 
                  (ORDER BY column_name) Columns
FROM all_tab_cols
GROUP BY table_name;

Lo cual produce el siguiente resultado:


Pero el problema surge cuando la lista concatenada de valores supera el tamaño máximo que el lenguaje SQL soporta en Oracle, el cual es 4000 bytes. En el ejemplo, siguiente, repetimos 50 veces los datos para aumentar el tamaño del resultado de LISTAGG, obteniendo el siguiente error:

SELECT table_name,
       LISTAGG(column_name, ',') WITHIN GROUP 
                  (ORDER BY column_name) Columns
FROM all_tab_cols
    CROSS JOIN (SELECT level FROM dual CONNECT BY level <=50)
GROUP BY table_name;

ORA-01489: result of string concatenation is too long
01489. 00000 -  "result of string concatenation is too long"
*Cause:    String concatenation result is more than the maximum size.
*Action:   Make sure that the result is less than the maximum size

Oracle 12cR2 introduce una sintaxis ampliada para la función LISTAGG, la cual nos permite obviar el error, mostrando sólo los primeros 4000 bytes que la función obtiene, sin producir un error, como podemos ver a continuación (aquí "cortamos' la cadena concatenada en dos pedazos para poder ver el principio y fin de la misma):

SELECT x.table_name,
       SUBSTR(LISTAGG(x.column_name, ',' ON OVERFLOW TRUNCATE) 
            WITHIN GROUP (ORDER BY x.column_name),1,30) AS "Comienza con...",
       SUBSTR(LISTAGG(x.column_name, ',' ON OVERFLOW TRUNCATE)
            WITHIN GROUP (ORDER BY x.column_name),-30) AS "Termina con..."
FROM all_tab_cols x
    CROSS JOIN (SELECT level FROM dual CONNECT BY level <=50)
GROUP BY x.table_name;




Como vimos en el ejemplo anterior, la opción "ON OVERFLOW TRUNCATE" por defecto corta el resultado hasta el valor anterior cuyo tamaño no exceda los 4000 bytes, agrega "..." a continuación del último valor que puede ser mostrado, y luego muestra entre paréntesis la cantidad de caracteres que fueron truncados.

Podemos reemplazar los puntos suspensivos con cualquier cadena que deseemos utilizar como indicador para informar que el texto ha sido truncado, de la siguiente forma:

ON OVERFLOW TRUNCATE '///'

Tambien podemos indicarle que no deseamos saber el numero de caracteres truncados, de la siguiente forma:

ON OVERFLOW TRUNCATE WITHOUT COUNT


La sintaxis completa de la función LISTAGG en oracle 12c Release 2 puede encontrarse aqui.

miércoles, 27 de septiembre de 2017

Oracle Application Express 5.1.3.00.05 disponible para descargar



Ya se encuentra disponible la última versión de APEX (5.1.3.00.05) en el sitio de descargas de Oracle.


La misma fue liberada en el día de ayer.

Mas información y toda la documentación sobre APEX en el sitio oficial de Oracle.

lunes, 25 de septiembre de 2017

Oracle 12c R2 - Utilizar Constantes para definir el tamaño de Variables

Es común encontrar en nuestras aplicaciones, lugares donde accedemos a tablas o vistas diccionario de datos de Oracle para obtener cierta información, por ejemplo:

SELECT t.table_name
INTO vTabla
FROM user_tables t
WHERE t.table_name like ‘T_%’

El tamaño máximo de los indicadores era, hasta Oracle 12c R2, de 30 caracteres, por lo que es frecuente encontrar que se definía a la variable “vTabla” de la siguiente forma:

DECLARE
    vTabla    VARCHAR2(30);

Pero, como ya vimos en el artículo anterior del blog, "Oracle 12c R2 - Identificadores de 128 Bytes", la Release 2 de Oracle 12c nos permite definir indicadores de hasta 128 caracteres de largo, por lo que es probable que nuestras aplicaciones que definían variables para almacenar indicadores con un largo fijo de 30 caracteres muy pronto comiencen a fallar con el siguiente error:

ORA-06502: PL/SQL: numeric or value error: character string buffer too small

Afortunadamente, el cambio  en el tamaño de los indicadores viene acompañado en Oracle 12c R2 de la posibilidad de declarar el largo de variables usando constantes. Por ejemplo, podemos definir un paquete de constantes y especificar en el mismo los valores que deseamos utilizar:

CREATE OR REPLACE PACKAGE pkg_constantes
AS
  --
  cn_largo_identificadores  constant pls_integer := 128;
  cn_largo_codigos          constant pls_integer := 20;
  cn_largo_cuit             constant pls_integer := 11;
  --
END pkg_constantes;
/

Y luego utilizar los mismos al momento de definir variables:

declare
  vNombreTabla     VARCHAR2(pkg_constantes.cn_largo_identificadores );
  vCUIT           NUMBER(pkg_constantes.cn_largo_cuit);
  vCodigoCliente  VARCHAR2(pkg_constantes.cn_largo_codigos);

Para simplificar nuestra tarea, la versión 12c R2 ya provee una constante declarada en el paquete “DBMS_STANDARD” llamada “ORA_MAX_NAME_LEN” la cual representa un valor de 128, por lo que nuestro primer ejemplo puede ser reformulado de la siguiente forma:

DECLARE
    vTabla   VARCHAR2(ORA_MAX_NAME_LEN);

Ejemplo y documentación adicional 



lunes, 18 de septiembre de 2017

Oracle 12c R2 - Identificadores de 128 Bytes

Seguramente, mas de una vez cada desarrollador o administrador de Oracle sufrió un dolor de cabeza al tener que crear un objeto y encontrarse con la limitación de treinta caracteres para los nombres de objetos (identificadores).

Por ejemplo, si queríamos correr el siguiente script:

CREATE TABLE t_EstadoComprobante
( ID_EstadoComprobante      NUMBER(4)       NOT NULL,
  EstadoComprobante         VARCHAR(50)     NOT NULL
);
--
ALTER TABLE t_EstadoComprobante
    ADD CONSTRAINT PK_EstadoComprobante
        PRIMARY KEY (ID_EstadoComprobante);
--
CREATE TABLE t_Comprobante
( ID_Comprobante            NUMBER(4)       NOT NULL,
  Numero_Comprobante        NUMBER(8)       NOT NULL,
  Fecha_Comprobante         DATE            NOT NULL,
  Monto_Comprobante         NUMBER(12,2)    NOT NULL,
  ID_EstadoComprobante      NUMBER(4)       NOT NULL
);
--
ALTER TABLE t_Comprobante
    ADD CONSTRAINT PK_Comprobante
        PRIMARY KEY (ID_Comprobante);
--
ALTER TABLE t_Comprobante 
    ADD CONSTRAINT FK_Comprobante_EstadoComprobante 
        FOREIGN KEY (ID_EstadoComprobante)
        REFERENCES t_EstadoComprobante (ID_EstadoComprobante);
--

Nos encontrábamos con el siguiente mensaje de error.

ORA-00972: identifier is too long
00972. 00000 -  "identifier is too long"
*Cause:    An identifier with more than 30 characters was specified.
*Action:   Specify at most 30 characters.

La limitación de 30 caracteres obligaba a utilizar abreviaturas para nombrar a identificadores, haciendo poco legibles (y hasta inentendibles) ciertos nombres.

Identificadores Largos (hasta 128 bytes) en Oracle 12c R2

La nueva versión de Oracle soporta identificadores de hasta 128 bytes, por lo que de ejecutar el script anterior en una base de datos 12c R2, obtendremos el siguiente resultado:

Table created.
Table altered.
Table created.
Table altered.
Table altered.
Si consultamos la estructura de las tablas del diccionario de datos, podemos ver que la mayoria de las columnas de las vistas del diccionario de datos que contienen identificadores ahora tienen un tamaño de 128 bytes:

SQL> desc all_tables
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 OWNER                                     NOT NULL VARCHAR2(128)
 TABLE_NAME                                NOT NULL VARCHAR2(128)
 TABLESPACE_NAME                                    VARCHAR2(30)
 CLUSTER_NAME                                       VARCHAR2(128)
 ...
 ...

Restricciones y Consideraciones

Los siguientes objetos mantienen sus identificadores con el largo como en versiones anteriores.
  • 8 Bytes
    • Nombre de Base de Datos
  • 30 Bytes
    • Tablespace
    • Disk Group
    • PDBs
    • Rollback Segment
Otro aspecto a tener en cuenta es que el nuevo tamaño se mide en Bytes, por lo que si nuestra base de datos tiene un set de caracteres UTF8, cada caracter puede ocupar entre 1 y 3 bytes, por lo que el tamaño máximo en caracteres del identificador puede ser menor, como vemos a continuación:

create table tablááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááá 
(
  Son_67_Caracteres_pero_ocupan_130_bytes int
);

ORA-00972: identifier is too long