Documentación/SQL Server
SQL Server
Base de datos relacional Microsoft SQL Server.
De un vistazo
- Categoría — Relacional
- Query language — T-SQL
- Puerto por defecto — 1433
- Esquema de URI —
sqlserver
Driver de Microsoft SQL Server para DBFlux, construido sobre el cliente TDS
tiberius.
Funcionalidades
- Driver relacional para SQL Server / Azure SQL con ejecución de queries SQL y descubrimiento de schema.
- Autenticación mediante logins de SQL Server (usuario + contraseña); el modo
URI acepta connection strings ADO, JDBC y
sqlserver://user:pass@host:port/db. - Reporta
Application Namecomodbflux/<version>salvo que la connection string o URI ya definan uno, en cuyo caso el valor del usuario siempre gana; el esquema de URLsqlserver:///mssql://acepta un parámetro de queryapplicationnamepara esto. - Modos de encriptación TLS (
off,on,required) vía elEncryptionLevelde tiberius. El formulario expone un único desplegable SSL Mode; el flagTrustServerCertificatese deriva automáticamente:off— sin encriptación (el paquete de login sigue encriptado por TDS).on— encriptado, acepta certificados autofirmados. Ideal para SQL Server local/de desarrollo con su certificado autogenerado.required— encriptado, valida la cadena del certificado. Úsalo contra servidores con un certificado firmado por una CA real (Azure SQL, etc.). En modo URI,?trust=true|falsesobrescribe explícitamente el valor derivado si necesitas una combinación inusual (p. ej.?encrypt=required&trust=true).
- Soporte opcional de instancias con nombre de SQL Server (
SQLEXPRESS,MSSQLSERVER2019, etc.) resueltas en el momento de conectar consultando SQL Browser sobre UDP 1434 (habilitado vía el featuresql-browser-tokiode tiberius). El campo Instance del formulario, la formahost\instanceal estilo SSMS en modo URI, y el parámetro de query?instance=en la URI fijan todos el mismoinstance_nameen la configuración de tiberius. - Soporte de túnel SSH para conectar a través de bastion hosts (la búsqueda de instancia con nombre no está disponible a través de un túnel solo-TCP).
- Cambio de base de datos por pestaña vía
USE [database]; el estado de sesión (opciones SET, tablas temporales, transacciones) persiste entre llamadas aexecute()sobre la misma conexión. - Lotes con múltiples result sets: cuando un lote produce varios result sets (p.
ej.
SELECT 1; SELECT 2;o un stored procedure con múltiplesSELECT), el driver devuelve el último set no vacío como elQueryResultprimario (preservando la UX histórica de “gana la última sentencia”) y adjunta cada set anterior no vacío aQueryResult.additional_resultsen el orden del lote. Los lotes de pura preparación (SET LOCK_TIMEOUT 5000) siguen mostrándose como un único primario vacío. Los callers que quieran recorrer cada set usanQueryResult::iter_result_sets(). - Motor de transferencia de datos: carga masiva nativa multi-fila con
INSERT(BULK_INSERT, con un tope de 1000 filas por sentencia según el límite de filas deVALUESde T-SQL, expuesto víaDriverLimits::max_bulk_insert_rows) y DDLCREATE TABLEnativo del driver a partir de las columnas de una tabla origen (TRUNCATE_TABLEtambién está soportado).
Instance Metrics
Expone un conjunto curado de métricas de servidor en vivo obtenidas de
sys.dm_os_performance_counters:
mssql.batch_requests_per_sec— batch requests de T-SQL por segundomssql.compilations_per_sec— compilaciones SQL por segundomssql.recompilations_per_sec— recompilaciones SQL por segundomssql.user_connections— conexiones de usuario abiertas actualmentemssql.lock_waits_per_sec— esperas de lock por segundo (instancia_Total)mssql.page_reads_per_sec— lecturas de página del buffer pool por segundomssql.page_writes_per_sec— escrituras de página del buffer pool por segundomssql.buffer_cache_hit_ratio— ratio de aciertos del buffer cache (porcentaje)mssql.server_memory_kb— memoria total del servidor en KB
Cada métrica se devuelve como una única fila (timestamp_ms, value) para
graficado en vivo.
Requiere el permiso de servidor VIEW SERVER STATE. Sin él, list_metrics()
devuelve una lista vacía y se registra una advertencia. El driver sondea este
permiso una vez al construir el catálogo.
Instance Inspector
Expone snapshots tabulares del estado del servidor en ejecución:
mssql.active_sessions— sesiones de usuario desys.dm_exec_sessionsunidas consys.dm_exec_requests(session id, login name, host name, program name, status, tiempo de CPU, uso de memoria, command, request status, wait type, wait time, blocking session id)
Requiere el permiso VIEW SERVER STATE.
Cancelación de queries
- La cancelación se implementa como
KILL <spid>emitido desde una conexión side-channel nueva. tiberius actualmente no expone la primitiva TDS Attention que usa SSMS, así que la siguiente mejor opción es pedirle al servidor que termine la sesión que ejecuta la query. - Al conectar, el driver captura
@@SPIDy cachea un clon de laConfigde tiberius (con el login ya incorporado). El handle de cancelación abre una segunda conexión bajo demanda, ejecutaKILL <spid>, y marca la conexión primaria como envenenada. - Tras la cancelación,
cleanup_after_cancel()reconstruye el cliente tiberius primario, captura el nuevo SPID, y reemite elUSE [db]anterior para que la siguiente query se ejecute en la misma base de datos. Desde la perspectiva de la UI, la conexión sigue conectada; solo cambia el id de sesión subyacente. - Los errores lanzados en la sesión eliminada (códigos 596 / 233 / 6005) se
traducen a
DbError::Cancelledpara que la UI muestre “query cancelled” en vez de un fallo a nivel de transporte. - El propietario de la sesión puede hacer
KILLde su propio SPID en SQL Server moderno sin el permisoALTER ANY CONNECTION. En logins más antiguos o restringidos, el propio KILL puede fallar con un error de permisos; el driver lo muestra al usuario.
Descubrimiento de schema
- Bases de datos (
sys.databases, oculta las bases de datos de sistema). - Tablas y vistas por base de datos (
sys.tables,sys.views). - Columnas por tabla + flag de primary key, índices, foreign keys.
- Constraints por tabla: constraints CHECK (con su definición) y constraints
UNIQUE (vía
sys.indexes.is_unique_constraint). - Índices y foreign keys de todo el schema para el panel lateral de navegación de schema.
- Tipos definidos por el usuario (
sys.types where is_user_defined = 1) clasificados comoDomain(tipos alias) oComposite(table types). view_details()verifica que la vista existe en la base de datos solicitada.- Routines: stored procedures (
P), scalar functions (FN), inline table-valued functions (IF), multi-statement table-valued functions (TF), y CLR aggregates (AF) se listan por schema víasys.objects. Las definiciones fuente se obtienen conOBJECT_DEFINITION(object_id).
CRUD con OUTPUT
- INSERT/UPDATE/DELETE sobre una fila usan la cláusula
OUTPUT INSERTED.*/OUTPUT DELETED.*de SQL Server para que los datos de la fila post-mutación se devuelvan al caller (CrudResult::success(row)), de la misma forma que el driver de Postgres usaRETURNING *. MutationCapabilities::supports_returningestrue.- La identidad de fila debe ser una primary key compuesta (la única variante de
RecordIdentityque tiene sentido para un driver relacional).
Planificación de queries
explain()ejecuta la query bajoSET SHOWPLAN_XML ONy devuelve el plan de query como XML. El driver siempre ejecutaSET SHOWPLAN_XML OFFdespués para que el estado de sesión no se filtre.version_query()devuelveSELECT @@VERSION.
Dialecto
- Comillas de identificador con
[corchetes]con escape de]. - Literales de string Unicode
N'…'; literales binarios0x…(en mayúsculas);1/0para valores booleanos (BIT). - Paginación
OFFSET … ROWS FETCH NEXT … ROWS ONLY(con un fallbackORDER BY 1para que las queries con OFFSET sin ORDER BY no den error). SELECT TOP Nno se usa; OFFSET/FETCH es la forma canónica de paginación.UPSERTintencionalmente no se genera;MERGEen SQL Server tiene bugs conocidos y debería escribirse a mano.
Reporte de errores
-
Los errores de token
Serverde tiberius muestran su código numérico, severity state, y línea de origen a través deFormattedError. -
Los números de error comunes de MSSQL se mapean a variantes semánticas de
DbErroren vez delQueryFailedgenérico:Código(s) Variante de DbError 4060, 18450, 18452, 18456, 18486, 18487, 18488 AuthFailed229, 230, 262, 297, 916 PermissionDenied207, 208, 2812, 4902 ObjectNotFound245, 334, 515, 547, 2601, 2627, 8152 ConstraintViolation102, 156, 8180 SyntaxError -
Los mensajes de violación de constraint se parsean para poblar
ErrorLocation(schema, tabla, columna, nombre de constraint) para que la UI pueda resaltar el objeto en cuestión.
Operaciones y límites
- Todas las operaciones declaran
transactional_ddl: trueysupports_savepoints: true. - Niveles de aislamiento soportados: ReadUncommitted, ReadCommitted, RepeatableRead, Serializable, Snapshot. El valor por defecto es ReadCommitted.
Comportamiento de DDL
- DDL transaccional. La mayoría del DDL en SQL Server es transaccional.
Envolver
CREATE,ALTER, oDROP TABLEdentro deBEGIN TRAN … COMMIT/ROLLBACKfunciona. Excepciones:CREATE DATABASE,DROP DATABASE,ALTER DATABASE,BACKUP/RESTORE, yCREATE FULLTEXT INDEXno pueden ejecutarse dentro de una transacción explícita. - Locking de ALTER TABLE.
ALTER TABLE … ADD COLUMN <nullable>es rápido (solo metadata). Agregar una columna NOT NULL con un default escribe en cada página y toma un lock Sch-M.ALTER TABLE … ALTER COLUMNpuede reescribir la tabla y bloquea lecturas y escrituras hasta que termina. - Operaciones de índice online (Enterprise / Azure SQL):
CREATE INDEX … WITH (ONLINE = ON)yALTER INDEX … REBUILD WITH (ONLINE = ON)permiten DML concurrente. SinONLINE = ON, la construcción de índices toma un lock Sch-M y bloquea escrituras (Standard/Express solo soportan modo offline). - TRUNCATE TABLE. Solo metadata, rápido, transaccional, requiere el permiso
ALTERsobre la tabla. No puede usarse en tablas referenciadas por una foreign key (usaDELETEo elimina la FK primero). - DROP TABLE / DROP VIEW. Transaccional.
IF EXISTSestá soportado desde 2016+. - Constraints. Agregar constraints
CHECK/UNIQUE/FOREIGN KEYvalida todas las filas existentes por defecto (toma un Sch-M brevemente). UsaWITH NOCHECKpara agregar el constraint sin escanear, luegoWITH CHECK CHECK CONSTRAINTmás tarde para validar cuando quieras — el mismo patrón queNOT VALID+VALIDATE CONSTRAINTen Postgres.
Limitaciones
-
Las funcionalidades de Instance Metrics e Instance Inspector requieren el permiso de servidor
VIEW SERVER STATE. Sin él, tantolist_metrics()comolist_inspectors()devuelven listas vacías en vez de un error. -
Instance Metrics devuelve un único dato por llamada (valor actual de
sys.dm_os_performance_counters), no una serie temporal histórica. Los contadores de tasa (p. ej.mssql.batch_requests_per_sec) representan el promedio en ejecución que reporta la DMV del lado del servidor, no un delta calculado por el driver. -
SQL Server mínimo soportado: 2016 (13.0). El driver usa la sintaxis
DROP INDEX IF EXISTS … ON …, que los servidores más antiguos rechazan con un error de sintaxis (102). Azure SQL Database y Managed Instance funcionan bien. -
CRUD sobre tablas (o vistas actualizables) con triggers
INSTEAD OFno está soportado. El driver devuelve la fila post-mutación víaOUTPUT INSERTED.*/OUTPUT DELETED.*sin una cláusulaINTO, que SQL Server rechaza con el error 334 (“the target table cannot have any enabled triggers if the statement contains an OUTPUT clause without INTO”). El error se muestra comoConstraintViolation. -
Driver solo SQL; no expone APIs de documentos ni de key-value.
-
La cancelación elimina la sesión subyacente y reconecta de forma transparente; no es la cancelación quirúrgica vía TDS Attention que usa SSMS (tiberius actualmente no expone esa primitiva). En la práctica, la única diferencia visible para el usuario es que todo el estado local de sesión (opciones
SET, tablas temporales, transacciones abiertas) se reinicia con la cancelación. La base de datos activa se restaura automáticamente. -
La latencia de cancelación depende del scheduler de SQL Server: típicamente unos pocos milisegundos para queries limitadas por CPU, inmediata para las que esperan un lock. Los rollbacks largos (p. ej. cancelar un
DELETEgrande a mitad de transacción) pueden mantener el SPID del lado del servidor en estado KILLED/ROLLBACK durante un rato después de que el driver ya pasó a una sesión nueva. -
No se usa parameter binding — las sentencias se despachan vía
simple_query. Los helpers CRUD componen valores dentro del texto SQL a través delSqlQueryBuildercompartido y los formatters de literales del dialecto. Los payloads binarios o Unicode grandes se insertan como literales0x…oN'…'. -
Streaming: los result sets se materializan en
Vec<Row>. El traitConnection::executedevuelve unQueryResulttotalmente resuelto, así que el streaming al estilo cursor requeriría un cambio de API a nivel de workspace, no solo del driver. -
Los lotes multi-sentencia muestran cada result set no vacío vía
QueryResult.additional_results, pero la UI actualmente solo renderiza el set primario (el último). Hasta que el sistema de pestañas de resultados leaadditional_results, los sets anteriores son capturados por el driver pero invisibles en el editor. -
Los mensajes
PRINTe informativos emitidos durante un lote se descartan. Mostrarlos requeriría manejar elTokenStreamde bajo nivel de tiberius en vez deQueryStream::into_results(). -
UPSERTintencionalmente no se genera. UsaMERGEmanualmente cuando lo necesites. -
Las instancias con nombre se respetan al conectar directamente (tiberius consulta el servicio SQL Browser sobre UDP 1434) pero no al pasar por un túnel SSH, ya que libssh2 solo hace forward de TCP. El workaround estándar es asignar un puerto TCP estático a la instancia y conectar directamente a ese puerto.
-
La introspección de schema usa las vistas de catálogo
sys.*; los usuarios sin el permisoVIEW DEFINITIONpor defecto verán metadata parcial. Aplican las reglas de visibilidad de metadata de SQL Server. -
Las rutinas CLR (funciones escalares CLR, funciones table-valued CLR, stored procedures CLR) y cualquier rutina creada con
ENCRYPTIONdevuelvenNULLdesdeOBJECT_DEFINITION, en cuyo caso el driver muestra un mensaje de fallback corto en vez de un error. -
parameter_typesno se pobla para rutinas;sys.parametersno se consulta en esta implementación. -
SQL Server no tiene un tipo
Windowen la taxonomía desys.objects.type; este driver nunca emiteRoutineKind::Window. -
Sin toggle de integridad referencial para el flujo de migración del motor de transferencia de datos (
DriverCapabilities::DISABLE_FK_CHECKSno está fijado;Connection::set_referential_integritydevuelveNotSupported). SQL Server deshabilita la comprobación de FK por tabla víaALTER TABLE ... NOCHECK CONSTRAINT, lo cual no encaja con el toggle global único del motor; una variante por tabla es una posible mejora futura.