Tipos de Datos Avanzados en PostgreSQL

PostgreSQLBeginner
Practicar Ahora

Introducción

En este laboratorio, explorará los tipos de datos avanzados de PostgreSQL, centrándose en JSON/JSONB, arrays y UUIDs. Aprenderá a almacenar, consultar y manipular datos dentro de estos tipos.

El laboratorio comienza demostrando cómo almacenar y consultar datos JSON y JSONB, incluyendo la creación de una tabla con una columna JSONB, la inserción de datos JSON y el uso de operadores como -> y ->> para extraer valores específicos. Luego, procederá a aprender sobre las columnas de array y los UUIDs.

Almacenar y Consultar Datos JSON y JSONB

En este paso, aprenderá a almacenar y consultar datos JSON y JSONB en PostgreSQL. PostgreSQL proporciona dos tipos de datos para almacenar datos JSON: JSON y JSONB. El tipo de datos JSON almacena una copia exacta del texto de entrada JSON, mientras que el tipo de datos JSONB almacena datos JSON en un formato binario descompuesto. Generalmente se prefiere JSONB porque ofrece un mejor rendimiento para la consulta y la indexación.

Comencemos abriendo la shell de PostgreSQL. Primero, conéctese a la base de datos labex:

sudo -u postgres psql -d labex

Debería ver el prompt de PostgreSQL:

labex=#

Ahora, creemos una tabla para almacenar datos JSONB:

CREATE TABLE products (id SERIAL PRIMARY KEY, data JSONB);

Este comando SQL crea una tabla llamada products. La tabla tiene dos columnas: id (una clave primaria entera de auto-incremento) y data (una columna JSONB para almacenar datos JSON).

Debería ver una salida similar a esta:

CREATE TABLE

Ahora, insertemos algunos datos en la tabla products:

INSERT INTO products (data) VALUES ('{"name": "Laptop", "price": 1200, "features": ["16GB RAM", "512GB SSD"]}');
INSERT INTO products (data) VALUES ('{"name": "Keyboard", "price": 75, "features": ["Mechanical", "RGB Backlight"]}');

Estos comandos insertan dos filas en la tabla products. Cada fila contiene un objeto JSON con información sobre un producto.

Debería ver una salida similar a esta para cada inserción:

INSERT 0 1

Para consultar los datos JSON, puede utilizar los operadores -> y ->>. El operador -> devuelve un objeto JSON, mientras que el operador ->> devuelve un valor JSON como texto.

Por ejemplo, para recuperar el nombre del primer producto, puede utilizar la siguiente consulta:

SELECT data ->> 'name' FROM products WHERE id = 1;

Este comando selecciona el valor asociado con la clave name de la columna data de la tabla products, donde el id es 1. El operador ->> asegura que el resultado se devuelva como texto.

Debería ver una salida similar a esta:

  ?column?
----------
 Laptop
(1 row)

También puede consultar objetos JSON anidados. Por ejemplo, para recuperar la primera característica del primer producto, puede utilizar la siguiente consulta:

SELECT data -> 'features' ->> 0 FROM products WHERE id = 1;

Este comando primero selecciona el array features de la columna data, y luego selecciona el elemento en el índice 0 del array. El operador ->> asegura que el resultado se devuelva como texto.

Debería ver una salida similar a esta:

  ?column?
----------
 16GB RAM
(1 row)

También puede utilizar el operador @> para comprobar si un objeto JSON contiene un par clave-valor específico. Por ejemplo, para encontrar todos los productos con un precio de 75, puede utilizar la siguiente consulta:

SELECT data ->> 'name' FROM products WHERE data @> '{"price": 75}';

Este comando selecciona el nombre de todas las filas de la tabla products donde la columna data contiene un objeto JSON con una clave price y un valor de 75.

Debería ver una salida similar a esta:

  ?column?
----------
 Keyboard
(1 row)

