Desde hace años es sabido que concatenar strings con el operador + no es nada recomendable por su bajo rendimiento respecto a otras opciones. Pero la facilidad de su uso ha conseguido que a estas alturas sea la primera opción que usan muchos programadores para juntar varios strings en uno.
Si lo que estás haciendo es un programa tipo "hola mundo" no vas a notar mucha diferencia entre usar el + o no, pero cuando ya te metes en algo más serio puedes estar creando una ralentización de tu código sin saberlo y que tiene muy facil solución: NO USES EL +
La opción con mejor rendimiento es usar StringBuilder y juntar Strings mediante el método append. Pongamos un ejemplo:
String juntaletras = new StringBuilder().append("A").append("BE").append("C").toString();
Como ves tampoco te va a llevar mucho más tiempo hacerlo de esta forma y a la larga vas a salir ganando. La única pega del StringBuilder es que no es synchronized y te puedes llevar un chasco si estás usando programación recurrente multihilos. Para asegurar que tus datos no se corrompen en esos casos puedes usar sin ningún problema StringBuffer. Su uso es similiar a StringBuilder:
String juntaletras = new StringBuffer().append("A").append("BE").append("C").toString();
Cualquiera de las dos opciones mejora el rendimiento del operador + así que ante la duda puedes usar siempre StringBuffer ;)
Resoluciones de bugs y expedientes X del día a día que aparecen en tu código cuando menos te lo esperas.
miércoles, 19 de febrero de 2014
miércoles, 12 de febrero de 2014
Obtener un array de strings que vienen en un clob
Cada día me sigo sorprendiendo más y más del género humano.
Hoy me he encontrado con la necesidad de obtener un listado de dnis que vienen guardados en un clob para luego tener que recorrerlos para quedarme con los ids a los que corresponden dichos dnis.
La solución más limpia que he encontrado ha sido la siguiente:
DECLARE
dnis apex_application_global.vc_arr2;
persona_id number;
BEGIN
dnis := apex_util.string_to_table(dbms_lob.substr(:NEW.LISTADO,length(:NEW.LISTADO),1), ', ');
FOR i IN 1..dnis.count LOOP
SELECT id INTO persona_id FROM persona WHERE dnis(i) = dni;
END LOOP;
END;
Cuidado porque si el clob (:NEW.LISTADO) tiene mas de 4000 caracteres va a dar error en la función dbms_lob.substr (que pasa un clob a un varchar2). Como en mi caso se que no va a ser nunca tan grande no me he preocupado pero si no habría que evitarlo (próximamente en sus pantallas...).
Si lo usas dentro de una function o procedure entonces podrías guardar hasta 32767 caracteres en un varchar2.
La gracia del asunto es usar las librerias de apex que metieron en oracle 10, usando por un lado los vectores (apex_application_global.vc_arr2) y por otro lado apex_util.string_to_table que pasa un string a vector indicándole un separador (en mi caso era la ',').
Hoy me he encontrado con la necesidad de obtener un listado de dnis que vienen guardados en un clob para luego tener que recorrerlos para quedarme con los ids a los que corresponden dichos dnis.
La solución más limpia que he encontrado ha sido la siguiente:
DECLARE
dnis apex_application_global.vc_arr2;
persona_id number;
BEGIN
dnis := apex_util.string_to_table(dbms_lob.substr(:NEW.LISTADO,length(:NEW.LISTADO),1), ', ');
FOR i IN 1..dnis.count LOOP
SELECT id INTO persona_id FROM persona WHERE dnis(i) = dni;
END LOOP;
END;
Cuidado porque si el clob (:NEW.LISTADO) tiene mas de 4000 caracteres va a dar error en la función dbms_lob.substr (que pasa un clob a un varchar2). Como en mi caso se que no va a ser nunca tan grande no me he preocupado pero si no habría que evitarlo (próximamente en sus pantallas...).
Si lo usas dentro de una function o procedure entonces podrías guardar hasta 32767 caracteres en un varchar2.
La gracia del asunto es usar las librerias de apex que metieron en oracle 10, usando por un lado los vectores (apex_application_global.vc_arr2) y por otro lado apex_util.string_to_table que pasa un string a vector indicándole un separador (en mi caso era la ',').
lunes, 10 de febrero de 2014
Configurar timeout de arranque y parada de Tomcat en Eclipse
Se guro que la mayoría de vosotros sabéis montar un Tomcat en Eclipse (es relativamente fácil y puede que me anime a hacer un minitutorial, aunque ya los hay a patadas) así que nos vamos a poner en ese supuesto.
Le dais a correr y ... Ops! error de timeout en la inicialización!!
Al final meterle tantos frameworks, plugins y demás parafernalia al proyecto lo ha convertido en un caballo de guerra que le cuesta bastante arrancar y el tomcat por defecto del eclipse no le da tiempo a montarlo todo en 45 segundos.
No te preocupes porque puedes ir un paso más en la configuración y ajustar dicho valor.
Vas a la vista (view) de servidores (servers) y ahí tendrás tus servidores.
Haz doble click en el nombre del servidor y se abrirá una pantalla con nombre Overview.
Le das a la opción Timeouts y ahí podrás asignar libremente el valor en segundos del timeout de arranque y de parada.
¡Cuando termines no te olvides de guardar!
Le dais a correr y ... Ops! error de timeout en la inicialización!!
Al final meterle tantos frameworks, plugins y demás parafernalia al proyecto lo ha convertido en un caballo de guerra que le cuesta bastante arrancar y el tomcat por defecto del eclipse no le da tiempo a montarlo todo en 45 segundos.
No te preocupes porque puedes ir un paso más en la configuración y ajustar dicho valor.
Vas a la vista (view) de servidores (servers) y ahí tendrás tus servidores.
Haz doble click en el nombre del servidor y se abrirá una pantalla con nombre Overview.
Le das a la opción Timeouts y ahí podrás asignar libremente el valor en segundos del timeout de arranque y de parada.
¡Cuando termines no te olvides de guardar!
miércoles, 5 de febrero de 2014
Crear un sequence con el maximo id de una tabla con execute immediate
Seguimos solucionando desaguisados y nos hemos encontrado con una tabla que no tiene ningún sequence para generar ids y se estaban metiendo a pelo.
Como en los distintos entornos (desarrollo, pruebas, producción,...) la tabla en cuestión tiene distinto número de elementos y queremos una solución única para todos los entornos voy a coger el máximo valor del id de la tabla para que la sequence se quede con ese valor para generar el próximo id.
Para ello vamos a usar la función execute immediate dentro de un script que solucionará nuestros problemas.
Primero declaramos una variable integer donde guardar el max id y con una fácil select le añadimos dicho valor. Luego para crear el sequence usamos execute immediate que va a ejecutar lo que le pasemos como parámetro, así que le pasamos el código para crear la secuencia concatenando el valor obtenido antes y asunto solucionado.
Os dejo un ejemplo para que lo disfruteis:
declare
secuencia integer;
begin
select max(id)+1 into secuencia from tabla_sin_sequence;
execute immediate 'CREATE SEQUENCE SEQ_TABLA
MINVALUE 1
MAXVALUE 999999999999999999999999999
INCREMENT BY 1
START WITH ' ||secuencia ||
' NOCACHE
ORDER
CYCLE';
end;
/
Como en los distintos entornos (desarrollo, pruebas, producción,...) la tabla en cuestión tiene distinto número de elementos y queremos una solución única para todos los entornos voy a coger el máximo valor del id de la tabla para que la sequence se quede con ese valor para generar el próximo id.
Para ello vamos a usar la función execute immediate dentro de un script que solucionará nuestros problemas.
Primero declaramos una variable integer donde guardar el max id y con una fácil select le añadimos dicho valor. Luego para crear el sequence usamos execute immediate que va a ejecutar lo que le pasemos como parámetro, así que le pasamos el código para crear la secuencia concatenando el valor obtenido antes y asunto solucionado.
Os dejo un ejemplo para que lo disfruteis:
declare
secuencia integer;
begin
select max(id)+1 into secuencia from tabla_sin_sequence;
execute immediate 'CREATE SEQUENCE SEQ_TABLA
MINVALUE 1
MAXVALUE 999999999999999999999999999
INCREMENT BY 1
START WITH ' ||secuencia ||
' NOCACHE
ORDER
CYCLE';
end;
/
Suscribirse a:
Comentarios (Atom)