Ver índice
PDO – Bases de datos SQLite / MySQL

        Ocultar índice  

   Índice de contenidos
   Instalación en Windows
   Instalación en Ubuntu
   Servidores seguros
   Páginas dinámicas
   Sintaxis básica
   Operaciones
   Arrays
   Formatos de presentación
   Operadores
   Bucles
   Extraer y ord. información
   Funciones
   Ficheros externos
   Imágenes dinámicas
   Gestión de directorios
   Cookies y sesiones
   Clases y objetos
   Ficheros en formato PDF
   Bases de datos MySQL
   PHP y XML
   PDO - Bases SQLite / MySQL
   MySQL a traves de misqli
   Algo de JavaScript y AJAX


Bases de datos SQLite

SQLite es una librería que permite gestionar bases de datos SQL sin necesidad de tener instalado un servidor como requieren MySQL y otros gestores. Ello significa que en la mayoría de los casos la gestión de bases de datos personales podría realizarse sin necesidad de instalar ningún servidor adicional a Apache + PHP.

Una base de datos SQLite es simplemente un fichero cuyo nombre y extensión podemos asignar con total libertad y que puede estar alojado en cualquier directorio de nuestro servidor PHP con la única condición de que ese directorio –en el caso de trabajar sobre Ubuntu– tenga permisos de escritura.

Aunque PHP dispone de todo un conjunto de funciones específicas para las bases de datos SQLite similares a las vistas para el caso de MySQL nosotros vamos a ver la forma de gestionar bases de datos (tanto SQLite como MySQL) de un modo distinto. Lo haremos por medio de la extensión PDO de PHP.

De esta forma, además de familiarizarnos con el manejo de las bases de datos SQLite, conoceremos una forma alternativa de gestionar MySQL. Es por ello que a lo largo de esta página y las siguientes nos referirmos con frecuencia a ejemplos, situaciones y operaciones ya estudiadas en MySQL. Ahora trataremos de hacer algo muy similar a aquello pero utilizando de forma exclusiva la extensión PDO.

PDO - PHP Data Objects

PHP Data Objects (PDO) es una extensión de PHP para la formalización de las conexiones de PHP con una de base de datos por medio de una interfaz uniforme. PDO proporciona una capa de abstracción de acceso a datos, que significa que, se utilizarán las mismas funciones para la gestión de las bases de datos con independencia del tipo de base que estemos utilizando.

Ello significa que, con muy ligeras modificaciones, un mismo script podría gestionar diferentes tipos de bases de datos tales como: SQLite, MySQL, Postgres, Oracle ó Firebird.

Configuración de PHP

El uso de PDO requiere el uso de una extensión específica de PHP para cada uno de los tipos de bases de datos que pretendamos gestionar. En nuestro caso vamos a manejar MySQL y SQLite lo que requiere que, bajo Windows, usemos las extensiones extension=php_pdo_sqlite.dll y extension=php_pdo_mysql.dll Habremos de editar el fichero php.ini, buscar esas dos extensiones, descomentarlarlas (quitar el punto y coma que llevan delante), guardar los cambios y reiniciar el servidor.

Cuando se trata de Ubuntu es preciso realizar la siguiente instalación:


sudo apt-get install php5-sqlite

con lo cual, en cualquiera de los dos casos, una vez reiniciado el servidor la página http://localhost/info.php debería mostrarnos una información similar a esta:

Gestión de bases de datos SQLite y MySQL mediante PDO

Dada la gran similitud entre los procedimientos (esa es una de las ventajas de utilizar PDO) vamos a intentar ir viendo de forma simultánea el uso de este interface tanto para SQLite como para MySQL. Lo iremos haciendo en distintos epígrafes procurando mostrar las afinidades y diferencias.

Después de haber visto el tema relativo al manejo de clases y objetos y la aplicación de la clase TCDF para la gestión de ficheros PDF te resultará fácil y familiar el manejo del PDO ya que lo que haremos en estos temas será manejar objetos de la clase PDO.

Aunque iremos viendo los diferentes métodos de esta clase tiene particular interés que empecemos conociendo un los más importantes:

$objeto->query(SENTENCIA)

que permite ejecutar cualquier SENTENCIA SQL sobre el $objeto sea cual fuere el tipo de base de datos en uso. Quiere ello decir que usaremos este mismo método para cualquier proceso de: creación, modificación, baja, o consulta de bases datos y tablas.

