Accediendo a MySQL y Postgresql con PHP y Perl


David Asorey Álvarez

29 de noviembre de 2000


Resumen

La intención de este artículo es hacer una comparación entre los gestores de bases de datos de libre distribución más usados en Linux (MySQL y Postgresql) y la forma de acceder a estos gestores desde un navegador usando lenguajes análogos en su fin y orientación: PHP, Perl Embebido y Perl-CGI.

Este artículo se publicó por primera vez en la revista DLinux de noviembre de 2000.

Puede ser reproducido y distribuído en cualquier medio y formato, de acuerdo a los términos de la "GNU Free Documentation License."

Introducción

Tanto PHP como Perl son dos lenguajes que pueden ser ejecutados como scripts CGI. De hecho, este último uso es la utilización habitual de Perl. La ventaja de usar un lenguaje embebido es que todo va junto, el código HTML y el código del script, no siendo necesario tener scripts en el directorio /cgi-bin/ del servidor. De cualquier forma, también veremos esta posibilidad.

El acceso a las bases de datos viene proporcionado para PHP por las librerías específicas de cada base de datos, mientras que en Perl, existe una librería genérica independiente de la base de datos (DBD) que luego usa un "driver" o conector para cada base de datos.

Estamos presuponiendo que el/la lector/a tiene algunos conocimientos de cómo instalar aplicaciones en su distribución de GNU/Linux y que sabe algo (básico) de HTML, PHP, Perl y SQL.

La máquina en la que se han hecho las pruebas para este artículo es una Intel Pentium 166 con 48MB de memoria RAM. La distribución sobre la que se ha trabajado es la Debian 2.2 r3 "Potato".

Configuración y pasos previos.

