Compatibilidad entre MySQL y SQLite

Iniciado por WHK, 9 Diciembre 2009, 21:05 PM

0 Miembros y 1 Visitante están viendo este tema.

WHK

Hola, estoy haciendo un par de funciones para poder manipular mysql y sqlite desde un solo lado tratando de compatibilizar a ambos y seleccionando el uso de cada uno según el archivo de configuraciones pero tengo un par de problemas ya que como todos saben sqlite no trabaja igual que mysql.

El problema que tengo es justamente ese, tratar de compatibilizar las funciones y necesito encontrar algunos reemplazos.

El primer problema es que no puedo listar tablas con show desde sqlite tal como puedo hacerlo en mysql para poder crear el instalador y verificador de integridad de la base de datos.
En mysql hago esto:
Código (php) [Seleccionar]
$query = "SHOW TABLE STATUS LIKE 'xxx'";

Como puedo encontrar un reemplazo en sqlite?

Otro problema es que en mysql si haces un update a columnas que no existen dentro de una tabla entonces la función te los creará de forma automática evitando tener que cargar desde cero la base de datos nueva y lo hago así:
Código (php) [Seleccionar]
$query = "ALTER TABLE tabla ADD columna tipo";

Pero en Sqlite no existe el "alter" por lo tanto no puedo agregar nuevas columnas y si por x motivo despues del desarrollo de mi aplicacion quiero insertarle una columna mas tendria que pasar toda la tabla a una variable temporal en php o a un archivo serializado y crear la tabla nuevamente con las nuevas columnas y volver los datos guardados a la tabla y es demasiado trabajo para el servidor si es que llega a ser demasiado grande.

Otro problema que tengo aunque no es tan significativo es la busqueda con like %$% ya que las busquedas son cas sensitive no como mysql por lo cual las busquedas por el lado del visitante son demasiado inexactas ya que debería atinarle a las mayusculas.
Habría alguna forma de prevenir este problema tal como lo hace mysql emulando alguna función sin tener que utilizar un select * a toda la base de datos para comparar con strtolower?

Gracias.

seba123neo

¿y porque desde un administrador de SQL LIte 3 puedo hacer un Alter Table? , para listar las tablas en la pagina de SQL Lite dice:

Código (sql) [Seleccionar]
SELECT name FROM sqlite_master
La característica extraordinaria de las leyes de la física es que se aplican en todos lados, sea que tú elijas o no creer en ellas. Lo bueno de las ciencias es que siempre tienen la verdad, quieras creerla o no.

Neil deGrasse Tyson

WHK

#2
Bueno, sería lo mismo que hacer un select * from schema en mysql pero igual me sirve ;) , yo habia hecho un select * con limit 1 a la tabla y si daba error era porque no existía la tabla :P pero aun así me faltaban los datos del tipo de tabla pero ya con esto me basta.

El alter table no se como lo voy a solucionar :-/ hacer un dump y un import sería una tontera.

Ahora estaba haciendo una prueba para poder hacer un control interno de errores y responder con una acción diferente por cada error pero en todos los errores me devuelve un estado igual a uno:

Código (php) [Seleccionar]
$handle = sqlite_open('x.db', 0666);
$query = 'insert into xxx (id, data, nada) values (\'2\', \'WHK\', \'nono\')';
if($data = sqlite_query($handle, $query)){
while($fila = sqlite_fetch_array($data, SQLITE_ASSOC)){
 $retorno[] = $fila;
}
print_r($retorno);
}else{
echo sqlite_error_string(sqlite_last_error($handle));
}


La idea era que con sqlite_last_error() podría obtener el id de error y predecir si la tabla le falta una columna ya que en ese ejemplo solamente estaba la columna id y data pero me devuelve un uno igual que cualquier error que intento forzar. No se si sea por alguna mala configuración de mi servidor o no se, no quiero hacer doble query para verificar si la columna existe o no aunque despues de eso tendré que ver como hacer para insertarle una nueva columna xDDD

seba123neo

proba hacer:

Código (sql) [Seleccionar]
PRAGMA TABLE_INFO(TuTabla)

con eso obtengo los nombres de los campos, los tipos de datos de cada uno..etc... ;D
La característica extraordinaria de las leyes de la física es que se aplican en todos lados, sea que tú elijas o no creer en ellas. Lo bueno de las ciencias es que siempre tienen la verdad, quieras creerla o no.

Neil deGrasse Tyson

WHK

Bueno ya lo solucioné, simplemente no le di soporte a la función para que modificara columnas si se está utilizando sqlite xD

^Tifa^

No trabajo con php (Si tu codigo es PHP) pero si con otros lenguajes scripting similares y con modulos o API C de mysql para el lenguaje correspondiente.

Tu sabes que cada modulo posee su correspondiente manejador de errores, en PHP por ejemplo para MySQL existe:

int mysql_errno(expresion)
Esta funcion (Que me parece que es la que buscas pero para SQLite) retorna el valor numerico del error en cuestion (Aunque desconozco si es el mismo valor del SQLSTATE error que lanza el motor de DB por cada accion de error), o si sencillamente retorna el valor numerico de error correspondiente a la funcion siguiente:

string mysql_error(expresion)
Esta funcion, presenta en pantalla el error retornado pero a modo texto...

Tu estas usando:

sqlite_error_string(sqlite_last_error($handle));

No programo en PHP que conste, pero como te dije estas llamando a la funcion string error en vez del int error, averigua cuantos error handling para SQLite posee el modulo de sqlite para PHP y como se llaman cada uno (Ya que pueden ser 2 como pueden ser mas).

Si lo anterior no te conviene o no encuentras una solucion, puedes optar por crear funciones almacenadas dentro de SQLite, y que estas te retornen 1 valor acorde a cada error que quieras utilizar para lanzar tu mensaje. Asi si usas funciones y le pasas X parametro sino encuentra lo que busca puedes dar uso de los errores SQLSTATE del motor y retornar acorde a X valor dentro de la funcion, y ese valor puedes usarlo en tu codigo como quieres hacer y por cada error lanzar un mensaje distinto... no se si me explico  :-\

Suponte que dentro del motor SQLite haces una funcion almacenada mas o menos asi:

create function ejemplo(parametro in char)
begin
select * from parametro;
exception:
when 4095 then
return 1
when 4096 then
return 2
end;

Donde supongamos que 4095 es el SQLSTATE error cuando no existe una tabla, y el 4096 es el SQLSTATE error de digamos no tienes permisos para ver esta tabla por ejemplo.

Y suponte que en tu codigo php tienes algo asi:

case 1 :
echo "No existe la tabla"
break;
echo 2 :
echo "No tienes permisos de lectura en esa tabla"
break;

PD: Se que la sintaxis de ambos ejemplos esta pesima, es un mero ejemplo y no corresponde a un lenguaje de programacion real. Espero que se entienda mas o menos lo que intento exponer.

WHK

Si esa era la idea y de esa forma lo hago en mysql pero en sqlite la función que retorna el id de error es sqlite_last_error() que debería devolver un integer y de paso le agrego sqlite_error_string() para comprobar el tipo de error pero el error es siempre uno sea cual sea y ese era mi problema, no puedo saber si el error fue una cosa u otra para recién comenzar a hacer el switch o el if elseif.

Pero bueno, no se que sea pero ya adapté casi todo para no utilizar ese tipo de control de errores, simplemente en sqlite utilizaré bases de datos estáticas y en mysql bases de datos dinámicas.

Alter table si lo spoprtaba sqlite pero a partir de la versión 3 y la mayoría de los hostings y app servers utilizan uno o dos como mucho en su versión.

^Tifa^

#7
Podrias obviar en este caso sqlite_error_string() y solamente utilizar sqlite_last_error() que te retorna el valor en numero del error SQLSTATE del motor, haz tratado algo como:

Código (php) [Seleccionar]


if ((sqlite_last_error($handle) == 4095 ) {

 echo "Error no existe la tabla seleccionada\n";

} elsif ((sqlite_last_error($handle)) == 4096 ) {

 echo "Error no tienes permiso de lectura en la tabla\n";

}



Donde 4095, 4096 son ejemplos de errores SQLSTATE del motor en cuestion... Ahora si solo te interesa imprimir el error de forma caracteres, no lo he hecho en PHP pero en Perl por ejemplo se haria asi:

Código (perl) [Seleccionar]


my $consulta = $conexión->prepare( qq{ SELECT * FROM tabla } );
$consulta->execute() or warn $conexión->errstr;



En lo anterior cuando se ejecuta la consulta si es efectivo obvia el warn sino es efectivo (Si no se cumple es false) entonces se ejecuta el $conexión->errstr y sale en pantalla el error que lanza el motor :

'Error table not found'  por ejemplo. No se como se haga en PHP esta situacion, pero no debe ir muy lejos. Haz intentado con:

Código (php) [Seleccionar]


$handle = sqlite_open('x.db', 0666);
$query = 'insert into xxx (id, data, nada) values (\'2\', \'WHK\', \'nono\')';
$data = sqlite_query($handle, $query) or die sqlite_error_string;

if ($data){
while($fila = sqlite_fetch_array($data, SQLITE_ASSOC)){
 $retorno[] = $fila;
}
print_r($retorno);
}



Sino aun tienes la opcion de las funciones almacenadas dentro del motor, no son tan dificiles  ;)  y suele ser hasta mas seguro para este tipo de aplicaciones.

sirdarckcat

bueno, acabo de ver el tema.. por si alguien mas tiene la misma duda.

para agregar una columna a una tabla de sqlite, puedes hacer:

create table nueva (con nueva estructura);
insert into nueva (columnas) values (select columnas from vieja);
drop table vieja;
alter table nueva rename to vieja;

y ya xD

Saludos!!