Creación de bases y/o acceso a bases de datos

Creación y/o conexión a una base de datos SQLite

Requiere únicamente la creación de un objeto PDO con la siguiente sintaxis:

$objeto= new PDO ('sqlite: fichero ')

dónde $objeto es el identificador de un nuevo objeto, sqlite: es una palabra reservada y obligatoria que especifica el tipo de base de datos y fichero es la ruta y nombre de un fichero destinado a guardar la nueva base de datos. Si el fichero no existe se crearía uno nuevo y en caso de que ya existiera no se sobreescribiría manteniendo toda la información que pudiera contener.

En este ejemplo puedes ver la forma de crear bases de datos SQLite. Si lo ejecutas podrás ver que se han creado los dos ficheros en los directorios indicados y que, su longitud es cero bytes. Es lógico que así sea ya que aún no contienen información alguna.

 <?php
 /* creamos un objeto PDO con el nombre $dbSQLite.
  Es importante que el parámetro que se incluye comience por sqlite:
   (esa palabra es la indica el driver debe utilizar PHP para gestionar
    la base de datos es SQLite)y a continuación la cadena con la ruta
    y nombre del fichero que contendrá la base de datos */
 $dbSQLite= new PDO('sqlite:./images/baseSQLite.zpq');
/* una opción un poco más sofisticada podría utilizar una función
   y devolvernos un mensaje de confirmación o de error. */
   function conecta($nombre){
    if ($db = new PDO('sqlite:'.$nombre)){
        print "Creado o abierto el fichero SqLite: ".$nombre.'<br />';
        return($db);
   } else {
       print "Error: No puede conectarse con la base de datos.<br />";
        print "<br />".$db->errorInfo()."<br />";
        exit();
    }
}
/* si hacemos una llamada a esta función pasándole como parámetro
   el nombre de la base de datos y (opcionalmente) la ruta
   habremos creado un nuevo objeto y un nuevo fichero de base de datos */
$dbSQLite1= conecta('practicar');
/* destruimos el objeto con ello desconectamos de la base de datos */
   $dbSQLite1=NULL;
   $dbSQLite=NULL;
/* destruimos los objetos (la conexión) pero los ficheros se mantienen*/
?>
ejemplo482.php
  ¡Cuidado!  

Es importante elegir un lugar adecuado para almacenar las bases de datos SQLite. Al tratarse de un único fichero si lo dejamos dentro del directorio raíz (htdocs en la configuración aquí descrita) o en uno de sus directorios es obvia su vulnerabilidad. Fíjate que este enlace http://www.rinconastur.net/php/ejemploSQLite permite descargar sin problema alguno la base de datos SQLite que hemos incluido como ejemplos. Además, al carecer de contraseña, los datos que contiene son totalmente accesibles.
La forma de evitar –o al menos paliar– ese riesgo sería almacenar este fichero fuera del document_root (htdocs) de la misma forma que hacíamos con las contraseñas de acceso a MySQL

Creación y conexión con una base de datos MySQL

Utilizando la clase PDO el acceso a una base de datos MySQL (como es lógico, el servidor de bases de datos MySQL tiene que estar activo) requiere únicamente la creación de un objeto PDO con la siguiente sintaxis:

$objeto= new PDO ("mysql: servidor " ,usuario,contraseña )

dónde $objeto es el identificador de un nuevo objeto, mysql: es una palabra reservada y obligatoria que especifica el tipo de base de datos, servidor es una cadena formada por: host=nombre_del_servidor_MySQL (en nuestro caso localhost), usuario el nombre de usuario (pepe en el caso de nuestros ejemplos) y contraseña (la contraseña de usuario, pepa en nuestro caso).

La cadena que estamos señalando como servidor admite una opción un poco más amplia que tendría la forma: host=nombre_del_servidor_MySQL ; dbname=nombre_de_la_base_de_datos. En ese caso el objeto devuelto sería la conexión al servidor MySQL y el acceso a la base de datos señalada mediante nombre_de_la_base_de_datos. Sería una situación equivalente a la resultante del uso de mysql_select_db cuando usábamos las funciones MySQL de PHP.

En este ejemplo puedes ver la forma de acceder a bases de datos MySQL. Por mantener el paralelismo con SQLite nos hemos visto obligados a incluir dos pasos. En el primero se comprueba la existencia de la base de datos y se crea si no existera. En el segundo se produce el acceso a la propia base de datos.

