SofiaDB · referencia de SQL#
Consejo
En corto: SofiaDB entiende un subconjunto del SQL de PostgreSQL, escrito a mano y sin NULL: CREATE/DROP/ALTER, INSERT, SELECT con JOIN, subconsultas y agregados, UPDATE, DELETE, transacciones y EXPLAIN. Una sentencia por llamada. Lo que no entiende lo rechaza con un mensaje que dice qué usar en su lugar; esta página los lista con su texto exacto.
Cada ejemplo de esta página se ejecuta en las pruebas del motor, y cada rechazo se comprueba con su mensaje. Para usar el SQL desde una app, mira SofiaDB desde el lenguaje; para el motor, SofiaDB.
Reglas generales#
- Una sentencia por llamada, con
;final opcional. Si sobra texto: «sobra texto tras la sentencia (…): una sola sentencia por llamada». - Sentencias:
CREATE TABLE,CREATE INDEX,DROP TABLE,DROP INDEX,ALTER TABLE … ADD COLUMN,INSERT,REPLACE,SELECT,UPDATE,DELETE,BEGIN,COMMIT,ROLLBACKyEXPLAIN. Cualquier otra: «sentencia desconocida: …». - Sin
NULL. Toda columna tiene valor.NULLse rechaza donde aparezca: «SofiaDB no usa NULL: toda columna tiene valor (usa '' o 0, o un valor por defecto)».IS NULLeIS NOT NULL: «SofiaDB no usa NULL: IS NULL / IS NOT NULL no tienen sentido». - Parámetros
$1,$2…: los valores viajan aparte del texto. La sentencia debe recibir exactamente tantos como el mayor$nque usa: «la sentencia usa N parámetro(s) y se pasaron M». Hasta 65 535. - Tipos de resultado:
ENTERO,TEXTO,LOGICO,BYTES,DECIMALeINSTANTE.
Léxico#
| Elemento | Regla |
|---|---|
| Comentarios | -- hasta el fin de línea y /* en bloque */. Sin cerrar: «comentario /* sin cerrar» |
| Texto | 'entre comillas simples'; una comilla dentro se escribe doble: 'it''s'. Sin cerrar: «texto sin cerrar en la posición N» |
| Identificadores | Letras (también Unicode), dígitos y _. Sin comillas se pasan a minúsculas; "entre comillas dobles" se respetan tal cual. Sin cerrar: «identificador " sin cerrar»; vacío: «identificador vacío ""» |
| Números | Entero de 64 bits; con punto, o demasiado grande, es decimal. Pegado a una letra: «número mal escrito en la posición N» |
| Parámetros | $1, $2…; otra forma: «parámetro inválido en la posición N: se escribe $1, $2…» |
| Símbolos | <> != <= >= || :: ( ) , ; * + - / % = < > y . |
| Otro carácter | «carácter inesperado «c» en la posición N» |
| Tamaño | Hasta 1 MiB de SQL: «el SQL ocupa más de 1024 KiB» |
Palabras reservadas (no sirven de nombre sin comillas): select from where group order by having limit offset and or not as asc desc in like between is null true false values set insert update delete create drop table into primary key default distinct case when then else end join on union all inner left right full outer cross natural using exists.
Nombres de tablas, columnas e índices: de 1 a 63 bytes, sin caracteres de control («nombre inválido: «n» (1 a 63 bytes, sin caracteres de control)»).
Tipos#
| Tipo | Nombres aceptados | Notas |
|---|---|---|
| Entero (64 bits) | integer, int, int4, int8, bigint, smallint, int2, entero | |
| Texto | text, texto, varchar, char, character (con varying y (n) opcionales) | El tamaño (n) se ignora |
| Lógico | boolean, bool, logico, lógico | true y false |
| Bytes | bytea, bytes | |
| Decimal exacto | numeric, decimal, con (p) o (p,s) | p de 1 a 38 y s de 0 a p: «DECIMAL(p,s): la precisión va de 1 a 38 y la escala de 0 a la precisión» |
| Instante | timestamptz, timestamp, instante | Milisegundos desde 1970 |
Otro nombre: «tipo desconocido: x».
CREATE TABLE#
CREATE TABLE [IF NOT EXISTS] t (
columna tipo [restricciones de columna],
…,
[restricciones de tabla]
)
Restricciones de columna, en cualquier orden: PRIMARY KEY [AUTOINCREMENT], UNIQUE, NOT NULL, DEFAULT expr, CHECK (expr), REFERENCES t [(col)] y CONSTRAINT nombre delante de cualquiera.
Restricciones de tabla (con CONSTRAINT nombre opcional): UNIQUE (cols), CHECK (expr), FOREIGN KEY (cols) REFERENCES t [(cols)] [ON DELETE|UPDATE RESTRICT|NO ACTION] y PRIMARY KEY (col).
CREATE TABLE cita (
id INTEGER PRIMARY KEY,
profesional TEXT NOT NULL,
inicio TIMESTAMPTZ DEFAULT 0,
monto NUMERIC(10,2) DEFAULT 0,
CHECK (monto >= 0)
)
- Clave primaria: una sola columna, de tipo ENTERO, TEXTO, BYTES o INSTANTE. Compuesta: «la clave primaria compuesta no está soportada»; dos: «la tabla declara dos claves primarias»; otro tipo: «la clave primaria c es T: debe ser ENTERO, TEXTO, BYTES o INSTANTE».
AUTOINCREMENTse acepta. Una clave INTEGER a la que elINSERTno da valor toma la siguiente: el máximo más uno, o 1 si la tabla está vacía. Si se acaban: «se acabaron los números de t».DEFAULTadmite una expresión sin columnas.CHECKy los índices parciales no admiten parámetros: «CHECK no admite parámetros ($n): usa valores fijos».- Claves foráneas: se comprueban al final de cada sentencia. Solo
RESTRICToNO ACTION: «ON DELETE|UPDATE solo admite RESTRICT o NO ACTION: CASCADE, SET NULL y SET DEFAULT no están soportados».MATCH,DEFERRABLEeINITIALLY: «…no está soportado: las claves foráneas se comprueban al final de cada sentencia». - Nombres automáticos de las restricciones:
<tabla>_pkey,<tabla>_<col>_key,<tabla>_<col>_check(<tabla>_checksi elCHECKes de tabla) y<tabla>_<col>_fkey. - Límites: de 1 a 1000 columnas, 16 MiB por fila, 1 KiB de clave.
- Otros errores: «la tabla X ya existe», «la columna X está repetida», «la clave primaria c no es una columna», «la columna X no puede admitir NULL: SofiaDB no usa NULL (toda columna tiene valor)», «la columna declara dos REFERENCES».
CREATE INDEX y DROP#
CREATE [UNIQUE] INDEX [IF NOT EXISTS] nombre ON t (col [ASC], …) [WHERE predicado]
DROP TABLE [IF EXISTS] t
DROP INDEX [IF EXISTS] nombre
CREATE UNIQUE INDEX cita_hora ON cita (profesional, inicio)
CREATE INDEX cita_cara ON cita (inicio) WHERE monto > 100
- Un índice se recorre en los dos sentidos:
DESCse rechaza («los índices se recorren en los dos sentidos: no hace falta DESC en el índice»). - El predicado no admite parámetros. Una columna repetida: «la columna c aparece dos veces».
DROP TABLEde una tabla a la que otra apunta con una clave foránea falla conFORANEA_VIOLADA.
ALTER TABLE#
ALTER TABLE t ADD [COLUMN] columna tipo [DEFAULT expr] [NOT NULL]
Es la única forma de cambiar columnas: «de ALTER TABLE solo hay ADD COLUMN, POLITICA INQUILINO col, SIN POLITICA, AUDITAR y SIN AUDITAR». Las filas que ya existen necesitan un valor, así que DEFAULT es obligatorio: «añadir la columna X necesita DEFAULT: las filas que ya existen deben tener un valor (SofiaDB no usa NULL)».
Tampoco se puede añadir:
| Intento | Mensaje |
|---|---|
| Una clave primaria | «no se puede añadir una clave primaria a una tabla que ya existe» |
UNIQUE o CHECK | «ADD COLUMN no admite UNIQUE ni CHECK: añade la columna y crea después CREATE UNIQUE INDEX» |
REFERENCES | «ADD COLUMN no admite REFERENCES: declara la clave foránea al crear la tabla» |
| Pasar de 1000 columnas | «una tabla tiene como mucho 1000 columnas» |
| Una columna que ya existe | «la columna X ya existe» |
INSERT#
INSERT [OR REPLACE | OR IGNORE] INTO t [(col, …)] VALUES (v, …), (v, …)
REPLACE INTO t [(col, …)] VALUES (v, …)
INSERT INTO cita (id, profesional, inicio) VALUES (1, 'ana', 1790586000000), (2, 'luis', 1790589600000)
INSERT OR IGNORE INTO cita (id, profesional) VALUES (1, 'otra')
INSERT OR REPLACE INTO cita (id, profesional) VALUES (1, 'otra')
- Una sentencia con varias filas es atómica: si una falla, ninguna queda.
- Sin lista de columnas,
VALUESdebe traer todas, en orden. Las columnas omitidas toman suDEFAULT; si no lo tienen: «falta el valor de la columna X (no tiene DEFAULT y SofiaDB no usa NULL)». Si la cantidad no cuadra: «VALUES trae N valor(es) y se esperaban M». OR IGNOREsalta la fila que choca con una clave o unUNIQUE;OR REPLACEyREPLACE INTOborran la fila con la que chocan y ponen la nueva.OR ABORT,OR FAILyOR ROLLBACK: «INSERT OR «abort» en la posición N no está soportado: usa INSERT, INSERT OR REPLACE o INSERT OR IGNORE».- Una clave repetida da
UNICO_VIOLADO:<tabla>_pkey(«clave primaria repetida en t: ya hay una fila con …»).
SELECT#
SELECT { * | alias.* | expr [[AS] alias] }, …
[FROM fuente [JOIN …]]
[WHERE predicado]
[GROUP BY expr, …] [HAVING predicado]
[ORDER BY expr [ASC|DESC], …]
[LIMIT expr] [OFFSET expr]
LIMIT y OFFSET pueden ir en cualquier orden. Un SELECT sin FROM vale (SELECT 1 + 1). Una columna sin alias se llama como la columna, o count, sum, min, max si es un agregado.
SELECT DISTINCT se rechaza: «SELECT DISTINCT no está soportado».
FROM y JOIN#
La fuente es t [[AS] alias] o una tabla derivada (SELECT …) [AS] alias (el alias es obligatorio). Un FROM junta hasta 16 fuentes.
SELECT c.id, c.profesional, p.nombre
FROM cita c
INNER JOIN profesional p ON p.id = c.profesional_id
LEFT JOIN sala s ON s.id = c.sala_id
[INNER] JOINyLEFT [OUTER] JOIN, siempre conON. SinON: «se esperaba ON tras el JOIN y hay …».- Un
LEFT JOINsin pareja entrega el valor vacío de cada tipo ('',0,false), noNULL. RIGHT,FULL,CROSSyNATURAL: ««x» en la posición N no está soportado: usa [INNER] JOIN o LEFT JOIN con ON».- La coma entre tablas: «la coma entre tablas del FROM no está soportada: usa JOIN … ON».
USING: «JOIN … USING no está soportado: usa ON».
Subconsultas#
| Forma | Ejemplo |
|---|---|
| Escalar | SELECT (SELECT max(id) FROM cita) |
IN / NOT IN | WHERE id IN (SELECT cita_id FROM pago) |
EXISTS / NOT EXISTS | WHERE EXISTS (SELECT id FROM pago WHERE pago.cita_id = cita.id) |
| Tabla derivada | FROM (SELECT profesional FROM cita) t |
Una subconsulta puede referirse a columnas de la consulta que la contiene (correlada), con hasta 24 niveles. Una escalar sin filas da el valor vacío del tipo.
- «una subconsulta escalar devuelve una sola columna (usa IN o EXISTS para varias)».
- «la subconsulta de IN devuelve una sola columna».
- Una subconsulta correlada no se combina con
GROUP BYni con agregados. Donde no caben: «no se permiten subconsultas en …».
Agregados y agrupación#
count(*), count(e), sum(e), min(e) y max(e), con GROUP BY y HAVING.
SELECT profesional, count(*), sum(id) FROM cita GROUP BY profesional HAVING count(*) > 1 ORDER BY profesional
SUMde ninguna fila da0.SUMsolo admite números: «SUM no admite un T».MINyMAXde ninguna fila fallan: «MIN/MAX de ninguna fila no tiene valor (SofiaDB no usa NULL): comprueba antes COUNT(*)».AVG: «AVG no está soportado: usa SUM y COUNT». ConDISTINCT: «los agregados con DISTINCT no están soportados».- «no se puede anidar un agregado dentro de otro» y «no se permiten agregados (COUNT, SUM…) en …» (por ejemplo, en un
WHERE). - Agrupar o juntar usa como mucho 64 MiB de memoria: «consulta demasiado grande: necesita más de 64 MiB de memoria para juntar o agrupar (agrega filtros, un índice o LIMIT)».
Expresiones#
De menor a mayor precedencia:
| Nivel | Operadores |
|---|---|
| 1 | OR |
| 2 | AND |
| 3 | NOT |
| 4 | = <> != < <= > >=, BETWEEN, IN (lista), LIKE, y sus NOT |
| 5 | || (concatenar texto) |
| 6 | + - |
| 7 | * / % |
| 8 | + y - unarios |
| 9 | Literales, columnas, $n, paréntesis, funciones, subconsultas |
LIKEusa%(cualquier cosa) y_(un carácter).- Comparaciones encadenadas: «no se pueden encadenar comparaciones: usa AND».
- Entero con entero:
+ - * / %. Fuera de rango: «desbordamiento: el resultado no cabe en el tipo»; «división por cero». - Decimal:
+ - *sí;/no («la división de DECIMAL no está soportada»). - Instante: instante ± entero (milisegundos) da instante; instante − instante da entero.
- Un texto junto a un número se interpreta como número. Tipos incompatibles: «no se puede operar un X con un Y»; menos unario: «no se puede negar un T». Una condición que no es lógica: «… debe ser verdadero o falso y es un T».
CASE: «CASE no está soportado».::: «las conversiones con :: no están soportadas».- Una expresión anida hasta 128 niveles («expresión anidada demasiado profunda») y encadena hasta 256 operandos con
AND,OR,+,*o||(«expresión encadenada demasiado larga (como mucho 256 operandos seguidos)»).
Funciones#
| Función | Qué hace |
|---|---|
lower(t), upper(t) | Minúsculas y mayúsculas |
length(x), char_length(x) | Caracteres de un texto, o bytes de un BYTES |
abs(n) | Valor absoluto de un entero o decimal |
trim(t) | Quita los espacios de los extremos (solo espacios) |
substr(t, desde [, largo]), substring(…) | Posiciones desde 1 |
encode(bytes, 'base64'|'hex') | BYTES a texto |
decode(texto, 'base64'|'hex') | Texto a BYTES |
SELECT upper(profesional), length(profesional), substr(profesional, 1, 2) FROM cita
coalesce,nullifeifnullse rechazan: «X no hace falta: SofiaDB no usa NULL».- Otra función: «función desconocida: x». Cantidad de argumentos distinta: «X recibe [n] argumento(s) y se le pasan N».
- Tipos: «length no admite un T», «abs no admite un T», «encode recibe BYTES», «formato de encode desconocido: x», «decode: el texto no está bien codificado», «substr: la posición debe ser ENTERO», «substr: largo negativo», «substr: el largo debe ser ENTERO».
UPDATE y DELETE#
UPDATE t SET col = expr, … [WHERE predicado]
DELETE FROM t [WHERE predicado]
UPDATE cita SET monto = monto + 1 WHERE id = 2
DELETE FROM cita WHERE inicio < 1790000000000
Ambas devuelven las filas afectadas. Sin WHERE actúan sobre toda la tabla. Una columna asignada dos veces: «la columna c se asigna dos veces». Las restricciones (UNIQUE, CHECK, claves foráneas) se comprueban al final de la sentencia; si fallan, la sentencia no deja nada.
Transacciones#
BEGIN [TRANSACTION | WORK]
START TRANSACTION
COMMIT | END [TRANSACTION | WORK]
ROLLBACK [TRANSACTION | WORK]
Sin BEGIN, cada sentencia es su propia transacción. Lo confirmado sobrevive a un corte de luz. Si otra transacción confirmó antes un cambio en lo que esta leyó, falla con CONFLICTO_SERIALIZACION y hay que repetirla (una sentencia suelta se repite sola). Una transacción acepta hasta 64 MiB de cambios y dura a lo más 30 s; pasado eso falla: «la transacción lleva abierta más de 30 s: confírmala o divídela en partes más cortas».
EXPLAIN#
EXPLAIN SELECT * FROM cita WHERE profesional = 'ana'
Devuelve en texto el plan (qué índice usa, cómo junta). Solo vale para SELECT, UPDATE y DELETE: «EXPLAIN solo vale para SELECT, UPDATE y DELETE».
Códigos de error estables#
Los errores de restricción y de concurrencia empiezan por un código que un programa puede comparar:
| Código | Cuándo |
|---|---|
UNICO_VIOLADO:<índice> | Clave primaria o UNIQUE repetido |
FORANEA_VIOLADA:<restricción> | Fila hija sin madre, o madre con hijas |
COMPROBAR_VIOLADO:<restricción> | Un CHECK no se cumple |
CONFLICTO_SERIALIZACION | Otra transacción cambió antes lo leído |
SOLO_LECTURA | Cambio en una sesión de solo lectura |
TIEMPO_AGOTADO, CANCELADA | Consulta que pasó su tiempo o fue cancelada |
CLAVE_REQUERIDA, CLAVE_INVALIDA | Base cifrada sin clave, o con clave que no la abre |
Límites#
| Qué | Límite |
|---|---|
| Sentencias por llamada | 1 |
| Tamaño del SQL | 1 MiB |
| Parámetros por sentencia | 65 535 |
| Columnas por tabla | 1000 |
Fuentes en un FROM | 16 |
| Niveles de subconsultas | 24 |
| Anidación de una expresión | 128 niveles |
| Operandos encadenados | 256 |
| Una fila | 16 MiB |
| Una clave | 1 KiB |
| Memoria al juntar o agrupar | 64 MiB |
| Cambios de una transacción | 64 MiB |
| Duración de una transacción | 30 s |