SELECT id, nombre FROM prueba_persona;
id | nombre
----+---------------------
1 | CARLOS PEREZ
2 | Carmen Pereira
3 | Ricardo Gonzalez
4 | gonzalo Perez
5 | PERICLES RICAURTE
6 | perico portocarrero
(6 filas)
Con estos datos, si quisiéramos obtener los nombres que contengan la cadena 'car' esperaríamos obtener las filas 1, 2, 3 y 6, pero si efectuamos la consulta obtendremos lo siguiente:
SELECT id, nombre FROM persona WHERE nombre LIKE '%car%';
id | nombre
----+---------------------
3 | Ricardo Gonzalez
6 | perico portocarrero
(2 filas)
Porque el motor de Bases de Datos distingue entre mayúsculas y minúsculas como caracteres diferentes. Una solución rápida consiste en modificar la consulta así:
SELECT id, nombre FROM persona WHERE lower(nombre) LIKE '%car%';
id | nombre
----+---------------------
1 | CARLOS PEREZ
2 | Carmen Pereira
3 | Ricardo Gonzalez
6 | perico portocarrero
(4 filas)
En esta consulta estamos primero pasando el atributo a minúsculas y sobre el texto modificado efectuamos la consulta. De este modo podremos obtener los datos que realmente buscamos. Hay que aclarar que no se modifican los valores del atributo dentro de la tabla sino en el búfer de búsqueda.
Sin embargo, si hacemos un uso recurrente de este tipo de consultas, es mejor usar un método más eficiente. Si no importa la mezcla de minúsculas y mayúsculas podemos modificar el valor del campo en un trigger antes de hacer el INSERT y almacenar el texto en minúsculas:
CREATE OR REPLACE FUNCTION modificar_nombre_persona() RETURNS TRIGGER AS $$
BEGIN
NEW.nombre := lower(NEW.nombre);
RETURN NEW;
END
$$
LANGUAGE 'plpgsql';
CREATE TRIGGER persona_antes_insertar BEFORE INSERT ON persona FOR EACH ROW EXECUTE PROCEDURE modificar_nombre_persona();
De este modo al ingresar los datos éstos quedarán almacenados así:
SELECT id, nombre_busquedas FROM prueba_persona;
id | nombre_busquedas
----+---------------------
1 | carlos perez
2 | carmen pereira
3 | ricardo gonzalez
4 | gonzalo perez
5 | pericles ricaurte
6 | perico portocarrero
(6 filas)
Y al hacer la misma búsqueda obtendremos los siguiente resultados:
SELECT id, nombre FROM persona WHERE nombre LIKE '%car%';
id | nombre_busquedas
----+---------------------
1 | carlos perez
2 | carmen pereira
3 | ricardo gonzalez
6 | perico portocarrero
(4 filas)
Pero si es necesario conservar la forma escrita por el usuario, podemos crear un campo adicional, en el que almacenaremos el valor en minúsculas y no alteraremos el campo original.
ALTER TABLE persona ADD nombre_busquedas varchar(255);
CREATE OR REPLACE FUNCTION crear_nombre_busquedas_persona() RETURNS TRIGGER AS $$
BEGIN
NEW.nombre_busquedas := lower(NEW.nombre);
RETURN NEW;
END
$$
LANGUAGE 'plpgsql';
CREATE TRIGGER persona_antes_insertar BEFORE INSERT ON persona FOR EACH ROW EXECUTE PROCEDURE crear_nombre_busquedas_persona();
En este caso los datos quedarían almacenados así:
SELECT * FROM persona;
id | nombre | nombre_busquedas
----+---------------------+---------------------
1 | CARLOS PEREZ | carlos perez
2 | Carmen Pereira | carmen pereira
3 | Ricardo Gonzalez | ricardo gonzalez
4 | gonzalo Perez | gonzalo perez
5 | PERICLES RICAURTE | pericles ricaurte
6 | perico portocarrero | perico portocarrero
(6 filas)
Y la consulta se haría así:
SELECT id, nombre FROM persona WHERE nombre_busquedas LIKE '%car%';
id | nombre
----+---------------------
1 | CARLOS PEREZ
2 | Carmen Pereira
3 | Ricardo Gonzalez
6 | perico portocarrero
(4 filas)
Mediante cualquiera de estas dos formas evitaremos el uso de funciones adicionales en la consulta y obtendremos un poco más de eficiencia.
Eso es todo!
PDTA: También habría que ejecutar los triggers antes de actualizar.