- Funciones nativas (ISJSON, JSON_VALUE/JSON_QUERY/MODIFY, OPENJSON) y agregados permiten consultar y formatear JSON en SQL Server.
- BigQuery ofrece tipo JSON nativo con acceso por punto/subíndice, UNNEST y conversión LAX; en PostgreSQL destacan los operadores -> y ->>.
- Para rendimiento, combina JSON con columnas indexadas, Columnstore o índices funcionales; valida con CHECK o en la capa de aplicación.
- En migraciones Oracle→PostgreSQL mapea JSON_TABLE a json_array_elements y usa JSON_BUILD_OBJECT/JSON_AGG para construir resultados.

Trabajar con datos semiestructurados ya no es opcional: JSON se ha convertido en el idioma común para APIs, apps móviles y registros, y los motores SQL modernos han respondido con funciones nativas y patrones de diseño para integrarlo sin fricciones. En esta guía práctica vas a encontrar cómo consultarlo, transformarlo y almacenarlo de forma eficiente en SQL Server, Azure SQL, PostgreSQL, Oracle y BigQuery, con ejemplos comentados y recomendaciones de rendimiento.
Más allá de las demos, el objetivo es operativo: explicar qué hacer en cada plataforma, dónde están las diferencias (por ejemplo, operadores, tipos nativos y límites), y qué índices o formatos conviene usar para que las consultas JSON escalen. También verás patrones de importación desde ficheros y servicios, y cómo abordar migraciones entre motores cuando hay funciones JSON específicas de cada proveedor.
Qué es JSON en el mundo SQL y dónde se aplica
JSON es un formato de texto popular para intercambio de datos que brilla en escenarios web, móviles y microservicios. SQL Server, Azure SQL Database, Azure SQL Managed Instance, Azure Synapse Analytics y SQL Database en Microsoft Fabric incorporan funciones para analizar, consultar y formatear JSON directamente en T‑SQL. Ejemplo de documento típico: [ { \”name\”: \”John\”, \”skills\”: [ \”SQL\”, \”C#\”, \”Azure\” ] }, { \”name\”: \”Jane\”, \”surname\”: \”Doe\” } ].

Con estas funciones puedes leer valores escalares, extraer objetos o arrays, modificar propiedades sin reescribir todo el documento, aplanar colecciones en filas y devolver resultados como JSON listo para tu API. Además, se combinan sin problema con columnas relacionales, agregados de ventana y cláusulas WHERE/ORDER BY/GROUP BY.
Novedades y compatibilidad: del texto nvarchar al tipo JSON nativo
Históricamente en SQL Server, el JSON se almacenaba en nvarchar/varchar y se procesaba con funciones nativas. SQL Server 2025 (17.x) introduce en versión preliminar un tipo de datos JSON nativo que guarda el documento en formato binario analizado para lecturas, escrituras y compresión más eficientes. Esto convive con el modelo clásico: las funciones ISJSON/JSON_VALUE/JSON_QUERY/JSON_MODIFY y OPENJSON siguen siendo la vía recomendada para consultar y transformar el contenido.
Conviene matizar compatibilidad: en documentación previa verás que “JSON no es un tipo integrado” en ciertas ediciones; la introducción del tipo nativo llega más tarde y puede no estar disponible en todos los entornos. Por eso, elige nvarchar(max) o el nuevo tipo JSON en función de la plataforma, y mantén el acceso a través de las funciones JSON para asegurar portabilidad y rendimiento.
Funciones esenciales de JSON en SQL Server
El núcleo del soporte T‑SQL se apoya en utilidades muy directas: ISJSON (valida), JSON_VALUE (extrae escalares), JSON_QUERY (devuelve objetos/arrays) y JSON_MODIFY (actualiza rutas). Estas funciones permiten filtrar, ordenar y agrupar por valores almacenados dentro del documento JSON sin necesidad de sacarlo de la base.
Ejemplo de mezcla relacional+JSON con filtros y ordenación por rutas JSON: selecciona campos de People y extrae código postal, dirección y skills.
SELECT Name,
Surname,
JSON_VALUE(jsonCol, '$.info.address.PostCode') AS PostCode,
JSON_VALUE(jsonCol, '$.info.address."Address Line 1"') + ' ' +
JSON_VALUE(jsonCol, '$.info.address."Address Line 2"') AS Address,
JSON_QUERY(jsonCol, '$.info.skills') AS Skills
FROM People
WHERE ISJSON(jsonCol) > 0
AND JSON_VALUE(jsonCol, '$.info.address.Town') = 'Belgrade'
AND Status = 'Active'
ORDER BY JSON_VALUE(jsonCol, '$.info.address.PostCode');
Para actualizar una propiedad concreta sin reescribir el documento: JSON_MODIFY localiza la ruta y sustituye el valor.
DECLARE @json nvarchar(max) = '{"info": {"address": [{"town":"Belgrade"},{"town":"Paris"},{"town":"Madrid"}]}}';
SET @json = JSON_MODIFY(@json, '$.info.address[1].town', 'London');
SELECT @json; -- {"info":{"address":[{"town":"Belgrade"},{"town":"London"},{"town":"Madrid"}]}}
De JSON a tablas con OPENJSON
Para aplanar colecciones JSON y consultarlas con SELECT, OPENJSON convierte arrays u objetos en filas/columnas y permite tipado explícito con la cláusula WITH. Entre sus reglas: convierte al tipo indicado, soporta jerarquías y devuelve NULL si falta un campo; además puedes marcar rutas como strict para exigir que existan.
DECLARE @json nvarchar(max) = N'[
{"id":2, "info":{"name":"John", "surname":"Smith"}, "age":25},
{"id":5, "info":{"name":"Jane", "surname":"Smith"}, "dob":"2005-11-04T12:00:00"}
]';
SELECT *
FROM OPENJSON(@json)
WITH (
id int 'strict $.id',
firstName nvarchar(50) '$.info.name',
lastName nvarchar(50) '$.info.surname',
age int,
dateOfBirth datetime2 '$.dob'
);
Si el documento incluye subarrays (por ejemplo, skills dentro de info), encadena otro OPENJSON con APPLY para expandirlo y unirlo al registro padre. OUTER APPLY repetirá la fila de la entidad por cada elemento del subarray (útil para informes o normalizaciones parciales).
DECLARE @json nvarchar(max) = N'[
{"id":2, "info":{"name":"John", "surname":"Smith"}, "age":25},
{"id":5, "info":{"name":"Jane", "surname":"Smith", "skills":["SQL","C#","Azure"]},
"dob":"2005-11-04T12:00:00"}
]';
SELECT id, firstName, lastName, age, dateOfBirth, skill
FROM OPENJSON(@json)
WITH (
id int 'strict $.id',
firstName nvarchar(50) '$.info.name',
lastName nvarchar(50) '$.info.surname',
age int,
dateOfBirth datetime2 '$.dob',
skills nvarchar(max) '$.info.skills' AS JSON
) AS P
OUTER APPLY OPENJSON(P.skills) WITH (skill nvarchar(32) '$');
Una alternativa muy práctica cuando solo quieres validación y extracción ligera es JSON_VALUE para campos escalares con índices en expresiones. Así se obtiene rendimiento al filtrar por rutas frecuentes.
De tablas a JSON: FOR JSON y agregados nativos
Cuando la aplicación o tu API necesitan JSON, FOR JSON delega el formateo en el motor. Con PATH puedes anidar usando alias con puntos; AUTO deriva estructura según las tablas/joins. Es ideal para OData, AJAX o frontends en JavaScript.
SELECT id,
firstName AS "info.name",
lastName AS "info.surname",
age,
dateOfBirth AS dob
FROM People
FOR JSON PATH;
Además, dispones de agregados JSON para construir estructuras desde grupos: JSON_OBJECTAGG (objetos) y JSON_ARRAYAGG (arrays). Simplifican la creación de payloads agregados sin salir de SQL.
Almacenamiento, indexación y rendimiento en SQL Server
Para almacenar documentos completos, la opción universal es nvarchar(max) (o json nativo cuando esté disponible). Valida con CHECK(ISJSON(col)=1) si necesitas asegurar integridad de formato, y exponte campos clave con columnas calculadas para indexar propiedades usadas en búsquedas.
CREATE TABLE WebSite.Logs (
[_id] bigint IDENTITY PRIMARY KEY,
[log] nvarchar(max),
[severity] AS JSON_VALUE([log], '$.severity'),
INDEX ix_severity (severity)
);
-- Opcional: forzar JSON válido
ALTER TABLE WebSite.Logs
ADD CONSTRAINT CK_Log_JSON CHECK (ISJSON([log]) = 1);
Para cargas analíticas y archivado masivo, un índice Columnstore agrupado en la colección aporta compresión y escaneos rápidos. Si predomina la escritura/actualización de documentos, considera tablas optimizadas para memoria (con la salvedad de tipos soportados) y procedimientos compilados nativamente para operaciones de actualización con JSON_MODIFY.
CREATE TABLE WebSite.Logs (
[_id] bigint IDENTITY PRIMARY KEY NONCLUSTERED,
[log] nvarchar(max)
) WITH (MEMORY_OPTIMIZED = ON);
GO
CREATE PROCEDURE WebSite.UpdateData
@Id int, @Property nvarchar(100), @Value nvarchar(100)
WITH SCHEMABINDING, NATIVE_COMPILATION
AS
BEGIN ATOMIC WITH (transaction isolation level = snapshot, language = N'English')
UPDATE WebSite.Logs
SET [log] = JSON_MODIFY([log], @Property, @Value)
WHERE _id = @Id;
END;
Como patrón híbrido, desnormaliza lo variable en JSON y conserva relacional lo consultado a menudo. En informes, usa OPENJSON con WITH para preparar datasets rectangulares, y añade índices sobre JSON_VALUE() cuando la ruta se usa en filtros/ordenaciones.
Carga e importación desde archivos y servicios
Si recibes JSON desde ficheros o endpoints REST, puedes cargarlo tal cual y parsearlo en SQL. Con acceso a archivos locales o compartidos, el motor admite operaciones bulk; para orígenes distribuidos como Hadoop o Azure Blob, PolyBase permite ingerir texto JSON y mapearlo con OPENJSON/JSON_VALUE en T‑SQL.
DECLARE @jsonVariable nvarchar(max) = N'[
{ "Order": {"Number":"SO43659", "Date":"2011-05-31T00:00:00"},
"AccountNumber":"AW29825", "Item": {"Price":2024.9940, "Quantity":1}},
{ "Order": {"Number":"SO43661", "Date":"2011-06-01T00:00:00"},
"AccountNumber":"AW73565", "Item": {"Price":2024.9940, "Quantity":3}}
]';
SELECT SalesOrderJsonData.*
FROM OPENJSON(@jsonVariable, '$') WITH (
Number varchar(200) '$.Order.Number',
Date datetime '$.Order.Date',
Customer varchar(200) '$.AccountNumber',
Quantity int '$.Item.Quantity'
) AS SalesOrderJsonData;
Cuando el tipo json nativo esté disponible en tu plataforma, aprovéchalo por eficiencia de E/S y compresión; si no, nvarchar(4000) ofrece ventajas de rendimiento frente a nvarchar(max) si sabes que los documentos no superan 8 KB.
Casos de uso y modelo híbrido
Los mejores candidatos para JSON en SQL incluyen modelos de datos con atributos variables (e‑commerce), telemetría y logs, IoT semiestructurado con análisis casi en tiempo real y exposición REST desde SQL a frontends. La recomendación general es desnormalizar lo necesario, mantener claves de consulta como columnas escalares e indexar rutas críticas.
En escenarios de seguridad o internacionalización, JSON se comporta como texto y se beneficia de todas las características del motor (tablas temporales, seguridad a nivel de fila, etc.). Esto facilita políticas uniformes y evita excepciones en pipelines mixtos.
BigQuery: tipo JSON nativo y consulta con GoogleSQL
BigQuery ofrece un tipo de datos JSON nativo con acceso a campos por operador de punto y subíndice. Puedes crear valores JSON con literales JSON, PARSE_JSON (convierte STRING a JSON), TO_JSON (convierte tipos SQL a JSON), y construir arrays con JSON_ARRAY u objetos con JSON_OBJECT.
-- Crear tabla con columna JSON
CREATE OR REPLACE TABLE mydataset.table1 (
id INT64,
cart JSON
);
-- Insertar literales JSON
INSERT INTO mydataset.table1 VALUES
(1, JSON '{"name":"Alice","items":[{"product":"book","price":10},{"product":"food","price":5}]}'),
(2, JSON '{"name":"Bob","items":[{"product":"pen","price":20}]}');
-- Acceso por punto y subíndice
SELECT cart.name, cart.items[0] AS first_item
FROM mydataset.table1;
Para listas, JSON_QUERY_ARRAY extrae ARRAY<JSON> y con UNNEST puedes expandir a filas. Si necesitas volver a compactar, usa ARRAY_AGG. Para comparaciones/ordenación, JSON_VALUE devuelve escalares como STRING SQL, y funciones LAX_* (por ejemplo LAX_INT64) convierten con tolerancia.
-- Expandir items y leer el campo product
SELECT id, JSON_VALUE(item.product) AS product
FROM mydataset.table1,
UNNEST(JSON_QUERY_ARRAY(cart.items)) AS item
ORDER BY id;
-- Conversión flexible de tipos
SELECT LAX_INT64(JSON '"10"') AS id; -- 10
Importante con valores nulos: el null de JSON no es el NULL de SQL. JSON_QUERY puede devolver null JSON; JSON_VALUE devuelve NULL SQL si no hay escalar. Tenlo en cuenta en filtros y agregaciones.
Limitaciones y carga: profundidad máxima 500 de anidación; no puedes particionar o clusterizar por columnas JSON (no hay comparadores definidos). Para ingerir, usa CSV o JSONL en jobs de carga, Storage Write API para streaming moderno o la API de transmisión heredada si procede; en todos los casos, respeta el escapado cuando JSON viaja como STRING.
Oracle y PostgreSQL: equivalencias y migración
En Oracle (12.2+), JSON_TABLE transforma documentos en filas con PATH por columna y manejo de errores. El reto al migrar es que AWS SCT no convierte automáticamente funciones JSON de Oracle a PostgreSQL, donde el enfoque idiomático usa operadores -> y ->> más funciones de agregación JSON.
En PostgreSQL, -> devuelve JSON y ->> devuelve texto, lo que facilita CAST explícito y uso en joins/agrupaciones. Para construir estructuras, emplea JSON_BUILD_OBJECT y JSON_AGG (equivalentes a JSON_OBJECT y JSON_ARRAYAGG de Oracle). Recuerda castear cuando necesites tipos numéricos o fechas para comparaciones.
-- Lectura en PostgreSQL: rutas jerárquicas y casteo con ->>
SELECT
(json_doc::json -> 'data' -> 'account' ->> 'parentAccountNumber')::int AS parentAccountNumber,
(json_doc::json -> 'data' -> 'account' ->> 'accountNumber')::int AS accountNumber,
(json_doc::json -> 'data' -> 'account' ->> 'businessUnitId')::int AS businessUnitId,
(json_doc::json -> 'data' ->> 'positionId')::varchar AS positionId
FROM aws_test_pg_table;
-- Agregación a JSON (equivalente conceptual a Oracle)
SELECT JSON_BUILD_OBJECT(
'accountCounts', JSON_AGG(
JSON_BUILD_OBJECT(
'businessUnitId', businessUnitId,
'parentAccountNumber', parentAccountNumber,
'accountNumber', accountNumber,
'totalOnlineContactsCount', online_contacts_count,
'countByPosition', JSON_BUILD_OBJECT(
'taxProfessionalCount', tax_professional_count,
'attorneyCount', attorney_count,
'nonAttorneyCount', non_attorney_count,
'clerkCount', clerk_count
)
)
)
)
FROM (...) t; -- Agrega unifica y castea antes de construir el objeto
Buena práctica en la conversión: simula JSON_TABLE con json_array_elements para expandir arrays, utiliza ->> cuando vayas a castear y garantiza tipos homogéneos al agrupar o unir. Esto te evita sorpresas de colaciones/ordenaciones y maximiza el rendimiento con índices funcionales o GIN según el caso.
Patrones de implementación, seguridad y BI
Para arquitecturas empresariales, combina documentos JSON para atributos dinámicos con columnas relacionales para claves de negocio. Añade índices en columnas calculadas (SQL Server) o GIN/expresiones (PostgreSQL), aplica validaciones (CHECK ISJSON, JSON Schema en la app) y planifica vías de exportación a modelos de BI. Así tendrás agilidad de esquema sin perder control en informes.
En seguridad, trata JSON como cualquier otro dato sensible: cifrado en tránsito y reposo, controles de acceso, auditoría y endurecimiento de sistemas. Para analítica, prepara vistas materializadas o ETL que descompongan JSON en tablas fact/dim si la herramienta (por ejemplo Power BI) lo demanda. Este enfoque híbrido es el que mejor escala en cargas mixtas.
Un truco útil en T‑SQL: recorrer arrays sin cursor
Si necesitas iterar elementos de un array JSON, evita concatenar rutas en bucles. OPENJSON con APPLY es más limpio, rápido y seguro. Un patrón típico para un procedimiento que inserta elementos de un array en una tabla sería:
DECLARE @json nvarchar(max) = N'{
"timeCardLogs": [
{"day":"2023-07-03T00:00:00", "totalHours":"01:52"},
{"day":"2023-07-04T00:00:00", "totalHours":"02:09"}
]
}';
-- Expandir el array y proyectar columnas tipadas
SELECT
JSON_VALUE(j.value, '$.day') AS Day,
JSON_VALUE(j.value, '$.totalHours') AS TotalHours
FROM OPENJSON(@json, '$.timeCardLogs') AS j;
-- Inserción ejemplo
-- INSERT INTO dbo.TimeCard(Day, TotalHours)
-- SELECT JSON_VALUE(j.value, '$.day'), JSON_VALUE(j.value, '$.totalHours')
-- FROM OPENJSON(@json, '$.timeCardLogs') AS j;
Además de ser más legible, este enfoque evita errores de índice y problemas de rendimientos asociados a WHILE/cursores, y es el recomendado por el propio motor cuando trabajas con colecciones JSON.
Para organizaciones que buscan ayuda de extremo a extremo, firmas especializadas como Q2BSTUDIO implementan patrones híbridos, despliegues cloud (AWS/Azure), ciberseguridad y automatización con IA. La clave está en combinar el diseño de datos con renderizado JSON en la base, pipelines robustos y visualización en suites BI, con acompañamiento en migraciones entre motores cuando hay funciones JSON específicas.
Integrar JSON en SQL consiste en elegir el tipo de almacenamiento correcto (nativo o texto), saber usar las funciones de cada motor (T‑SQL, GoogleSQL, operadores de Postgres, JSON_TABLE en Oracle), y apoyarse en índices y vistas para que consultas y APIs sean ágiles. Con estas piezas bien encajadas, puedes ingerir, consultar, transformar y servir JSON a escala manteniendo gobierno, seguridad y rendimiento en toda la plataforma.