<?php
    function conecta($base){
     $db = new PDO('mysql:host=localhost','pepe','pepa');
     /* crea la base de datos si no existe */
     $db->query("CREATE DATABASE IF NOT EXISTS  ".$base);
     /* crea un nuevo objeto usando la base de datos pasada como
        parámetro sin riesgo de error por inexistencia de la base */
     if($db1 = new PDO('mysql:host=localhost;dbname='.$base,'pepe','pepa')){
      print "Creado o abierta la base de datos MySQL: ".$base.'<br />';
        return($db1);
   } else {
       print "Error: No puede conectarse con la base de datos.<br />";
        print "<br />".$db1->errorInfo()."<br />";
        exit();
    }
}
/* Hacemos una llamada a esta función pasándole como parámetro
   el nombre de la base de datos */
$dbSQLite1= conecta('practicar'); 

?>
ejemplo483.php
  ¡Cuidado!  

Presta atención a la sintaxis sin olvidar la correcta ubicación de las comillas.
$objeto=new PDO ("mysql:host=localhost","pepe","pepa") o
$objeto=new PDO ("mysql:host=localhost; dbname=ejemploSQLite", "pepe", "pepa") sería la sintaxis válida.
Utiliza siempre comillas dobles (estas " ") en este tipo de sentencias. Si los nombres de bases de datos, usuarios, host y/o contraseñas proceden de variables la sintaxis que deberás utilizar será esta:

new PDO("mysql:host=$host;dbname=$base_datos",$usuario,$password)

Unificación del proceso de conexión

Nuestro propósito es ir desarrollando, de forma simultánea, ejemplos con ambas bases de datos. Eso no requerirá manejar, en paralelo, objetos de ambos tipos. Para facilitar un poco las cosas,en el ejemplo siguiente veremos como unificar en una sola función los procesos de conexión a ambas bases de datos.

De esa forma, modificando un solo parámetro, podríamos crear indistintamente objetos de uno u otro tipo.

<?php
function conecta($base,$tipo){
    if ($tipo=='MySQL'){
            $db = new PDO('mysql:host=localhost','pepe','pepa');
            /* crea la base de datos si no existe */
            $db->query("CREATE DATABASE IF NOT EXISTS  ".$base);
            /* crea un nuevo objeto usando la base de datos pasada como
                parámetro sin riesgo de error por inexistencia de la base */
            if($db1 = new PDO('mysql:host=localhost;dbname='.$base,'pepe','pepa')){
                    print "Creado o abierta la base de datos MySQL: ".$base.'<br />';
                    return($db1);
             } else {
                    print "Error: No puede conectarse con la base de datos.<br />";
                    print "<br />".$db1->errorInfo()."<br />";
                    exit();
            }
    }
    if ($tipo=='SQLite'){
            if ($db = new PDO('sqlite:'.$base)){
                    print "Creado o abierto el fichero SqLite: ".$base.'<br />';
                     return($db);
            } else {
                    print "Error: No puede conectarse con la base de datos.<br />";
                     print "<br />".$db->errorInfo()."<br />";
                    exit();
            }
    }
}
/* Hacemos una llamada a esta función pasándole como parámetros nombre de la base de datos y tipo*/
$dbDual= conecta('practicar','MySQL'); 
?>
Caso MySQL Caso SQLite

Desconexión de una base de datos SQLite

Aunque en SQLite no cabe hablar de desconexión, utilizaremos esa palabra por similitud con lo visto para MySQL. En este caso lo que llamaremos desconexión no será otra cosa que la destrucción del objeto creado a acceder. Para ello bastaría con escribir:

$objeto= NULL

En cualquier caso resulta innecesario. En PHP los objetos se destruyen al finalizar la ejecución del script mediante el que han sido creados.

Borrar bases de datos SQLite

Como quiera que una base de datos SQLite no es otra cosa que un fichero, para eliminarla sería suficiente borrar tal fichero mediante la función PHP:

unlink(nombre_del_fichero)

Cuando se trata de eliminar bases de datos (como es lógico se eliminarían las eventuales tablas e información que pudiera contener) basta proceder de igual forma que para borrar cualquier otro fichero.

<?php
/* borramos las bases de datos creadas en el ejemplo anterior */
unlink('./images/baseSQLite.zpq');
unlink('practicar');
?>
ejemplo486.php

