Exportar datos de PostgreSQL a un fichero CSV

En algún momento ya habíamos hablado por aquí del formato CSV (comma separated values), un estándar para compartir información mecánicamente legible que, a pesar de algunas limitaciones con la codificación de caracteres, es bastante popular pues, por ejemplo, nos permite pasar datos de un sistema gestor de bases de datos a una hoja de cálculo o viceversa.

El sistema gestor de bases de datos PostgreSQL nos permite exportar datos a CSV de forma muy sencilla, y además tenemos dos posibilidades: Exportar una tabla entera o exportar el resultado de una consulta.

El comando básicamente sería COPY loquesea TO ficherodesalida DELIMITER ‘caracterdelimitador’ CSV HEADER; siendo el caracter delimitador generalmente una coma, pero puedes cambiarlo por otro si lo necesitas para tu exportación (puede darse el caso de que los datos que exportes tengan textos con coma, por lo que igual te interesa un caracter más exótico). El loquesea del ejemplo sería o el nombre de una tabla o una consulta, mientras que ficherodesalida sería la ruta donde queremos que se cree nuestro CSV.

Veamos dos ejemplos. Imaginemos que queremos expotar todos los datos de una tabla que se llama Pacientes:

COPY Pacientes TO 'Users/Donato/Documents/Pacientes.csv' DELIMITER ',' CSV HEADER;

Esa instrucción generaría un fichero con el nombre que le hemos definido en la ruta que le hemos ordenado, conteniendo todos los valores de la tabla pacientes separados por comas. Ahora imaginemos que solo queremos los nombres y apellidos de los pacientes del año 2021 (tenemos un campo con el año en el que se dieron de alta), podríamos exportarlos usando una consulta:

COPY (Select Nombre, Apellidos from Pacientes where Alta = 2021) TO 'Users/Donato/Documents/Pacientes.csv' DELIMITER ',' CSV HEADER;

De esta forma exportaríamos solo esos datos que nos interesan, filtrados a través de esa consulta. Ahora podríamos abrir esos datos en Excel, Googl Sheet o LibreOffice Math, por ejemplo.

Importar datos desde un fichero CSV a una tabla de SQLite

Ya hemos hablado en el pasado de ficheros CSV en este blog, y hoy vuelven a la primera línea.

En este caso porque ayer estaba aconsejando a un amigo sobre cómo agilizar una tarea de inserción de datos en SQLite y llegamos a la conclusión de que, teniendo los datos en un fichero CSV tenía que haber una forma de importarlo. El caso es que San Google nos dio la respuesta, pero me fijé en que no había mucha cosa válida sobre el tema en español. Total, que me he decidido a traducir la entrada que nos fue más útil, que fue esta de HackGeo. Bueno, como siempre no será una traducción literal, sino una adaptación/explicación de su solución.

En fin, como dice el artículo original, hay una serie de puntos a considerar antes de ponerse a trabajar:

  • SQLite instalado en tu sistema operativo.
  • Una base de datos ya creada (si quieres seguir el ejemplo del original, podéis descargar ejemplos de código desde allí)
  • Una tabla creada en esa base de datos cuyos campos y tipos coincidan con los datos de nuestro CSV, tal que así:
    CREATE TABLE counties (
        name        CHAR,
        state       CHAR,
        state_abbrv CHAR( 2 ),
        FIPS        CHAR( 5 )
    );
    
  • Un fichero CSV cuyo esquema coincida con vuestra tabla, como por ejemplo:

    Maui,Hawaii,HI,15009
    Kauai,Hawaii,HI,15007
    Kalawao,Hawaii,HI,15005
    Honolulu,Hawaii,HI,15003
    Hawaii,Hawaii,HI,15001

Ahora, siguiendo el ejemplo original, ya tenemos todos los datos y el software listos. Ya sólo quedan cuatro pasos para tener todo listo:

  1. Lanza un terminal
  2. Abre la herramienta de terminal de comandos de SQLite, escribiendo sqlite3 y pasándole como parámetros la ruta absoluta a vuestra base de datos:
    sqlite3 '/Path/To/HackGeo - SQLite CSV Import Example/HackGeo.db'
    
  3. Pon la coma como separador por defecto (si usas tu propio CSV y no el del ejemplo entonces define el separador que corresponda, en caso de que no sea la coma):
    .separator ','
    
  4. Ahora ejecuta el importador de SQLite para volcar los datos del CSV en tu equipo. Le tenemos que pasar dos parámetros a este comando: la ruta del csv y el nombre de la tabla donde insertaremos los valores:
    .import '/Path/To/HackGeo - SQLite CSV Import Example/Counties.csv' counties
    

Y sólo con esto ya tenemos los datos pasados del CSV a la base de datos SQLite. Ya podéis cerrar el terminal de línea de comandos y empezar a trabajar con vuestros nuevos datos. Y si sabéis inglés en HackGeo tenéis muchos artículos interesantes sobre desarrollo, sistemas, etc…

Leyendo ficheros CSV con PHP

