Migrando de MySQL a Oracle para PHP (problemas!)

Bueno, hacía tiempo que no escribía por aquí, la verdad es que me cuesta mantener un ritmo constante, puesto que ahora que tengo un trabajo fijo (bien!?) a veces vuelvo a casa y lo último que me apetece es seguir escribiendo sobre programación, pero que os voy a contar ¿no?
En fin, volviendo al tema importante, hace unos días nos propusieron actualizar una aplicación hecha enteramente en PHP (nativo, sin ningún framework), para que soportase oracle. Bien la cosa no parecía difícil, porque esa aplicación, tenía una librería con las funciones de MySQL, por lo que sería tan fácil como duplicar esa librería y substituir las funciones por las de Oracle. Después de ver lo que había, decidimos usar la OCI8 de PHP (documentación).
Bien, este artículo no es para haceros un tutorial sobre como migrar de MySQL a Oracle, pero si que quería comentar algunos de los problemas que nos hemos ido encontrando, tanto a nivel de funciones en PHP como al migrar con SQL de una a la otra. Y ojo! Yo tuve que aprender Oracle a marchas forzadas, por lo que me considero un usuario de este gestor totalmente novato, seguramente los errores expuestos a continuación se pueden solventar de una manera quizá mas compleja y profesional, pero al menos os daré un punto de partida si estáis en los mismos problemas que yo.
Para empezar, la migración la hicimos "automaticamente" mediante SQL Developer (enlace) y estos fueron algunos de los problemas y consideraciones que nos encontramos:
1) los campos TEXT de MySQL pasan a ser objetos LOB de Oracle, por lo que a posteriori, será diferente tratarlos, ya que las consultas no nos devolverán una "string", sino que te devuelven un objeto OCILOB (documentación), que para leerlo se tendrá que hacer algo así como:
//$cad sería el valor del campo de la base de datos tipo CLOB $cad = (string)$blob->read($blob->size());
2) los campos DATE de MySQL pasan a ser TIMESTAMP con la migración automática. Remarcar que en el proceso de migración automática, estos campos fueron definidos como DATE_TIME, pero no servían dado que no guardaban la hora/minuto/segundo. Por ese motivo nos vimos obligados a realizar un script para modificar este campo en toda la base de datos.
3) en el proceso de migración no se reflejaron los valores por defecto en toda la base de datos, proceso que se ha tenido que hacer manualmente.
Tambien tuvimos algunas consideraciones y cambios sobres el conjunto de queries para el nuevo entorno Oracle:
1) no hay una función equivalente a mysql_insert_id, por lo que nosotros lo reemplazamos por una consulta a la id "MAX" para saber la última inserción. Avisaros que esta solución es realmente mala y no contempla la atomicidad de la base de datos (ni la integridad).
2) para escapar las variables, usamos algo así
//function db_escape($str) {return mysql_real_escape_string($str);}
function db_escape($str) {
// fucntion that simulates mysql_real_escape_string
if(is_array($str))
return array_map(__METHOD__, $str);
if(!empty($str) && is_string($str)) {
return str_replace(array('\\', "\0", "\n", "\r", "'", '"', "\x1a"), array('\\\\', '\\0', '\\n', '\\r', "\\'", '\\"', '\\Z'), $str);
}
return $str;
}
3) Oracle no devuelve un objeto de donde se puede sacar el número total de resultados, esto ha sido resuelto realizando una nueva query con un COUNT(*) de la última query realizada.
4) Problemas con el DISTINCT: Oracle no soporta un DISTINCT * FROM, si soporta un DISTINCT campo1,campo2,.. FROM
5) Palabras reservadas : Existen una serie de palabras reservadas en Oracle, que al realizar la migración les ha añadido una barra baja detrás, p.ej : start ⇒ start_
6) Insertar secuencias: En cada inserción de datos en la base de datos se requiere la llamada para obtener el siguiente id / número de la secuencia incremental. P.ej. INSERT INTO TABLA(ID, …) VALUES (TABLA_ID_SEQ.NEXTVAL, …)
7) Tratamiento LOB : tal y como se explica mas arriba, al hacer la migración, automáticamente se convirtieron los campos TEXT en CLOB's, que son unos objetos en oracle, por lo que antes de tratarlos como una simple string habrá que tratarlos con las funciones propias de PL*/SQL de la clase OCI-Lob Documentación de OCI-Lob
8) Concat : la función CONCAT de Oracle solo soporta dos parámetros, así que se usará esta sintaxis para más parámetros: SELECT region_name || ' ' || store_name FROM Geography WHERE store_name = 'Boston';
9) Limites: no existe LIMIT en Oracle, pero proporciona una variable en SQL llamada ROWNUM con la cual se pueden filtrar como el limit con unas comparaciones basicas, ejemplo: ROWNUM ⇐ 1 es lo mismo que LIMIT 1
Bueno y eso es todo un poco por encima de los "grandes" problemas que nos hemos encontrado.
¿Te gustó este artículo?
Aún no hay trackbacks.

6 octubre, 2011 - 01:17
SI DEFINITIVAMENTE TIENE MUCHAS VENTAJAS ORACLE, PERO PUES ASI CUESTA
ME FASCINA ORACLE, SOLO ME DESALIENTA EL COSTE
PERO TODO LO DEMAS EXCELENTE…