Borrar bases de datos MySQL

Cuando se trata de borrar bases de datos MySQL se utiliza el método:

$objeto->query(DROP DATABASEnombre_de_la_base)

como verás la sentencia SQL es la que hemos manejado con anterioridad y que puedes recordar en desde este enlace. El ejemplo siguiente contiene un script que borra la base de datos MySQL creada en los ejemplos anteriores.

Ver código fuente

Formas de almacenamiento de SQLite

A diferencia de MySQL, SQLite maneja solamente cinco formas de almacenamiento:

En cualquier caso SQLite es extremadamente flexible en este sentido. Cualquier campo, con excepción de los definidos como INTEGER PRIMARY KEY, puede utilizarse para almacenar un valor de cualquier tipo.

SQLite no dispone de un tipo específico para almacener fechas. Sin embargo dispone de fuciones internas permiten tratar datos de fecha y hora a partir de los siguientes formatos:

Parámetros de los campos

Además del nombre de campo y la declaración de tipo de datos, SQLite permite incluir opcionalmente unos parámetros adicionales similares a los utilizados por MySQL. Entre ellos los siguientes: PRIMARY KEY, UNIQUE, INTEGER PRIMARY KEY, CHECK, NOT NULL, DEFAULT, AUTOINCREMENT.

La diferencias más sustanciales respecto a MySQL son estas:

  ¡Cuidado!  

SQLite ignora los valores que se trate de asignar al tamaño del campo. SQLite no impone ninguna limitación en el tamaño de un campo siempre que no sobrepase el valor máximo preestablecido que está establecido en 109 bytes.

Flexibilidad en la declaración de tipos de datos

SQLite es enormemente flexible en cuanto a la declaración del tipos de datos contenidos en sus tablas. En este sentido debemos diferenciar tres elementos: tipos declarados, afinidades y forma de almacenamiento.

Cuando definimos tablas en MySQL es necesario hacer una estricta declaración de tipos para cada uno de los campos. Recuerda que la sintaxis era similar a esta: numero1 VARCHAR(32). En el caso de SQLite las cosas son más sencillas ya que la propia librería dispone de recursos capaces de interpretar de forma inteligente los tipos declarados y traducirlos a una de sus cinco formas de almacenamiento. Para ello sigue las reglas especificadas en la tabla siguiente:

ReglaFuncionamiento
1Si el tipo declarado contiene la cadena INT se le asigna afinidad INTEGER
2Si el tipo declarado contiene cualquiera de las cadenas: CHAR, CLOB, o TEXT, se asignará afinidad TEXT.
3Si el tipo declarado contiene la cadena BLOB, o si no se define ningún tipo, se le asignará afinidad NONE
4 Si el tipo declarado contiene cualquiera de las cadenas: REAL, FLOA, o DOUB se el asigna afinidad REAL
5En cualquier otro caso la afinidad se considera NUMERIC

Quiere esto decir que podríamos permitirnos la frivolidad de definir un tipo de campo como tipo paraguas. Las reglas de afinidad anteriores lo convertirían de forma automática en NUMERIC dado que no contiene ninguna de las cadenas indicadas en las reglas anteriores. Esta peculiaridad de SQLite resulta muy útil cuando se trata de compatibilizar su sintaxis con la de otros gestores de bases de datos más estrictas en cuanto a su sintaxis. En ejemplos posteriores veremos como SQLite es capaz de manejar, sin apenas modificaciones, definciones de tablas propias de MySQL.

Esta tabla es un resumen de las afinidades de tipos entre las definiciones de los gestores más habituales y SQLite.

Nombres comunes en SQL utilizables en la declaración de tiposAfinidadRegla
INT, INTEGER, TINYINT, SMALLINT, MEDIUMINT, BIGINT, UNSIGNED BIG INT, INT2 ,INT8 INTEGER1
CHARACTER(20), VARCHAR(255), VARYING CHARACTER(255), NCHAR(55), NATIVE CHARACTER(70), NVARCHAR(100), TEXT, CLOB TEXT2
BLOB (sin especificar tipos de datos)NONE3
REAL, DOUBLE, DOUBLE PRECISION, FLOAT REAL4
NUMERIC, DECIMAL(10,5), BOOLEAN, DATE, DATETIME NUMERIC 5