A petición de Jorge de Saliceta, que lo reclamó en la entrada sobre lectura de ficheros en PHP va la explicación sobre cómo leer ficheros CSV con PHP. No es la primera vez que en este blog hablamos sobre el formato CSV (comma separated values).

Bueno, si te vas a la entrada de lectura de ficheros verás que para la lectura secuencial, línea a línea, usábamos la función fgets(). Bueno, pues existe una función similar, llamada fgetcsv(), pensada para trabajar con archivos de este tipo. En lugar de devolver una cadena de texto como fgets(), esta función lo que devuelve por cada línea recorrida es un array, donde cada valor separado por una coma ocupa una de las posiciones del mismo. Veamos un ejemplo:

//supongamos la siguiente fila en un csv:
//Manolo, Rodríguez, Málaga, Fontanero
//y que está guardado en el archivo prueba.csv
//Aplicaríamos el siguiente código

<?php
$file = fopen("prueba.csv","r");
$result = fgetcsv($file);
fclose($file);
?> 

//esto devolvería un array con el siguiente resultado:
Array
(
[0] => Manolo
[1] => Rodríguez
[2] => Málaga
[3] => Fontanero
) 

Cuestiones a tener en cuenta hay varias. La primera es que si pilla una línea en blanco devolverá una matriz con un sólo campo con el valor NULL. La segunda es que existen varios parámetros que podemos pasar: Obligatorio, desde PHP5, sólo es el archivo a parsear, pero también acepta la longitud máxima de línea (si la sabes pásalo, porque hará que la función vaya más rápido), el delimitador de campo (por defecto, la coma), el «cercado» de campo (por defecto comillas dobles… ya se que lo de cercado no es muy claro, en inglés sería enclosure) y el caracter de escape (por defecto, la barra invertida). Al igual que con fgets() puede haber problemas para detectar los finales de fila en archivos creados en un Mac, y también hay que tener en cuenta que la función tiene en cuenta la configuración local, así que si estás trabajando con UTF8 tenlo en cuenta a la hora de calcular el tamaño máximo de línea o con los archivos codificados en one-byte.

Finalmente os dejo un gran ejemplo del funcionamiento de esta función sacado de la web de php:


<?php
$fila = 1;
if (($gestor = fopen("test.csv", "r")) !== FALSE) {
    while (($datos = fgetcsv($gestor, 1000, ",")) !== FALSE) {
        $numero = count($datos);
        echo "<p> $numero de campos en la línea $fila: <br /></p>\n";
        $fila++;
        for ($c=0; $c < $numero; $c++) {
            echo $datos[$c] . "<br />\n";
        }
    }
    fclose($gestor);
}
?>

Importando y exportando archivos csv con PHP

Los ficheros CSV (abreviatura de comma-separated values) son de gran utilidad, dado que nos permiten importar y exportar datos fácilmente en un formato libre que puede ser abierto por casi cualquier hoja de cálculo.

Para el ejemplo de generación de CSV vamos a suponer que habéis lanzado una consulta contra una base de datos SQL y ya tenéis los datos recuperados en el array pertinente (en este caso le llamaré $datos en el ejemplo), pero además de imprimirlos en pantalla tenéis que exportarlos a un formato con el que pueda trabajar, por ejemplo, Excel (cuando estaba en Nática tuve que hacer algo similar pero con ASP). Bueno, pues la cosa iría como en el siguiente ejemplo:

$file = fopen("exportacion.csv","w"); //abrimos el archivo csv para escritura
$s = ","; //establecemos un separador

while($registro = mysql_fetch_array($datos) ) {
	$fila = $registro['id'].$s.$regisro['nombre'].$s.$registro['telefono']."\n";
	fwrite($file,$fila);
}
fclose($file);

Bueno, la cosa es simple. Primero abrimos el archivo (en este caso le llamé exportacion.csv) en modo de escritura. Establecemos una variable con un valor como separador (en este caso, la coma) y recorremos el array con un bucle while, creando una variable $fila con todos los datos que guardamos en cada iteración del bucle. Con todo esto ya tenemos generado nuesto .csv

Pero ¿y el caso contrario? ¿Y si lo que queremos es abrir un fichero csv desde nuestro php para imprimirlo en pantalla o para guardarlo en la base de datos? Bueno, en el siguiente ejemplo veremos como leer el archivo:

$file = fopen ( "exportacion.csv" , "r" );
while (( $data = fgetcsv ($file,1000,",")) !== FALSE ){
    $i = 0;
    foreach($data as $row) {
        echo "registro $i: $row<br/>";
        // Imprime toda la fila
        $i++ ;
    }
    echo "<br/><br/>";
}
fclose ( $file );

 

Bueno, la explicación es rápida también. Primero abrimos el archivo de antes en modo lectura. Tras esto, usando la función fgetcsv recuperamos la información del archivo y con el bucle foreach recorremos todas las filas, en este caso imprimiéndolas. Podríamos, por ejemplo, usar la función split para partir la fila por las comas y acceder así a los valores por separado de cada una

En fin, espero que esto os sirva como ayuda e introducción para trabajar con estos archivos en php