¡Genial! Hemos creado con éxito nuestra primera tabla con datos JSONB y hemos aprendido a consultarla. Continuaremos trabajando con esta tabla en el siguiente paso para añadir funcionalidades más avanzadas.

Añadir Columnas de Array a Tabla Existente

En este paso, aprenderá a añadir y manipular columnas de array en PostgreSQL. Ampliaremos nuestra tabla products existente añadiendo una columna de array para almacenar etiquetas (tags). Las columnas de array le permiten almacenar múltiples valores del mismo tipo de dato en una sola columna, lo cual es útil para almacenar listas de elementos como etiquetas, categorías o características.

Dado que ya estamos conectados a la base de datos y tenemos nuestra tabla products del paso anterior, añadamos columnas de array a nuestra tabla existente:

ALTER TABLE products ADD COLUMN name VARCHAR(255);
ALTER TABLE products ADD COLUMN tags TEXT[];

Estos comandos añaden dos nuevas columnas a nuestra tabla products existente: name (una cadena de texto) y tags (un array de cadenas de texto). El tipo de dato TEXT[] especifica que la columna tags es un array de valores de texto.

Debería ver una salida similar a esta para cada comando ALTER:

ALTER TABLE

Ahora, actualicemos nuestros datos existentes e insertemos nuevos datos con las nuevas columnas:

UPDATE products SET name = data ->> 'name' WHERE id = 1;
UPDATE products SET name = data ->> 'name' WHERE id = 2;
UPDATE products SET tags = ARRAY['electronics', 'computers', 'portable'] WHERE id = 1;
UPDATE products SET tags = ARRAY['electronics', 'accessories', 'input'] WHERE id = 2;

Estos comandos actualizan nuestros productos existentes con información de nombre y etiquetas extraída de los datos JSONB y nuevos valores de array.

Debería ver una salida similar a esta para cada actualización:

UPDATE 1

Para consultar los datos del array, puede utilizar la indexación de arrays. Los índices de array en PostgreSQL comienzan en 1.

Por ejemplo, para recuperar la primera etiqueta del primer producto, puede utilizar la siguiente consulta:

SELECT tags[1] FROM products WHERE id = 1;

Este comando selecciona el elemento en el índice 1 del array tags de la tabla products, donde el id es 1.

Debería ver una salida similar a esta:

   tags
-----------
 electronics
(1 row)

También puede utilizar la función UNNEST para expandir un array en un conjunto de filas.

Por ejemplo, para recuperar todas las etiquetas de todos los productos, puede utilizar la siguiente consulta:

SELECT name, UNNEST(tags) AS tag FROM products;

Este comando selecciona el name y cada tag individual del array tags, creando una nueva fila por cada etiqueta.

Debería ver una salida similar a esta:

  name   |     tag
---------+-------------
 Laptop  | electronics
 Laptop  | computers
 Laptop  | portable
 Keyboard| electronics
 Keyboard| accessories
 Keyboard| input
(6 rows)

Puede utilizar el operador @> para comprobar si un array contiene un valor específico.

Por ejemplo, para encontrar todos los productos con la etiqueta 'electronics', puede utilizar la siguiente consulta:

SELECT name FROM products WHERE tags @> ARRAY['electronics'];

Este comando selecciona el nombre de todas las filas de la tabla products donde el array tags contiene el valor 'electronics'.

Debería ver una salida similar a esta:

  name
----------
 Laptop
 Keyboard
(2 rows)

También puede utilizar el operador && para comprobar si dos arrays tienen algún elemento en común.

Por ejemplo, para encontrar todos los productos que comparten alguna etiqueta con el primer producto, puede utilizar la siguiente consulta:

SELECT p2.name FROM products p1, products p2 WHERE p1.id = 1 AND p1.tags && p2.tags AND p2.id != 1;

Este comando selecciona el nombre de todas las filas de la tabla products (con alias p2) que tienen al menos una etiqueta en común con las etiquetas del primer producto (con alias p1), excluyendo el primer producto en sí.