La flexibilidad de SQLite aún tiene un nuevo aspecto diferencial. ¿Qué puede ocurrir si tratamos de agregar datos alfanuméricos a un campo definido como NUMERIC?

SQLite intentará adecuar los contenidos de los campos a la forma de establecimiento establecida en la definición de tabla y/o las reglas de afinidad y cuando esto no resulta posible adecúa la forma de almacenamiento a los contenidos. En la tabla tienes descritas algunas situaciones en las que se producen adaptaciones de este tipo.

AfinidadComportamiento
TEXT– Un campo con afinidad TEXT almacena todos los datos utilizando las formas NULL, TEXT o BLOB.
– Si se inserta un dato numérico en un campo con afinidad TEXT será convertido en cadena antes de ser almacenado
NUMERIC– Un campo con afinidad NUMERIC puede contener valores de cualquiera de las cinco clases de almacenamiento. Cuando se insertan textos la clase de almacenamiento del texto el campo intenta convertirse a INTEGER o REAL (en orden de preferencia). Realiza esa transformación si se conservan los 15 primeros dígitos significativos del número (conversión sin pérdidas y reversible).
– Si la conversión sin pérdida no es posible, entonces el valor se almacena con la clase de almacenamiento TEXT.
– No se intenta convertir los valores NULL o BLOB.
– Una cadena con aspecto de punto flotante con un punto decimal o notación exponencial,que pueda ser expresada como un entero será convertida en entero. Por ejemplo, la cadena 3 .0 e +5 se almacena en una columna con afinidad NUMERIC con el valor 300.000, no como el valor de punto flotante 300.000,0.
INTEGER– Una columna que utiliza afinidad INTEGER se comporta igual que una columna con afinidad NUMÉRICO. La diferencia entre la afinidad INTEGER y NUMERIC sólo es evidente en una expresión de conversión
REAL– Un campo con afinidad REAL se igual que con afinidad NUMERIC excepto que fuerza valores enteros en la representación de punto flotante.
– Los valores de punto flotante sin ningún componente fraccionaria (por ejemplo 23.0) se escriben en el disco como enteros con el fin de ocupar menos espacio. Cuando son leidos recuperan su condición de punto flotante.
NONEUna columna con afinidad NONE no establece ninguna preferencia de clase de almacenamiento.

Errores en la clase PDO

La clase PDO dispone de un método que nos permite obtener información sobre los errores que ocasionalmente puedan producirse en el manejo de sus métodos y/o propiedades. Su sintaxis es esta:

$error=$objeto->errorInfo()

dónde el array escalar $error resultante de la ejecución del método errorInfo está formado por tres elementos cuyos contenidos serían los siguientes:

Creación de tablas

La creación de tablas SQLite, tiene una sintaxis prácticamente igual a la utilizada por MySQL. Requiere una de estas dos sentencias

CREATE TABLE IF NOT EXISTS tabla (campo1, campo2,... )
o
CREATE TABLE tabla (campo1, campo2,... )

La única diferencia entre ambas opciones es que la segunda daría un error si tratáramos de crear una tabla preexistente mientras que la primera no da ese mensaje de error.

La definición de los campos es mucho menos estricta que en MySQL. Sería suficiente con asignarles un nombre sin tan siquiera declarar un tipo. La declaración de tipos, si se opta por hacerla, tiene la amplitud comentada en párrafos anteriores respecto a las afinidades y los parámetros restrictivos –los llamábamos flags de campo en MySQL– tienen como allí carácter opcional y, tal como indicamos un poco más arriba, son básicamente los mismos que MySQL con las excepciones ya comentadas.

La ejecución de las sentencias SQLite por medio de la clase PDO requiere utilizar el método siguiente:

$resultado=$objeto->query(sentencia)

dónde $resultado puede recoger un valor booleano (que confirmaría la correcta ejecución de la sentencia o los eventuales errores producidos durante la ejecución de la misma) o el objeto con el resultado de la ejecución de dicha sentencia (una consulta, por ejemplo).

Base de datos ejemplos

Utilizaremos una base de datos con nombre ejemploSQLite tanto en SQLite como en MySQL. En el primero de los casos será un fichero con ese nombre (ejemploSQLite)que se creará en el servidor. En el segundo será una nueva base de datos añadida a nuestro servidor MySQL. En el mismo script crearemos una tabla en ambas bases (utilizando la misma sentencia) tal como puedes ver en el código fuente.

Ver código fuente