Veamos qué hay que hacer para que todo vaya aceitado y funcione:

  1. Instalar, solventando las dependencias que surjan:

    Estos son los paquetes recomendables para Debian Potato, si usais otra distribución, buscad los equivalentes. Apache-perl puede ser sustituído por el Apache con mod_perl. Los módulos para Perl libdbd-mysql-perl, libdbd-pg-perl, libdbi-perl y libhtml-embperl pueden encontrarse en CPAN (http://www.cpan.org).

  2. Una vez instalados y configurados estos paquetes, creamos la base de datos de prueba:

    Debemos tener en cuenta que el usuario que utilicemos para crear estas bases de datos debe tener los permisos adecuados para crear bases de datos, hacer insert, etc... Hay que leer un poco la documentación que se nos instala con los paquetes.

  3. Cargamos las bases de datos:

    Ahora vamos a crear una tabla con bastantes registros para hacer las pruebas, para ello usaremos un pequeño script en Perl, lo guardamos como carga.pl y le damos permisos de ejecución:

    #!/usr/bin/perl
    
    print "create table tabla1 (campo_entero integer, campo_char varchar(50));\n";
    
    for($numero=0;$numero<=3000;$numero++) {
    
              $cuadrado=$numero*$numero;
    
              print "insert into tabla1 values ($numero,'El valor del campo $numero al cuadrado: $cuadrado' );\n";
    
    }
    
        
    
  4. Lo ejecutamos dirigiendo la salida a un archivo, carga.sql:

    ~$ ./carga.pl>carga.sql        
    
  5. Ahora introduciremos los datos en las bases de datos:

    En Postgresql usamos el archivo generado:

    ~$ psql prueba
    
    template1=>\i carga.sql
    
    template1=>\q
        
    

    En mysql ejecutamos el script directamente:

    ~$ ./carga.pl | mysql mysql --user=mi_usuario --password=mi_contraseña

  6. Configurando el Apache.

    Ahora vamos a preparar al apache para que pueda ejecutar PHP y Perl Embebido, asegurándonos de que existen las líneas siguientes en /etc/apache/httpd.conf:

    #Esta línea carga el módulo para que Apache entienda el PHP:
    
    LoadModule php4_module /usr/lib/apache/1.3/libphp4.so
    
    #Esta otra hace que Apache se entienda con el Perl Embebido:
    
    <Files *.epl>
    
    SetHandler perl-script
    
    PerlHandler HTML::EmbperlOptions ExecCGI<Files>
        
    

    ¡Hay que reiniciar el apache si cambiamos algo!

  7. Comprobación:

    Para ver si esto funciona, creamos dos archivos, perl.epl y php.php. Estos los colocamos en el directorio DocumentRoot (en Debian, por defecto /var/www)

    Si dirijimos nuestro navegador habitual a estas páginas, deberían aparecer los mensajes que estamos suponiendo.

Creación de la página de consulta.

Vamos a crear una página HTML convencional para hacer las consultas desde el navegador. Vamos a llamar esta página "select.html" y este sería el código básico:

                        

<HTML>

  <HEAD>

    <TITLE>Acceso a MySQL y Postgresql</TITLE>

  </HEAD>

<BODY>

  <h2>Búsqueda de registros:</h2>

  La consulta será: <BR>

  <h4> "SELECT campo_char FROM tabla1 WHERE campo_entero > criterio1 AND campo_entero < criterio2" </h4>

  <h3>Consulta con PHP:</h3>

  <p><Form method="POST" action="select.php"></p>

    <P>Criterio inferior:  <INPUT type="text" name="criterio1"> (criterio 1) </INPUT></P>

    <P>Criterio superior:  <INPUT type="text" name="criterio2"> (criterio 2) </INPUT></P>

    <P><Input type="submit" name="enviar_mysql" value="Consulta MySQL"></P>

    <P><Input type="submit" name="enviar_psql" value="Consulta PostgreSQL"></P>

  </form>

  <h3>Consulta con Perl Embebido:</h3>

  <p><Form method="POST" action="select.epl"></p>

    <P>Criterio inferior:  <INPUT type="text" name="criterio1" > (criterio 1) </INPUT></P>

    <P>Criterio superior:  <INPUT type="text" name="criterio2"> (criterio 2) </INPUT></P>

    <P><Input type="Submit" name="enviar_mysql" value="Consulta MySQL"></P>

    <P><Input type="Submit" name="enviar_psql" value="Consulta PostgreSQL"></P>

  </form>

  <h3>Consulta con Perl-CGI:</h3>

  <p><Form method="POST" action="cgi-bin/select.pl"></p>

    <P>Criterio inferior:  <INPUT type="text" name="criterio1" > (criterio 1) </INPUT></P>

    <P>Criterio superior:  <INPUT type="text" name="criterio2"> (criterio 2) </INPUT></P>

    <P><Input type="Submit" name="enviar_mysql" value="Consulta MySQL"></P>

    <P><Input type="Submit" name="enviar_psql" value="Consulta PostgreSQL"></P>

  </form>

</BODY>

</HTML>



El fin de la página es bastante obvio: escribimos los valores entre los que queremos buscar (el inferior en un campo y el superior en el otro) y pulsamos el botón que queramos.

Hemos incluído también la posibilidad de hacer la consulta con Perl como un CGI, su uso más tradicional.

Consulta con PHP.

Este sería el código para hacer la consulta con PHP. Es lo más básico posible para ver claramente la diferencia entre usar las funciones de mysql y las de postgresql.

Hemos añadido un botoncito en JavaScript al principio para regresar a la página anterior. Así vemos cómo también podemos integrar diferentes lenguajes complementando la funcionalidad de cada uno.

Si los valores que proporcionamos desde select.html son incorrectos o inadecuados nos encontraremos con que se nos devuelve un error o ningún resultado. Esto podría evitarse validando los valores que introducimos. La forma más útil sería utilizando JavaScript o algún otro lenguaje que se ejecute en el navegador, para así ahorrar carga de trabajo al servidor procesando unos datos incorrectos.

Archivo select.php:

                        

<HTML><HEAD><TITLE>Procesado con PHP</TITLE>

<script language="JavaScript">

        function atras() { history.back() }

</script>

</HEAD>

<BODY>

<p><INPUT type="button" value="Volver" onClick="atras()"></INPUT></p>

<?php

// $enviar_mysql será true si pulsan el botón "Consulta MySQL",

// si pulsan el de "Consulta PostgreSQL", $enviar_psql será true

// los nombres de estas variables coinciden con el atributo "name"

// de los elementos del formulario de la página que llama al script PHP

if ( $enviar_mysql ) {

        $conex_mysql = mysql_connect ("localhost" , "mi_usuario", "mi_contraseña") ;

// $conex_mysql devuelve un indicador de conexión

        $sql = "SELECT campo_char FROM tabla1 WHERE campo_entero > $criterio1 AND campo_entero < $criterio2" ;

        $resultado_mysql = mysql_db_query( "prueba" , $sql , $conex_mysql );

// $resultado_mysql devuelve el indicador de la consulta,

// true si fue exitosa

        if ( $resultado_mysql ) {

                echo "Los resultados de la consulta: <br> $sql <br> son los siguientes: <br><br>";

                while ( $tupla_extraida = mysql_fetch_array ( $resultado_mysql ) ) {

// la función mysql_fetch_array devuelve un array asociativo con los campos extraídos

// y salta a la siguiente tupla, si es la última, devuelve false y salimos del bucle

                        echo $tupla_extraida["campo_char"] ;

                        echo "<br>";

                }

        }else {

                echo "Falló la consulta a MySQL:<br>";

                echo mysql_error ( $conex_mysql ) ;

        }



} elseif ( $enviar_psql ) {

        $conex_psql = pg_connect ("dbname=prueba user=mi_usuario password=mi_contraseña") ;

// vemos que la sintaxis para conectar a Postgresql es un poco diferente

        $sql = "SELECT campo_char FROM tabla1 WHERE campo_entero > $criterio1 AND campo_entero < $criterio2" ;

        $resultado_psql = pg_exec( $conex_psql , $sql );

// como al conectar ya especificamos la base de datos,

// ya no es necesario especificarla en la consulta

        if ( $resultado_psql ) {

                echo "Los resultados de la consulta: <br> $sql <br> son los siguientes: <br><br>";

                $contador = 0;

                while ( $contador < pg_numrows ( $resultado_psql ) ) {

// la función pg_fetch_array necesita de un contador para saber

// en que tupla nos encontramos, al contrario que mysql_fetch_array,

// que ya se encarga de saltar a la siguiente tupla y dar false si termina

                        $tupla_extraida = pg_fetch_array ( $resultado_psql , $contador );

                        echo $tupla_extraida["campo_char"] ;

                        echo "<br>";

                        $contador++;

                }



        }else {

                echo "Falló la consulta a Postgresql:<br>";

                echo pg_errormessage ( $conex_psql ) ;

        }



} else {

// no creo que por aquí entremos ... :-)

echo "Algo va mal ...";

}

?>

</BODY></HTML>



Consulta con Perl Embebido.

Ahora vamos a ver cómo podemos hacer lo mismo con Perl Embebido. El perl embebido tiene algunas particularidades que lo distinguen del perl "corriente". Si con PHP las instrucciones PHP las encerramos entre <? y ?>, en perl embebido las encerramos entre [ y ] con las siguientes particularidades:

Veamos ahora cómo hacemos la consulta. El archivo lo llamaremos select.epl



<html>

<head>

<title>Procesado con EmbPerl</title>

<script language="JavaScript">

        function atras() { history.back() }

</script>

</head>

<body>

<p><INPUT type="button" value="Volver" onClick="atras()"></INPUT></p>

<!-- En el array asociativo fdat vienen los valores que nos manda el formulario.

Cada atributo "name" de cada control del formulario es la clave del array. 

Para conectar a las bases de datos usamos el módulo DBI. Toda la información

sobre DBI la podemos consultar con perldoc: perldoc DBI.

-->

[-

use DBI;

$campo1 = $fdat{criterio1};

$campo2 = $fdat{criterio2};

$boton_mysql = $fdat{enviar_mysql};

$boton_psql = $fdat{enviar_psql};

-]

[$ if ( $boton_mysql ) $]

[-

$driver="mysql";

$baseD="prueba";

$usuario="mi_usuario";

$contrasenna="mi_contraseña";

$conexion = DBI ->connect("dbi:$driver:$baseD",$usuario,$contrasenna);

-]

[$ elsif ( $boton_psql ) $]

[-

$driver="Pg";

$baseD="prueba";

$usuario="mi_usuario";

$contrasenna="mi_contraseña";

$conexion = DBI ->connect("dbi:$driver:dbname=$baseD",$usuario,$contrasenna);

-]

<!-- Dependiendo de qué botón hayan pulsado, conectaremos a una base de datos

 u a otra. La función que usamos es DBI -> connect( ). 

 Vemos que varía algo la sintaxis de la función connect según la base de datos 

 a la que conectemos. En general se especifica dbi:driver:datos de conexión.

 El driver puede ser Pg, mysql, odbc, etc...

--> 

[$ endif $]

[-

$sql = "SELECT campo_char FROM tabla1 WHERE campo_entero > $campo1 AND campo_entero < $campo2";

$sentencia = $conexion->prepare($sql);

$sentencia->execute();

-]

<!-- La consulta lleva tres pasos: Conexión con connect, que nos devuelve un 

 indicador de conexión, preparación con prepare() y ejecución con execute().

 Para extraer los resultados usamos la función fetchrow_array, que nos devuelve

 un array con los contenidos de un registro, salta al siguiente y devuelve false

 si termina.

--> 

 Los resultados de la consulta: <br> [+ $sql +] <br> son los siguientes: <br><br> 

[$while @tupla=$sentencia->fetchrow_array $]

        [+ $tupla[0] +]

        <br>

[$ endwhile $]



</body>

</html>



        

Procesando con Perl-CGI.

Este es el uso más tradicional de Perl. Colocamos un script en el directorio cgi-bin del servidor, le damos permisos de ejecución y lo llamamos desde una página HTML. Es imporatante que en el encabezado del archivo pongamos la línea Content-Type, si no el navegador no es capaz de entender lo que le mandamos. Guardaremos este archivo, selec.pl en el directorio cgi-bin del servidor.



#!/usr/bin/perl

use DBI;

print "Content-Type: text/html \n\n";

print "<html><head><title>Procesado con Perl-CGI</title>";

print "<script language=\"JavaScript\">  function atras() { history.back() }</script>

print "</head><body><p><INPUT type=\"button\" value=\"Volver\" onClick=\"atras()\"></INPUT></p>\n";

$entrada = <STDIN>;

#Los datos introducidos en el formulario vienen con el formato siguiente:

#campo=valor&otro_campo=otrovalor&boton=nombre_del_boton.

#Los separamos con la función split para tener en el array @campos los tres 

#valores que nos pasa el formulario.

@campos = split("&" , $entrada); 

#Ahora volvemos a "partir" con split y nos quedamos con el segundo valor del

#array @temp, que contiene el valor que nos interesa.

@temp = split ("=" , $campos[0]);

$campo1 = $temp[1];

@temp = split ("=" , $campos[1]);

$campo2 = $temp[1];

@temp = split ("=" , $campos[2]);

$boton = $temp[1];

if ( $boton eq "Consulta+MySQL" ) {

$driver="mysql";

$baseD="prueba";

$usuario="mi_usuario";

$contrasenna="mi_contraseña";

$conexion = DBI ->connect("dbi:$driver:$baseD",$usuario,$contrasenna);

}elsif ( $boton eq "Consulta+PostgreSQL" ) {

$driver="Pg";

$baseD="prueba";

$usuario="mi_usuario";

$contrasenna="mi_contraseña";

$conexion = DBI ->connect("dbi:$driver:dbname=$baseD",$usuario,$contrasenna);

}

#Según se haya pulsado un botón u otro, conectamos con una base de datos u otra.

#Como con PHP , varía ligeramente la sintaxis para establecer la conexión.

$sql = "SELECT campo_char FROM tabla1 WHERE campo_entero > $campo1 AND campo_entero < $campo2";

$sentencia = $conexion->prepare($sql);

$sentencia->execute();

print "Los resultados de la consulta: <br> $sql <br> son los siguientes: <br><br> ";

#La consulta lleva tres pasos: Conectar con DBI->connect, preparar la consulta

#con prepare y ejecutarla con execute.

while (@tupla=$sentencia->fetchrow_array ) {

# fetchrow_array nos devuelve un array con los campos correspondientes 

# y salta al siguiente registro

        print "$tupla[0] <br>";

}



print "</body></html>";



        

Conclusiones.

Hemos visto tres formas diferentes de acceder a MySQL y Postgresql. Sólo hemos realizado consultas del tipo "SELECT". Podríamos hacer algunos scripts similares para hacer inserciones en las tablas ("INSERT"), actualizar registros, etc. En definitiva, todas las sentencias SQL que admita cada gestor de bases de datos son realizables.

Comparación de rendimiento.

Las pruebas se han hecho en una sóla máquina, por ello estos resultados son poco fiables para aplicarlos a un entorno de "producción" real. Han sido ejecutados en una máquina modesta: Pentium 166 con 48Mb de RAM y 64Mb de memoria de intercambio. Estas conclusiones tienen validez para analizar el rendimiento independientemente del tráfico de una red y otros factores que pueden influir en el tiempo en responder el servidor a la petición. Hemos hecho una consulta para extraer todos los registros de la tabla (3000) y estos han sido los tiempos medios en devolvernos la página completa. En general la primera petición ya sea con PHP, Perl Embebido o Perl CGI siempre tarda un poco más que las siguientes.

Comparación en prestaciones.

  1. MySQL vs. Postgresql:

    En general MySQL parece algo más rápido que Postgresql, si bien es una diferencia muy pequeña, sin embargo Postgresql tiene más funcionalidades: soporta transacciones (esto quiere decir que podemos hacer, por ejemplo, un montón de sentencias "INSERT" y si, por alguna razón, algo falla, cancelar todos estas sentencias con la instrucción "ROLLBACK", o por el contrario, hacerlas efectivas con un "COMMIT"). Hasta ahora ésto no era soportado por MySQL (en las versiones más modernas ya se ha introducido). La comprobación de datos es más efectiva (se pueden comparar claves foráneas y otras funcionalidades avanzadas). En conclusión, Postgresql parece más completa y avanzada, pero esto tiene un precio en consumo de recursos del sistema. Por otra parte, en muchísimas situaciones no se necesitan estas funcionalides, como por ejemplo en aplicaciones Web en las que sólo se leen datos. En la práctica, en entornos de Internet se suele usar MySQL prererentemente por su sencillez y rapidez.

  2. PHP vs. Perl Embebido vs. Perl-CGI:

    En cuanto a velocidad sale ganando PHP frente a Perl. Esto depende mucho de la configuración del sistema y la carga de usuarios y consultas, pero así, a "palo seco", en local, PHP parece más rápido.

    Respecto a la facilidad de programación, lo que sigue es muy subjetivo y habrá quien opine lo contrario, pero la primera impresión es que la sintaxis de PHP es más clara que la de Perl. Un programador acostumbrado a Perl no tendría ninguna dificultad para adaptarse a PHP o al Perl Embebido con sus peculiaridades, pero el paso inverso de PHP a Perl puede ser más dificultoso. La gran ventaja de Perl es su antigüedad: lleva muchísimos años funcionando y ampliándose. Existen infinidad de módulos para ampliar la funcionalidad de Perl (de hecho Perl Embebido es uno de estos módulos). La documentación sobre Perl es muy amplia, y es un lenguaje que una vez aprendido permite hacer maravillas en una línea de código. PHP está basado en parte en Perl, y de éste hereda muchas de sus buenas características: amplia biblioteca de funciones y un tratamiento de expresiones regulares muy bueno. ¿Cúal elegir?. La respuesta es tan difícil cómo elegir una base de datos para trabajar. PHP es rápido ejecutándose y es fácil de escribir. Perl es también rápido y tiene muchísimos módulos disponibles y documentados que nos permiten hacer de todo aparte de aplicaciones orientadas a Internet. Para alguien que nunca ha programado con ninguno de los dos parece más recomendable PHP, pero sabiendo que se pierde uno de los lenguajes más potentes de los entornos UNIX y con más historia. En entornos reales parece que lo que más se está utilizando por ahora es PHP. De hecho se ha acuñado últimamente un término para designar aplicaciones Web realizadas con unas determinadas herramientas: LAMP (Linux + Apache + MySql + PHP).

Finalmente...

Espero que haya resultado útil este breve recorrido por PHP, Perl, MySQL y Postgresql. Dejo como ejercicio a el/la lector/a tratar de hacer inserciones en las bases de datos y comprobar el funcionamiento. Como anécdota, cargar la base de datos de prueba tardó muchísimo más con Postgresql, así que es de esperar que los "INSERT" sean más rápidos en MySQL.

Si alguien quiere hacer alguna sugerencia o corrección, que le proporcione el código fuente de los ejemplos o comentar alguna dificultad puede ponerse encontacto con el autor en la dirección: forodejazz@yahoo.es

Documentación útil:

  1. http://www.php.org Manual de PHP. Aquí encontraremos el manual oficial de PHP, en múltiples formatos y traducido a bastantes idiomas, incluído el castellano. También encontraremos descargas de PHP para diversas plataformas (incluso propietarias).
  2. http://www.cpan.org Módulos de Perl. CPAN es el "Comprehensive Perl Archive". Aquí encontraremos documentación y módulos para descargarnos.
  3. http://www.perl.org El sitio oficial de Perl.
  4. http://www.mysql.com Manuales de uso, descargas para distintas plataformas (incluso propietarias) y más información.
  5. http://www.postgresql.org Aquí también encontraremos información de utilidad.

Subir