Tools mentioned in this article
Open the browser-based tool while you read and try the workflow immediately.
De “más o menos sé qué tablas necesito” a un CREATE TABLE, rápido
Cuando empiezas una función nueva, normalmente ya tienes una idea aproximada de las tablas que vas a necesitar. Escribir eso como sentencias CREATE TABLE es sencillo en teoría, pero consume más tiempo del que debería: recordar el tipo exacto de cada columna, consultar en qué se diferencia la sintaxis de MySQL y PostgreSQL, equivocarte en una cláusula de clave foránea.

El Generador de DDL te permite montar tablas y columnas en pantalla y genera sentencias CREATE TABLE con el formato de MySQL, PostgreSQL o SQLite, junto con un diagrama ER en formato Mermaid, todo a la vez. También puedes pegar una muestra JSON para inferir las columnas automáticamente. Todo se ejecuta en tu navegador: el diseño de tablas que introduces nunca se envía a ningún sitio.
Este artículo explica qué ocurre por dentro: cómo se convierten los tipos entre dialectos y cómo se infieren las columnas a partir de una muestra JSON.
Tres formas de construir una tabla
- Generar desde JSON: pega una muestra JSON de una respuesta de API o de un registro de log, y la herramienta infiere nombres de columna, tipos, clave primaria y NOT NULL automáticamente.
- Diseño manual de tablas: edita el nombre de la tabla, los nombres de columna, los tipos, PK/NOT NULL/UNIQUE/autoincremento y los valores por defecto directamente en pantalla.
- Relaciones: elige una tabla/columna origen y una tabla/columna destino para añadir una restricción de clave foránea y su línea de conexión en el diagrama ER.
El DDL generado puede pasarse directamente a Visual SQL Builder para empezar a escribir consultas, o pegarse más tarde en SQL a Diagrama ER para revisar la estructura. Todo el flujo, del diseño a la consulta, permanece dentro del navegador.
Cómo se convierten los tipos entre bases de datos
Internamente, la herramienta mantiene las tablas con un conjunto de “tipos lógicos” independiente de la base de datos:
export type LogicalType =
| 'INTEGER' | 'BIGINT' | 'DECIMAL' | 'VARCHAR' | 'TEXT'
| 'BOOLEAN' | 'DATE' | 'DATETIME' | 'JSON' | 'UUID';
Solo al generar el DDL se convierten esos tipos a los tipos SQL reales del dialecto elegido. Los casos más interesantes son aquellos en los que SQLite no dispone de tipo booleano ni JSON, y las diferencias en las claves primarias autoincrementales:
| Tipo lógico | MySQL | PostgreSQL | SQLite |
|---|---|---|---|
BOOLEAN | BOOLEAN | BOOLEAN | INTEGER |
JSON | JSON | JSONB | TEXT |
UUID | CHAR(36) | UUID | TEXT |
| PK + autoincremento | INT ... AUTO_INCREMENT | SERIAL | INTEGER PRIMARY KEY AUTOINCREMENT |
La fila de la clave primaria autoincremental es la que más diverge: PostgreSQL sustituye el propio tipo por SERIAL (azúcar sintáctico para INTEGER más una secuencia), mientras que SQLite solo obtiene un alias real de rowid autoincremental cuando la columna se declara exactamente como INTEGER PRIMARY KEY. La herramienta absorbe esas diferencias para que obtengas una sintaxis correcta sea cual sea el dialecto que elijas.
Un detalle más: en cuanto una columna se marca como clave primaria, sus ajustes de NOT NULL, UNIQUE y valor por defecto se ignoran; se emite simplemente como TIPO PRIMARY KEY, porque una clave primaria es NOT NULL y UNIQUE por definición.
La lógica de inferir columnas desde una muestra JSON
Al pegar un objeto JSON (o un array), el valor de cada propiedad se usa para inferir el tipo de columna. Aproximadamente, en orden de prioridad:
- Todos los valores son booleanos →
BOOLEAN - Todos los valores son números →
INTEGERsi todos son enteros (oBIGINTsi alguno supera 2^31); en caso contrario,DECIMAL - Todos los valores son cadenas →
DATETIMEpara fechas y horas ISO 8601,DATEpara fechas sin hora,UUIDpara cadenas con formato UUID; en caso contrario,VARCHAR(oTEXTsi alguna cadena supera los 255 caracteres) - Todos los valores son objetos simples →
JSON
Si pasas un array, todos los elementos se usan conjuntamente para la inferencia. Eso permite detectar la nulabilidad (algunos valores son null) y los tipos mixtos (una mezcla de enteros y decimales, por ejemplo) que un único objeto no revelaría.
[
{ "id": 1, "nickname": "Alice", "score": 10 },
{ "id": 2, "nickname": null, "score": 10.5 }
]
Aquí, nickname pierde el NOT NULL porque una fila tiene null, y score se infiere como DECIMAL porque los valores mezclan enteros y decimales.
Los arrays anidados de objetos se convierten en tablas relacionadas
Cuando el valor de una propiedad de nivel superior es un array de objetos, la herramienta no lo reduce simplemente a una columna JSON, sino que lo separa en su propia tabla con una clave foránea hacia la tabla padre.
{
"id": 1,
"name": "Order #1",
"items": [
{ "product": "Widget", "qty": 2 },
{ "product": "Gadget", "qty": 1 }
]
}
Al generar este JSON como orders se produce una tabla items independiente, con una clave foránea items.orders_id → orders.id configurada automáticamente: una relación uno a muchos, como un pedido y sus líneas de detalle, construida a partir de un solo fragmento de JSON. El anidamiento de más de un nivel no se divide automáticamente, así que ajusta esos casos a mano después de generar.
Ida y vuelta con SQL a Diagrama ER para comprobar el diseño
Exporta las tablas que has construido como DDL en dialecto MySQL y pégalo en SQL a Diagrama ER: salen las mismas tablas, columnas y relaciones. Es un recorrido útil cuando quieres confirmar que el DDL generado es SQL válido y estándar, o cuando quieres revisar el diseño más adelante.
Preguntas frecuentes
¿Qué ocurre con NOT NULL, UNIQUE y el valor por defecto si marco una columna como PK?
Una clave primaria es NOT NULL y UNIQUE por definición, así que al marcar PK se ignoran esos ajustes y solo se genera “TIPO PRIMARY KEY” (más AUTO_INCREMENT/SERIAL si el autoincremento está activado).
¿Puedo usar el DDL generado directamente en una migración de producción?
Esta herramienta está pensada como punto de partida para el diseño de tablas o como material de revisión: no genera índices, restricciones CHECK, juegos de caracteres/collation ni particionado, que los despliegues reales suelen necesitar. Revisa siempre el resultado y ajústalo antes de usarlo en producción.
¿Qué pasa si el nombre de tabla inferido desde JSON coincide con uno existente?
Se añade automáticamente un sufijo como _2 para evitar la colisión; una tabla existente que hayas creado a mano nunca se sobrescribe.
Si no sabes por dónde empezar con un diseño de tablas, prueba a pegar una muestra JSON que ya tengas.
Hay más herramientas gratuitas para desarrolladores como esta en https://devtoolkits.app/