Debería ver una salida similar a esta:

  name
----------
 Keyboard
(1 row)

¡Perfecto! Hemos añadido con éxito columnas de array a nuestra tabla existente y hemos aprendido a trabajar con arrays. Nuestra tabla products ahora contiene tipos de datos JSONB y de array, lo que la prepara para el siguiente paso.

Añadir Columna UUID y Aprender Generación de UUID

En este paso, aprenderá a generar y utilizar UUIDs (Identificadores Únicos Universales) en PostgreSQL. Los UUIDs son números de 128 bits diseñados para ser únicos en el espacio y el tiempo. A menudo se utilizan como identificadores únicos en tablas de bases de datos para evitar conflictos al fusionar datos de diferentes fuentes.

Dado que continuamos con nuestra sesión y tabla existentes, añadiremos una columna UUID a nuestra tabla products actual para demostrar la funcionalidad de UUID.

Primero, habilitemos la extensión UUID que proporciona funciones de generación de UUID:

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

Este comando crea la extensión uuid-ossp si aún no existe.

Debería ver una salida similar a esta:

CREATE EXTENSION

Ahora, añadamos una columna UUID a nuestra tabla products existente:

ALTER TABLE products ADD COLUMN uuid_id UUID;

Este comando añade una nueva columna UUID a nuestra tabla products existente.

Debería ver una salida similar a esta:

ALTER TABLE

Ahora podemos actualizar nuestras filas existentes con valores UUID utilizando la función uuid_generate_v4():

UPDATE products SET uuid_id = uuid_generate_v4() WHERE id = 1;
UPDATE products SET uuid_id = uuid_generate_v4() WHERE id = 2;

Estos comandos actualizan nuestros productos existentes con valores UUID únicos. La función uuid_generate_v4() genera un nuevo UUID para cada fila.

Debería ver una salida similar a esta para cada actualización:

UPDATE 1

Para consultar los datos utilizando UUIDs, puede utilizar los valores UUID en sus cláusulas WHERE. Dado que los UUIDs se generan aleatoriamente, primero veamos nuestros datos actuales:

SELECT id, name, uuid_id FROM products;

Este comando selecciona todas las columnas de la tabla products para ver los UUIDs generados junto con nuestros otros datos.

Debería ver una salida similar a esta (su UUID será diferente):

                  id
------------------------------------
 a1b2c3d4-e5f6-7890-1234-567890abcdef
(1 row)

Ahora, utilice ese UUID en el siguiente comando, reemplazando <YOUR_UUID_HERE> con el UUID real que recuperó:

SELECT name FROM products WHERE id = '<YOUR_UUID_HERE>';

Este comando selecciona el name de la tabla products donde el id coincide con el UUID especificado.

Debería ver una salida similar a esta (dependiendo del UUID que haya elegido):

  name
----------
 Laptop
(1 row)

Finalmente, limpiemos la tabla y la extensión que creamos:

DROP TABLE products;
DROP EXTENSION "uuid-ossp";

Debería ver una salida similar a esta para cada comando DROP:

DROP TABLE
DROP EXTENSION

Extraer Datos de Tipos Avanzados

En este último paso, practicará la extracción de datos de todos los tipos de datos avanzados que hemos añadido a nuestra tabla products a lo largo de este laboratorio. Nuestra tabla ahora contiene columnas JSONB, de array y UUID, proporcionando un ejemplo completo de los tipos de datos avanzados de PostgreSQL.

Dado que continuamos con nuestra sesión y tabla existentes, podemos empezar inmediatamente a trabajar con los datos que hemos estado construyendo a través de los pasos anteriores.

Primero, añadamos algunos datos JSONB adicionales para hacer nuestros ejemplos de extracción más completos:

UPDATE products SET data = '{"brand": "Dell", "model": "XPS 13", "specs": {"ram": "16GB", "storage": "512GB SSD"}, "warranty": "3 years"}' WHERE id = 1;
UPDATE products SET data = '{"brand": "Logitech", "model": "G915", "specs": {"type": "Mechanical", "backlight": "RGB"}, "warranty": "2 years"}' WHERE id = 2;

Estos comandos actualizan nuestros datos JSONB existentes con información más detallada, incluyendo objetos anidados y campos adicionales.

Debería ver una salida similar a esta para cada actualización:

UPDATE 1

Ahora practiquemos la extracción de datos de todos nuestros tipos de datos avanzados. Para extraer datos de la columna JSONB data, puede utilizar los operadores -> y ->>. Por ejemplo, para extraer la marca de nuestros datos actualizados:

SELECT data ->> 'brand' FROM products WHERE id = 1;

Este comando recupera el valor asociado con la clave brand de la columna data.

Debería ver una salida similar a esta:

 ?column?
----------
 Dell
(1 row)

Para extraer datos anidados de la columna JSONB, puede encadenar los operadores -> y ->>. Por ejemplo, para extraer la especificación de RAM:

SELECT data -> 'specs' ->> 'ram' FROM products WHERE id = 1;

Este comando recupera el valor asociado con la clave ram dentro del objeto specs.

Debería ver una salida similar a esta:

 ?column?
----------
 16GB
(1 row)

Para extraer datos de la columna tags (array), puede utilizar la indexación de arrays, como aprendió en el Paso 2. Por ejemplo, para extraer la primera etiqueta del primer producto:

SELECT tags[1] FROM products WHERE id = 1;

Este comando recupera el elemento en el índice 1 del array tags de la tabla products donde el id es 1.

Debería ver una salida similar a esta:

   tags
-----------
 electronics
(1 row)

Ahora creemos una consulta completa que extraiga datos de todos nuestros tipos de datos avanzados: JSONB, arrays y UUIDs:

SELECT
    id,
    name,
    data ->> 'brand' AS brand,
    data -> 'specs' ->> 'ram' AS ram,
    tags[1] AS first_tag,
    uuid_id
FROM products;

Este comando recupera datos de todos los tipos de datos avanzados con los que hemos trabajado: el id entero, el name, la brand de la columna JSONB data, la especificación anidada ram, el primer elemento del array tags y el uuid_id.

Debería ver una salida similar a esta:

   name   |  ?column?  |   tags
----------+------------+-----------
 Laptop   | Dell       | electronics
 Keyboard | Logitech   | electronics
(2 rows)

¡Excelente! Ha trabajado con éxito con los tres tipos de datos avanzados de PostgreSQL en una sola tabla. Este ejemplo completo demuestra cómo JSONB, arrays y UUIDs se pueden utilizar juntos para crear esquemas de bases de datos flexibles y potentes.

Cuando haya terminado con todos los pasos, puede salir del shell de PostgreSQL escribiendo:

\q

También puede optar por conservar la tabla para seguir experimentando con los tipos de datos avanzados de PostgreSQL.

Resumen

En este laboratorio, construyó y trabajó progresivamente con una tabla products completa que demuestra los tipos de datos avanzados de PostgreSQL en acción. Comenzó creando una tabla con columnas JSONB y aprendió a almacenar y consultar datos JSON utilizando operadores como -> y ->>.

Luego extendió la tabla añadiendo columnas de array, aprendiendo a almacenar múltiples valores en una sola columna y a consultarlos utilizando indexación de arrays y funciones como UNNEST. A continuación, añadió funcionalidad UUID habilitando la extensión uuid-ossp y añadiendo una columna UUID para generar identificadores únicos.

Finalmente, practicó técnicas de extracción de datos completas que combinaron los tres tipos de datos avanzados (JSONB, arrays y UUIDs) en consultas sofisticadas. Este enfoque paso a paso demostró cómo estos tipos de datos pueden trabajar juntos en esquemas de bases de datos del mundo real, proporcionando flexibilidad y potentes capacidades de consulta para aplicaciones modernas.