Instalar MongoDB en Linux

MongoDB es un sistema de bases de datos «no SQL» (aunque lo haya metido en la sección SQL del blog), documental, que destaca por su velocidad y rendimiento. No en vano, muchas páginas con requisitos de gran escalabilidad están recurriendo a ete tipo de soluciones, como Facebook y Twitter, que han migrado parte de su base de datos (en un principio MySQL) a CassandraDB.

Aparte de un nombre horrible, MongoDB es bastante fácil de instalar, sólo hay que seguir estos pasitos tras descargar desde aquí la versión que se adapte a vuestra arquitectura (32bits o 64bits):

La idea es descomprimir el archivo (en el ejemplo será el de 64 bits, si bajáis el de 32 poned el nombre que corresponde), crear la carpeta donde MongoDB guarda los datos (/data/db) y darte permisos de usuario en ella. Tal que así:

tar -xzvf mongodb-linux-x86_64-1.8.1.tgz
sudo mkdir -p /data/db
sudo chown TU_USUARIO /data/db

Una vez cambiado el usuario a la carpeta /data/db, se debe ir a los archivos extraídos de MongoDB, entrar a la carpeta bin y ejecutar (con tu usuario) la aplicación: ./mongod

Si no aparece el mensaje «really exiting now» se está ejecutando el demonio de mongoDB, listo para conectar por defecto en el puerto 27017, aunque también tiene una interfaz web muy básica que pone a la escucha el puerto 28017 (puede consultarse en http://localhost:28017). Si quieres finalizar el demonio presiona ctrl + c.

Para hacer consultas desde consola de debe usar otro terminal, el el cual debes ir a la misma carpeta donde descomprimiste mongoDB, entrar a la carpeta bin y ejecutar la aplicación ./mongo que nos debe devolve un prompt vacío (símbolo >)

La shell de MongoDB es un intérprete de JavaScript por lo que podemos escribir scripts que pueden ser interpretados por la propia shell, utilizar las librerías estándares de JavaScript o escribir funciones en varias líneas.

> "Hello, World!".replace("World", "usuario molón");
Hello, usuario molón!

Cuando iniciamos la shell, el cliente conecta con la base de datos por defecto del servidor MongoDB y guarda la conexión en la variable db. Desde esta shell podemos utilizar las operaciones CRUD: crear, modificar, leer y borrar, para manipular y ver los datos en el shell.

Tras esto ya tienes instalado tu servidor de bases de datos MongoDB, si quieres documentación en español puedes tirar de su wiki oficial, para ir introduciéndote en este mundillo NoSQL

EDITO para comentar que en Ubuntu 12.04 han metido MongoDB en los repositorios, por lo que la instalación se simplifica con un básico

sudo apt-get install mongodb

En Debian que yo sepa de momento no, así que tenéis que seguir con el primer ejemplo, de momento.

Instalar LAPP en Debian (Apache/PHP/Postgres)

En fin, con esto ya está instalado el servidor y el PHP, y además iniciado el servicio de Apache para que puedas testear el funcionamiento de la instalación. El siguiente paso será la instalación de PostgreSQL 9.1 que, de momento, no está incluída en los repositorios oficiales de Debian (donde todavía está la 8.4), por lo que habrá que tirar del repositorio Debiak-Backports, donde tienen las últimas de versiones de software para Debian. Basta con añadir la línea deb squeeze-backports main en el fichero /etc/apt/sources.list y listo, ya tienes el repositorio disponible. Con esto ya sólo tenemos que actualizar repositorios e instalar tal que así:

$sudo apt-get update
$sudo apt-get -t squeeze-backports install postgresql-9.13.1

Ahora será el momento de configurar la contraseña de Postgres. Primero hemos de asumir la identidad del usuario postgres. A continuación, accedemos al cliente de linea de ordenes de PostgreSQL.Una vez dentro, cambiamos el password. Todo esto como en el ejemplo de código:

$sudo su postgres
$psql
postgres=# alter user postgres with password ‘passwd’;

El sistema debe responder con un:ALTER ROLE postgres=# Salimos del cliente de linea de ordenes con la orden:postgres=#\q Y salimos de la cuenta en el sistema del usuario postgres con un simple:$exit

Por defecto, PostgreSQL sólo atiende peticiones provenientes de la máquina local. Si estamos configurando un servidor remoto, deberemos habilitar el acceso desde otras IPs. Debemos editar el fichero /etc/postgresql/9.1/main/postgresql.conf. Busca la línea #listen-address = ‘localhost’ la copiala debajo, la descoméntala y modifícala. Si queremos poermitir el acceso de todas las IP habría que poner listen-address = ‘*’ mientras que si queremos utilizar varias IP concretas sólo tenemos que pasarle las direcciones, separadas por comas tipo listen-address = ‘192.168.0.6,192.168.0.8’

Tras esto lo primero que hay que hacer es dar ciertos permisos locales, dado que Postgres es muy restrictivo en esto en su instalación por defecto. Hay que editar el fichero /etc/postgresql/9.1/main/pg_hba.conf. Busca la línea local all postgres peer y cámbiala por local all postgres md5 con lo que permitimos al usuario postgres conectarse desde la maquina local, usando una contraseña encriptada con md5.Lo siguiente es acceso a cualquier cuenta de usuario desde la maquina local siempre que se especifique una contraseña encriptada mediante md5.Busca la línea cuyo contenido es:local all all peer y cámbialo por local all all md5, con lo que ya estará.

Finalmente debemos configurar los permisos de acceso remoto. Se trata de tratar las siguientes cuestiones:¿Qué usuarios tienen permiso para conectarse?¿Desde qué IPs lo pueden hacer?¿A qué bases de datos?¿Qué método de auteticación usarán?. Eso ya lo dejo en tus manos y tienes varios tutoriales sobre cómo hacerlo por la red adelante. También puedes probar siriviéndote de la ayuda del sistema, el fichero donde se dan los permisos es /etc/postgresql/9.1/main/pg_hba.conf

Para permitir el subir y bajar archivos de forma remota, finalmente, debemos instalar un servidor FTP, en este caso ProFTP. Requiere un poco de configuración tras la instalación:

$sudo apt-get install proftpd

Durante la instalación nos preguntará qué modo de funcionamiento queremos elegir, en este caso standalone. Luego habrá que configurar el servidor para que el directorio raíz del servidor FTP sea el mismo que el directorio raíz del servidor web, permitiendo de esa forma subir y bajar los archivos publicados en Apache. Hay que modificar el fichero /etc/proftpd.conf y añadir

<global>
  DefaultRoot /var/www
   var/www >
     All> AllowAll
   </directory>
</global>

Finalmente reiniciamos el servidor para que todos los servicios estén arrancados, y ya podemos probar todo el funcionamiento.

Usando librerías .dll de .NET en SQL-Server2008

Aunque normalmente no se recomiende tener la lógica de negocio en el lado del servidor de la base de datos, en algunos casos puede resultar interesante el hacerlo. Microsoft, en su empeño (por otra parte loable) de lograr una integración total entre sus servicios, nos permite utilizar nuestras .dll creadas en .NET (sea en VB.NET o en C#.NET o en C++) dentro de nuestra base de datos SQL-Server como «código gestionado».

Iré construyendo poco a poco un ejemplo para que veáis, paso a paso como se realiza esto. Lo primero es activar clr para que nos permita la integración con .NET tal que así:

USE [basedatosdeejemplo]
go
sp_configure 'clr enabled', 1
go
reconfigure
go

Seleccionamos la base de datos a utilizar, configuramos clr como ‘enabled’ (armado, activado) con el parámetro 1 y ejecutamos reconfigure para que el cambio tenga efecto. Acuérdate de poner el parámetro (en este caso 1) y de ejecutar reconfigure.

El primer paso está realizado. Lo siguiente es crear el ensamblado para la librería, definiendo el esquema y el tipo de permisos.


CREATE ASSEMBLY [Utilidades]
AUTHORIZATION [dbo]
FROM 'C:\LibreriaEjemplo.dll'
WITH PERMISSION_SET = SAFE
GO

Creamos el ensamblado con el nombre «Utilidades» (podemos darle el que queramos mientras no sea una palabra reservada), con el esquema dbo (podríamos haber utilizado cualquiera de los disponibles), en FROM le especificamos la dirección del archivo en disco mediante una cadena de texto con la ruta y finalmente los permisos, en este caso SAFE.

SAFE es el permiso más restrictivo que hay, el más «seguro» para nuestro equipo pues limita mucho lo que pueda hacer la librería. En caso de que uses liberías de terceros es el permiso que te reportará más seguridad. Existe también el permiso EXTERNAL_ACCESS, que permite que el código acceda a ciertos recursos externos (registro, archivos, red) y el permiso UNSAFE, que da control sin restricciones a la librería sobre los recursos de la máquina. Si usas una librería propia puedes usar UNSAFE, pero si usas una de un tercero piensa que pueden entrañar riesgos de seguridad.

Con lo puesto ya tenemos la librería disponible en nuestra base datos. ¿Y ahora qué? Ahora simplemente puedes usar las clases y métodos de dicha librería en tu base. Puedes crear tus tipos de datos propios usando sus objetos, incluir sus métodos en procedimientos o triggers. En este ejemplo vamos a suponer que la librería importada tiene una clase Point que guarda las coordenadas de un eje X y un eje Y junto a un valor booleano, y tiene también una función GetCoordsAsText que muestra un mensaje largo con las coordendas. Vamos a crear un tipo de datos Point, usarlo en una tabla, acceder a los valores y usar el método GetCoordsAsText en una función. Pondré comentarios para ir explicando el proceso

--Creamos el tipo de datos Point como un objeto de la clase Point.
--Para acceder a la clase point tenemos que usar el método external name de SQL-Server
--accediendo a la clase mediante el nombre del assembly que creamos antes y el namespace de la clase (en 
--este caso point)
create type Point
external name Utilidades.Point 
go

--Creamos la tabla

create table dbo.Points
(
	id int identity primary key,
	valor Point
);
go

--Para acceder a los datos de la tabla debemos usar un método que nos devuelva
--los valores almacenados dentro del objeto en forma de texto (en este caso .X para el valor X, .Y para 
--el valor Y o .ToString() para sacar ambos en una columna como texto).

select id,
			valor.X as X,
			valor.Y as Y,
			valor.ToString() as Completo
from dbo.Points

--Si intentáramos acceder al objeto a pelo, como voy a poner debajo, nos devolvería el valor del objeto
--sin convertir (un churrazo con la dirección de memoria del puntero)

select valor from dbo.Points --así nos saldría un churo tipo 0x0000000100020000303000000

--También podríamos usar los métodos de la librería en una función, trigger, función de agregado,
--cursor... En este caso haremos una función que acceda a GetCoordsAsText (que está en la clase 
--UserFunctions)

create function dbo.CoordenadasComoTexto
returns nvarchar(50)
as
    external name Utilidades.UserFunctions.GetCoordsAsText

Y con esto tendríais la función que simplemente ejecuta el método definido en la dll y un tipo de datos igual al objeto. Las posibilidades de esto son muy grandes, así que podéis ir profundizando.

Procedimiento que hace una select desde un XML en SQL-Server

Bueno, estoy realizando un cursillo de SQL-Server2008 R2 cortesía de la Xunta y la UE (hay que aprovechar, que a ver lo que dura la formación gratis en este país). Así que vamos con pequeño ejemplo: un procedmiento que realiza un select sobre un fichero xml, que recibe como parámetro.

Primero vamos a definir una variable como xml (podríamos también importarlo usando un bulk import, pero así veis más clara):

declare @EjemploXML as xml

set @EjemploXML=
'<?xml version="1.0"?>
<SalespersonMods>
    <SalespersonMod SalespersonID="274">
        <Mods>
            <Mod SalesTerritoryID="3"/>
        </Mods>
    </SalespersonMod>
    <SalespersonMod SalespersonID="278">
        <Mods>
            <Mod SalesTerritoryID="4"/>
        </Mods>	
    </SalespersonMod>
<SalespersonMods>'

En fin, ahí tenéis el xml que vamos a recorrer. Como véis la «chicha» está en los atributos SalespersonID y SalesTerritoryID, que son los datos que queremos sacar en la consulta. Ahora os dejo el código y debajo explico todo el procedimiento:


create procedure selectFromXML
@SalesPersonMods xml
as
begin
  declare @XMLdoc int
  exec sp_xml_preparedocument @XMLdoc output, @SalesPersonMods
  select * from
  openxml(@XMLdoc, '/SalespersonMods/SalespersonMod/Mods/Mod')
  with
  (
	SalesTerritoryID int '@SalesTerritoryID',
	SalespersonId int '../../@SalespersonID'
  )

  exec sp_xml_removedocument @XMLdoc
end

En fin, y explicado rápido: Lo primero es crear el procedimiento con create procedure seguido del nombre que queremos darle, y especificando que recibirá como parámetro @SalesPersonMods, que será un xml. Tras eso declaramos un variable entera (la he llamado @XMLdoc) que almacenará un manejador. Para crear dicho manejador usamos el procedimiento almacenado de sistema sp_xml_preparedocument, que recibe como parámetros la variable entera @XMLdoc (definido como output) y la variable xml @SalesPersonMods. Ya tenemos el manejador listo. Ahora queda hacer la select, que empieza como cualquier select normal: select ‘loquesea’ from (en este caso *, o sea, todo). Y en este caso en vez del nombre de tabla irá la función openxml, que recibirá como parámetros el manejador que creamos antes (@XMLdoc) y una cadena de texto con el elemento del xml en el que queremos posicionarnos.

Movernos por el xml es como movernos por MS-DOS, usamos la jerarquía de etiquetas separadas por barras (/) como si fuera una jerarquía de directorios, usando el punto (.) para referirnos a elementos que parten del mismo nivel jerárquico y el doble punto (..) para navegar hacia atrás en la jerarquía. En este caso queremos acceder al atributo SalesTerritoryID, que es un atributo de /Mod (donde nos hemos situado), por lo que no hay que navegar, accedemos a él simplemente con @SalesTerritoryID (a los atributos nos referimos siempre precediéndolos de una arroba, si fuera texto en la etiqueta lo haríamos sin ella) dándole como nombre de columna SalesTerritoryID (definida como entero, en este caso, por ser el valor más adecuado). SalespersonID en cambio está dos niveles más arriba, así que llegamos a él indicándolo con el doble punto: «../../SalespersonID».

Finalmente, tras todas las operaciones, quitamos el manejador de la memoria para liberarla. Si quieres probar la funcionalidad de esto te basta con copiar y todo el código en el QueryManager de SQL-Server. Finalmente ejecuta el procedimiento pasándole como parámetro la variable sql que definimos arriba y comprueba el resultado.

Consultas parametrizadas con PHP y MySQL

ESTA ENTRADA ESTÁ ANTICUADA. EL USO DE LA LIBRERÍA mysql YA NO SE RECOMIENDA EN PHP POR OBSOLETO. EN ESTE ENLACE TIENES UNA OPCIÓN MEJOR, CON MySQLi. PARA VER COMO HACERLO CON PDO PRUEBA CON ESTE.

Sigo con mi desarrollo freelance en PHP (para matar estos tiempos de desempleo), y hoy me he visto en la situación de tener que usar consultas parametrizadas. ¿Por qué usar consultas parametrizadas? Básicamente por seguridad, dado que las consultas parametrizadas son la mejor opción, a día de hoy, para evitar la inyección SQL (siempre y cuando estén bien implementadas). Lo habitual en las consultas MySQL en PHP es chuzarle tal cual los parámetros, concatenando cadenas de texto, lo que es muy inseguro, como en este ejemplo:

$sql = "SELECT * FROM tabla WHERE condicion1 = ".parametro1." and condicion2 = ".parametro2."";

En Java tenemos la función PreparedStatement como una gran ayuda, pero en PHP en principio no (aunque con PDO creo que hay algo similar, pero no he trabajado con dicho framework), así que lo que haremos será crear nuestro propio método para crear consultas parametrizadas y otro para tratar los parámetros.

Pero lo primero es crear la consulta sql tal que así:

$sql = "SELECT * FROM tabla WHERE condicion1 = ? and condicion2= ?";

Este es el formato de consulta parametrizada típico de Java, utilizando interrogaciones en lugar de los valores.

Bien, una vez tenemos así la idea es generar dos funciones. La primera comprobará el tipo de parámetro, si es cadena, array, número o nulo. Si es de cadena lo devolverá entre comillas y con los caracteres especiales ya escapados. Si es un array lo devolverá como una cadena de valores separados por comas, si es un nulo devolverá la cadena NULL y si no es ninguno de esos tres dará por hecho que se trata de un número y lo devolverá tal cual. El código sería el siguiente:

function prepareParam($parametro)
{
if(is_string($parametro))
{
// Si el parámetro es una cadena retorna cadena
return "'".mysql_scape_string($parametro)."'";
}
else if(is_array($parametro))
{
// Si es un array devolvemos una lista de los parámetros
// separados por comas.
$devolver = '';
foreach($parametro as $par)
{
// Cuando retorno es vacio ('') quiere decir que no
// tenemos que añadir la coma.
if($devolver == '')
{
$devolver .= prepararParametro($par);
}
else
{
$devolver .= ','.prepararParametro($par);
}
}
return $devolver;
}
else if($parametro == NULL)
{
// Si es nulo devolvemos la cadena 'NULL'
return 'NULL';
}
else
{
// Devolvemos el parametro.
return $parametro;
}

En fin, me disculpo por enésima vez por el sangrado. En fin, Pilarín, continuamos. Ya tenemos nuestro tratamiento de parámetros, ahora nos queda hacer la función que inserte los parámetros dentro de la consulta, y esta será la siguiente. Una función que recibe la cadena con la consulta y una lista de parámetros, parte la consulta por las interrogaciones, procesa los parámetros y se los chuza dentro:

function preparedStatement($cons_sql, $param = array())
{
// Partimos la consulta por los símbolos de interrogación
$partes = explode("?", $cons_sql);

$devolver = '';
$num_parametros = count($param);

// Recorremos los parametros
for($i = 0; $i < $num_parametros; $i++)
{
// Juntamos cada parte con el parametro correspondiente preparado
//con la función antes creada.
$devolver .= $partes[$i].prepareParam($param[$i]);
}

$num_partes = count($partes);
// Si hay más partes que parametros quiere decir que hay una parte final que hay que concatenar
if($num_partes > $num_parametros)
{
$devolver.= $partes[$num_partes -1];
}

// Devolvemos la consulta preparada
return $devolver;
}

Con esto ya tenemos nuestro PreparedStatement, casero y mejorable (podríamos, por seguridad, hacer que comprobara si el número de parámetros pasado coincide con el número requerido en la consulta, por ejemplo).

Existe otra forma de parametrizar utilizando una función nativa de PHP, sin tener que recurrir a bibliotecas externas, que era la que nos enseñaban en el San Clemente cuando hice allí el ciclo (idea de Rafa Veiga, que era el profesor que daba Proyecto Integrado): La idea es utilizar la función sprintf, que funciona como un printf (si has programado en C seguro que conoces dicha función) pero no imprime en pantalla, simplemente almacena en la variable la cadena construída de forma parametrizada. Dicho así suena un poco rollo, pero con este ejemplo lo entenderás:

$sql = sprintf("SELECT * FROM pi_usuarios WHERE nick = '%s' and password = '%s'", $_POST['nick'],$_POST['passwd']);

Bueno, esto era un fragmento de código de mi proyecto de curso de PHP. Básicamente la consulta recupera todos los registros de la tabla pi_usuarios cuyos valores nick y password coincidan con los que se han pasado por un método post (si hubiera más de uno, devolvería un error, si hubiera menos también, pero eso es tema para otro día que hablemos de tratamiento de errores en php). En cualquier caso os explico: la función sprintf (al igual que printf) sustituirá los %s por valores de cadena de texto que vendrán especificados tras la coma (en este caso las variables $_POST[‘nick] y $_POST[‘passwd’]). Dichos %s van entre comillas porque van a ser tratados en la consulta sql como cadenas, la idea es que paséis entre comillas todo lo que en la consulta, de forma nativa, iría entre comillas, y sin ellas lo que no las necesite (valores numéricos, mismamente). Lo que no se es si este sistema ayuda a evitar la inyección sql de forma efectiva o no, pero al menos se ve más claro que construyendo la consulta a base de concatenar cadenas.

En fin, espero que os haya sido útil.

Paginación con PHP+MySQL

Hoy me encontraba con la necesidad de hacer uso de la paginación en un desarrollo PHP. Nunca lo había hecho previamente en este lenguaje, aunque sí había tenido que hacerlo en VB.NET (tablas paginadas a gogo en mi paso por Nática SL) y en Java. Entre la experiencia con otros lenguajes y las búsquedas en San Google he encontrado como hacerlo.

Para esto vamos a utilizar dos funciones de MySQL: SQL_CALC_FOUND_ROWS, que nos permite calcular el número de resultados de una consulta sin LIMIT, y FOUND_ROWS, que nos permite recuperar el resultado de la última ejecución de la función anterior. Estos dos métodos nos ahorrarán hacer una consulta COUNT para saber el total de resultados, que necesitaremos para calcular la cantidad de páginas que se mostrarán.

Supongo que ya sabéis crear una conexión con una base de datos MySQL en PHP, así que es lo primero que debéis hacer.

Lo siguiente es definir una variable con el número máximo de resultados a mostrar por página:

 $max = 10

En mi caso la fijé en 10 resultados. Luego hay que definir qué página se mostrará, que en principio se pedirá usando el método GET:

$pagina = (int) $_GET[‘pag’];

if($pagina<1)

{

$pagina = 1;

}

$offset = ($pagina-1)*$max;

Luego viene la creación de la consulta paginada y de la consulta para conocer el total.

$sql = «SELECT SQL_CALC_FOUND_ROWS id, name FROM clientes LIMIT $offset, $max»;

$sqlTotal = «SELECT FOUND_ROWS() as total»;

Tras esto, recogemos los Result Set de ambas consultas, con los que podemos calcular el total y almacenar los resultados.

$resultSet = mysql_query($sql);

$rsTotal = mysql_query($sqlTotal);

$filasTotal = mysql_fetch_assoc($rsTotal);

$total = $filasTotal[‘total’];

Bueno, ahora sólo nos queda crear una tabla en la que mostrar los resultados, con los enlaces a las distintas páginas debajo.

border=»1″ bordercolor=»#0000EE»>
<thead>
<tr>
<td>Id</td>
<td>Name</td>
</tr>
</thead>
<tbody>
<?php
while ($fila = mysql_fetch_assoc($resultSet))
{
$id = $fila[«id»];
$name = htmlentities($fila[«nombre»]);
?>
<tr>
<td><?php echo $id; ?></td>
<!–?php echo $name; ?>–>
</tr>
<?php
}
?>
</tbody>
<tfoot>
<tr>
colspan=»2″>
<?php
$totalPag = ceil($total/$max);
$enlaces = array();
for( $i=1; $i<=$totalPag ; $i++)
{
$enlaces[] = «href=\»?pag=$i\»>$i«;
}
echo implode(» – «, $links);
?>
</td>
</tr>
</tfoot>
</table>

Tenéis que perdonar el deficiente sangrado del código, pero al ponerlo como comentario siempre queda descojonado. En cualquier caso podéis probar a copiar y pegar en un editor como Aptana Studio, donde el sangrado automático arreglaría la cuestión.

En fin, espero que esto os sea de ayuda.

MariaDB vs MySQL

Si en su momento probé a comparar MySQL vs PostgreSQL (ganaba el primero en velocidad y el segundo en seguridad y estabilidad), ahora llega una comparación mucho más morboda: MariaDB vs MySQL.

Para los que no sepáis qué es MariaDB, se trata de un fork del SGBD MySQL. Cuando este fue compado por SUN Microsystems el creador de MySQL decidió hacer la guerra por su parte. Con la compra de Sun por parte de Oracle las alarmas sobre el futuro de MySQL saltaron, lo que hizo que el proyecto MariaDB cobrara fuerza.

La mayoría de las versiones de MariaDB están basadas en MySQL, lo cual les da la desventaja de ir siempre unas  semanas por detrás, pero la ventaja de que cuando sale su versión esta es como la de MySQL pero con los bugs corregidos y con algunas implementaciones propias de ideas recogidas de comentarios por la red de los usuarios de MySQL.

MariaDB ha sido pensado como un sustituto de MySQL, es decir, ha sido diseñado para que el usuario de MySQL pueda migrar a MariaDB con el mínimo conflicto. De hecho un cliente MariaDB puede conectarse a un servidor MySQL y viceversa. Si desinstalas tu versión de MySQL (manteniendo todos los scripts, bases de datos, procedimientos, vistas, etc) e instalas la versión de MariaDB con el mismo número (por ejemplo, si tenías MySQL 5.1.53 intalas MariaDB 5.1.53) todo funcionará igual. De hecho hay bancos de pruebas en los que afirman que es más fácil migrar los scripts de MySQL 5.0 a MariaDB 5.1 que a MySQL 5.1, yo no he probado, pero es info que viene de gente a la que respeto bastante en este terreno (y que saben bastante más que yo, que para eso son ingenieros).

Entre las ventajas que MariaDB aporta frente a MySQL está el que en el prompt del cliente está siempre visible a qué base de datos estás conectado, incluye mayor cantidad de motores de almacenamiento, al borrar una tabla es capaz de detectar si hay consultas que van a tirar de ella en las vistas y las elimina del plan de consulta (ganando velocidad y minimizando mensajes de error), permite usar «columnas virtuales» (calculadas y actualizadas en ejecución) y su caché segmentada permite un acceso más rápido a la misma.

Las ventajas de MySQL a día de hoy: el servicio técnico de pago en principio es más completo (el gratuíto creo que se lo cargaron hace un año) y siempre van a ir con unas semanas de ventaja en cuanto a actualizaciones (claro, con el handicap de que los bugs no estarán corregidos y en la de MariaDB sí).

Pero para mi, el punto que da la victoria a MariaDB es que sigue siendo totalmente libre (licencia GNU-GPL) mientras que MySQL ahora es «open core» (que suena a tienda del Corte Inglés).

Implementar la función Split en Transact-SQL

Prácticamente todos los lenguajes de programación que tienen un tipo de datos string tienen una función split. Dicha función recibe como parámetro una cadena o un caracter con el separador que queremos usar y corta la cadena sobre la que lo aplicamos por ese caracter, devolviendo generalmente un array de cadenas. Es decir, si tenemos una cadena «hola, soy, Manolito» y aplicamos un split que recibe como parámetro la coma («,») obtendríamos un array que tendría en su posición cero «hola», en su posición uno «soy» y en su posición dos «Manolito».

El caso es que en T-SQL no existe esta función, una soberana putada porque muchas veces nos va a hacer falta. Imaginad que desde un programa le tenéis que pasar un array de enteros para una comprobación ¿cómo lo hacéis? Pasáis el array a una cadena y lo metéis como parámetro, ok. Pero en ese caso lo que tenéis como parámetro no es una array de enteros, sino una cadena con enteros, y para determinadas comparaciones puede fallar. Pero tranquilos, implementar la función split no es difícil.

CREATE FUNCTION Split(@Cadena varchar(150), @Limite char(1))
RETURNS @Resultado table (word varchar(50))
AS
BEGIN
  DECLARE @Indice INT
  DECLARE @AUXILIAR varchar(200)
  SELECT @Indice = 1

  WHILE @Indice !=0
  BEGIN
    SELECT @Indice = CHARINDEX(@Limite,@Cadena)
      IF @Indice != 0
        SELECT @AUXILIAR = LEFT(@Cadena,@Indice - 1)
      ELSE
        SELECT @AUXILIAR = @Cadena

      insert into @Resultado(word) values(@AUXILIAR)

      SELECT @Cadena = RIGHT(@Cadena,LEN(@Cadena) - @Indice)
      IF LEN(@Cadena) = 0 BREAK
  END

RETURN
END

Si copiáis y pegáis debería funcionar a la perfección (sólo la he testeado en SQL-Server pero debería tirar en MySQL, PostgreSQL y, en general, en todos los SGBD que tiren de T-SQL). Edito para comentar que obviamente esto devuelve una tabla, no un array ni un string.

PostgreSQL vs MySQL

¿Qué animal te gusta más?¿El delfín o el elefante? Es una pregunta complicada, a fin de cuentas ambos son dos mamíferos simpáticos, así que a la hora de elegir un SGBD no será la mascota quien decante la balanza hacia un lado u otro.

Haciendo un poco de historia, Postgres es más veterano. El proyecto nació en la universidad de Berkeley en el año del mundial de Naranjito (1982), aunque no incluyó un intérprete de SQL hasta 1995 (antes utilizaba un lenguaje propio, el Postquel), cuando Andrew Yu y Jolly Chen lo metieron en la versión 4.2, dando lugar a Postgres95, que luego se convertiría en PostgreSQL (bajo licencia BSD), y que a principios de la década de los ’00 sería el SGBD más popular. Por su parte MySQL, creado por la empresa sueca MySQL AB (y está bajo licencia GPL desde la versión 3.2), nació a finales de los 90 y allá por 2004, con su versión 4.1, ya se había convertido en el SGBD de código abierto más popular, por encima de PostgreSQL. Desde aquella ha permanecido en el número 1 de forma incuestionable, aunque en los últimos meses se está viendo un cambio de tendencia, con muchos usuarios volviendo a PostgreSQL.

Este cambio se debe a que, en 2008, MySQL AB fue adquirida por SUN Microsystems (hasta ahí, sin problemas), empresa que fue comprada en abril de 2009 por la multinacional Oracle (ahí empezó el mosqueo). Oracle tradicionalmente ha sido una empresa vinculada a la filosofía del software propietario, pioneros en la innovación de complejos sistemas anticopia para sus productos y con fama de “peseteros” (dicen que a su lado las hordas de Gates y Jobs parecerían discípulos de Stallman). Las primeras medidas de Oracle fueron encarecer las tarifas de soporte y cargarse las gratuitas, lo que puso la mosca tras la oreja a muchos usuarios de MySQL. Además, la existencia de un SGBD privativo (y bastante caro) de Oracle lleva a muchos a pensar que puede haber un conflicto de intereses, que puede llevar a Oracle a dejar un poco de lado MySQL para centrarse en su producto privativo.

No me meteré a buscar diferencias en sus motores, sus funciones o sus funcionalidades, dado que no los he estudiado tan profundamente y mi conocimiento se basa, simplemente, en el uso que he dado a los mismos en proyectos Java o PHP. Estudiando DAI mayoritariamente utilizaba MySQL para ese tipo de proyectos (y alguna vez MS-SQLServer de Microsoft, aunque comparando a nivel de usuario creo que no merece la pena pagar el precio de la licencia disponiendo, gratuitamente, de dos SGBD tan potentes como estos, sin contar las implicaciones morales de las licencias de uno u otro), aunque en los últimos meses he estado probando PostgreSQL.

A la hora de utilizar ambos SGBD en Java apenas he notado diferencias, en cuanto a funciones existentes. En PHP en teoría hay más funciones para MySQL, pero yo al menos no he notado que falte ninguna esencial, y hasta me parece más flexible a la hora de realizar la conexión a la base de datos. MySQL supera a PostgreSQL en todo lo referente a velocidad, tanto en consultas pequeñas como en las más grandes (para 1.000.000 de inserciones con datos aleatorios, en el mismo equipo, MySQL lo hace en un 25% menos de tiempo). En cambio el elefante gana en otros campos: tanto a la hora de mantener la integridad referencial, a la hora de usar triggers, en estabilidad y seguridad, a la hora de utilizarlo para programar cosas complejas o en cuanto a facilidad de uso. MySQL tiene más funciones predefinidas, aunque no permite crear tipos de datos definidos por el usuario como si lo hace Postgres. Si se trabaja con datos del tipo “TIME”, Postgres da mucha mayor precisión que MySQL (en determinados casos esto puede ser importante, en otros trivial). A la hora de la instalación, tanto en Windows como en Linux el premio es para los chicos de Berkeley, y de hecho en Windows XP da bastante la lata instalar el Workbench (entorno gráfico) de MySQL.

En resumen ¿Cual es mejor? Es difícil decidirlo. El debate en internet es encarnizado y lleva abierto el último lustro, con fanboys de ambos SGBD tirándose los trastos a la cabeza. Por las características de cada uno, bien diferentes, la conveniencia de usar uno u otro es una cuestión más del ámbito del uso que se le dará al mismo que de las características intrínsecas de cada software. PostgreSQL seguramente sea más indicado para aplicaciones complejas o que requieran una mayor seguridad (datos bancarios, datos sanitarios) mientras que MySQL se lleva la palma en cuanto a velocidad y bajo consumo de recursos, haciéndolo más adecuado para almacenar usuarios de una página web sin datos trascendentales, por ejemplo.