[{"data":1,"prerenderedAt":163},["ShallowReactive",2],{"seo-verification":3,"blog-migrar-sql-server-2016-a-postgresql-en-un-vps-es":6},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-migrar-sql-server-2016-a-postgresql-en-un-vps-es",{"id":9,"slug":10,"slugs":11,"title":15,"excerpt":16,"readTime":17,"views":18,"isPinned":19,"publishedAt":20,"updatedAt":21,"category":22,"categories":28,"featuredImage":30,"bgImage":31,"posterImage":32,"relatedSolution":30,"intro":33,"sections":34,"ctaTitle":128,"ctaBody":129,"ctaButton":130,"ctaUrl":131,"relatedPosts":132},467,"migrar-sql-server-2016-a-postgresql-en-un-vps",{"fr":12,"en":13,"ar":14,"es":10},"migrer-sql-server-vers-postgresql-vps","migrating-sql-server-2016-to-postgresql-on-a-vps","هجرة-sql-server-2016-إلى-postgresql-على-vps","Migrar SQL Server 2016 a PostgreSQL en un VPS","SQL Server 2016 llegó al fin de soporte en julio de 2026. Guía técnica: migrar a PostgreSQL en un VPS con tipos de datos, T-SQL, pgloader y plan de corte.",12,0,false,"2026-10-18T00:00:00+00:00","2026-10-18T21:57:56+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},6,"Bases de datos","bases-de-donnees","bg-teal-500\u002F10 text-teal-400","database",[29],{"id":23,"name":24,"slug":25,"color":26,"icon":27},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fmigrer-sql-server-vers-postgresql-vps-poster.svg","El 14 de julio de 2026, Microsoft dio por concluido el soporte extendido de SQL Server 2016. No se publicarán más parches de seguridad para esta versión. Los equipos que aún trabajan con esta base de datos tienen dos opciones reales: pagar una actualización a SQL Server 2022 o migrar a una alternativa de código abierto. PostgreSQL 16 es una base de datos relacional madura, de alto rendimiento y sin coste de licencia. La migración no es trivial — el dialecto T-SQL de Microsoft no es SQL estándar y los tipos de datos difieren en varios puntos importantes. Esta guía detalla las incompatibilidades clave, la correspondencia de tipos y un plan de corte estructurado para evitar pérdida de datos y regresiones en la aplicación.",[35,39,50,53,89,92,112,115,118,122,125],{"type":36,"title":37,"body":38},"h2","SQL Server 2016: fin del soporte extendido el 14 de julio de 2026","La política de ciclo de vida de Microsoft prevé diez años de soporte para cada versión de SQL Server: cinco años de soporte estándar y luego cinco años de soporte extendido. Para SQL Server 2016, la fecha de fin del soporte extendido es el 14 de julio de 2026. Pasada esta fecha, Microsoft ya no publica actualizaciones de seguridad, correcciones críticas ni actualizaciones técnicas para esta versión. Una instancia de SQL Server 2016 expuesta en una red después de esta fecha acumula vulnerabilidades sin parchear. Los requisitos regulatorios — PCI-DSS, RGPD, ISO 27001 — exigen en general que los componentes de infraestructura reciban los parches de seguridad disponibles. Permanecer en SQL Server 2016 después de julio de 2026 constituye, por tanto, una desviación documentable en una auditoría.",{"type":40,"title":41,"items":42},"ul","Por qué elegir PostgreSQL en lugar de actualizar SQL Server o migrar a Azure SQL",[43,44,45,46,47,48,49],"Coste de licencia cero: PostgreSQL está bajo la licencia PostgreSQL (permisiva, similar a BSD), sin CAL y sin edición Enterprise separada que adquirir.","Control total de la infraestructura: en un VPS dedicado, se gestionan versiones, extensiones, parámetros de memoria y copias de seguridad sin depender de un proveedor cloud.","SQL Server 2022 resuelve la deuda de versión pero mantiene los costes de licencia y vincula la organización al ecosistema Microsoft.","Azure SQL Managed Instance simplifica la migración pero introduce un coste mensual recurrente, dependencia de Azure y restricciones de red adicionales.","PostgreSQL soporta las mismas funcionalidades avanzadas: funciones de ventana analíticas, CTE recursivas, JSON nativo, particionado de tablas, replicación lógica.","El ecosistema de herramientas es amplio: pgAdmin, DBeaver, Metabase, PostgREST, y la mayoría de ORM (Entity Framework, Hibernate, SQLAlchemy, ActiveRecord) soportan PostgreSQL.","Las principales distribuciones Linux empaquetan PostgreSQL con actualizaciones de seguridad regulares incluidas en el contrato de mantenimiento de la distribución.",{"type":36,"title":51,"body":52},"Auditoría preliminar: qué migra bien y qué requiere trabajo","Antes de escribir un solo comando de migración, es indispensable una auditoría del esquema. Los elementos que migran sin fricción son las tablas simples con tipos estándar, las restricciones `PRIMARY KEY`, `FOREIGN KEY`, `UNIQUE` y `NOT NULL`, los índices B-tree clásicos, las vistas sin sintaxis T-SQL propietaria y las secuencias. Los elementos que requieren trabajo explícito son los procedimientos almacenados y funciones T-SQL (sintaxis incompatible, hay que reescribirlos en PL\u002FpgSQL o moverlos a la capa de aplicación), los desencadenadores que usan las tablas virtuales `INSERTED` y `DELETED` (equivalente en PostgreSQL: `NEW` y `OLD`), las columnas `ROWVERSION`\u002F`TIMESTAMP` usadas para la detección de concurrencia optimista, las columnas calculadas, las sugerencias de bloqueo (`WITH (NOLOCK)`, `WITH (UPDLOCK)`) y las tablas temporales globales (`##temp`). Un inventario de SQL Server puede obtenerse consultando `INFORMATION_SCHEMA` y las vistas del sistema `sys.objects`, `sys.procedures`, `sys.triggers`.",{"type":54,"title":55,"rows":56,"headers":85},"comparison","Correspondencia de tipos SQL Server → PostgreSQL",[57,61,65,69,73,77,81],[58,59,60],"DATETIME2","TIMESTAMPTZ","Almacenar marcas de tiempo con zona horaria; DATETIME2 no lleva zona horaria, definir la convención UTC explícitamente",[62,63,64],"UNIQUEIDENTIFIER","UUID","PostgreSQL soporta el tipo UUID de forma nativa; usar la extensión `uuid-ossp` o `gen_random_uuid()` para la generación",[66,67,68],"NVARCHAR(MAX) \u002F NTEXT","TEXT","PostgreSQL almacena todas las cadenas en UTF-8; sin distinción NVARCHAR\u002FVARCHAR ni límite MAX separado",[70,71,72],"BIT","BOOLEAN","Los valores `0`\u002F`1` pasan a ser `false`\u002F`true`; atención a columnas BIT usadas como enteros en cálculos",[74,75,76],"MONEY \u002F SMALLMONEY","NUMERIC(19,4)","MONEY en SQL Server es un entero escalado, NUMERIC es exacto; comportamiento idéntico para cálculos financieros",[78,79,80],"INT IDENTITY(1,1)","SERIAL o GENERATED ALWAYS AS IDENTITY","SERIAL es un atajo a una secuencia; GENERATED ALWAYS AS IDENTITY es el estándar SQL:2003, preferible para tablas nuevas",[82,83,84],"ROWVERSION \u002F TIMESTAMP","bytea + trigger o xmin","Sin equivalente directo; la columna de sistema `xmin` gestiona la detección de concurrencia optimista en la mayoría de los casos",[86,87,88],"Tipo SQL Server","Tipo PostgreSQL","Observación",{"type":36,"title":90,"body":91},"Incompatibilidades T-SQL comunes y sus equivalentes en PostgreSQL","Varias construcciones T-SQL habituales no tienen equivalente directo en SQL estándar y requieren reescritura.\n\n`TOP N` sin `ORDER BY`: SQL Server acepta `SELECT TOP 10 * FROM t` sin cláusula de orden. PostgreSQL requiere `LIMIT 10`; si un orden definido es importante, añadir `ORDER BY` explícitamente.\n\n`ISNULL(expr, valor)`: la función T-SQL `ISNULL` tiene como equivalente estándar `COALESCE(expr, valor)`. El comportamiento es idéntico para los casos habituales.\n\n`GETDATE()` y `GETUTCDATE()`: estas funciones pasan a ser `NOW()` (marca de tiempo con zona horaria de la sesión) y `NOW() AT TIME ZONE 'UTC'` o `CURRENT_TIMESTAMP` respectivamente.\n\n`DATEDIFF` y `DATEADD`: PostgreSQL usa aritmética de intervalos: `date + INTERVAL '7 days'`, y `date2 - date1` devuelve un `INTERVAL`.\n\nSugerencia `WITH (NOLOCK)`: esta sugerencia solicita una lectura sin bloqueo compartido. PostgreSQL no soporta esta sugerencia; el nivel de aislamiento `READ COMMITTED` (por defecto) cubre la mayoría de casos de uso. Para informes analíticos que toleran datos ligeramente obsoletos, una réplica de lectura es la solución estructural.\n\n`PRINT` en procedimientos: usar `RAISE NOTICE 'mensaje'` en PL\u002FpgSQL.\n\n`GO` como separador de lotes: este separador no existe en PostgreSQL. Los scripts SQL deben reestructurarse en transacciones o bloques `DO $$...$$` separados.",{"type":93,"title":94,"steps":95},"steps","Plan de migración en 8 pasos",[96,98,100,102,104,106,108,110],{"body":97},"Inventario y auditoría del esquema: exportar la lista de todas las tablas, columnas con tipos, índices, restricciones, procedimientos almacenados, funciones, desencadenadores y vistas. Identificar y priorizar los objetos que requieren reescritura manual.",{"body":99},"Configurar el VPS PostgreSQL de destino: instalar PostgreSQL 16, configurar `postgresql.conf` (memoria compartida, conexiones, WAL), crear el usuario de aplicación con el mínimo de privilegios necesarios, habilitar TLS para conexiones remotas.",{"body":101},"Conversión del esquema y datos con pgloader o manualmente: `pgloader mssql:\u002F\u002Fuser:pass@host\u002Fdb postgresql:\u002F\u002Fuser:pass@vps\u002Fdb` migra el esquema y los datos con un solo comando. Para esquemas complejos, exportar el DDL de SQL Server y adaptarlo manualmente aplicando la tabla de correspondencia de tipos.",{"body":103},"Validar el esquema migrado: verificar el número de tablas, el conteo de filas por tabla, la integridad referencial (`FOREIGN KEY`) y los índices. Comparar los tipos reales con los esperados mediante `information_schema.columns`.",{"body":105},"Reescribir los procedimientos almacenados y desencadenadores: cada objeto T-SQL debe reescribirse en PL\u002FpgSQL o moverse a la capa de aplicación. Probar cada procedimiento de forma independiente con conjuntos de datos representativos.",{"body":107},"Adaptar el código de la aplicación: buscar en el código fuente todas las cadenas SQL literales y las consultas parametrizadas que usen construcciones T-SQL propietarias. Actualizar el driver de conexión (pasar de `mssql` a `pg`, `psycopg2`, `npgsql` o el driver apropiado para la pila tecnológica).",{"body":109},"Pruebas de carga y no regresión: ejecutar la suite completa de pruebas de regresión contra la base de datos PostgreSQL de staging. Usar `pgbench` para validar el rendimiento bajo carga. Comparar los planes de ejecución de las consultas críticas (`EXPLAIN ANALYZE`) entre SQL Server y PostgreSQL.",{"body":111},"Corte en ventana de mantenimiento: planificar una ventana (noche o fin de semana), poner la aplicación en modo mantenimiento, ejecutar una migración diferencial final (datos insertados desde la migración inicial), apuntar el DSN de la aplicación a PostgreSQL, validar las funciones críticas y levantar el mantenimiento. Mantener SQL Server en modo solo lectura durante 48 horas para permitir una reversión rápida si fuera necesario.",{"type":36,"title":113,"body":114},"Configurar PostgreSQL 16 en un VPS para producción","Una instalación PostgreSQL por defecto no está ajustada para producción. Los parámetros siguientes en `postgresql.conf` son un punto de partida para un VPS con 4 GB de RAM.\n\n`shared_buffers`: establecer al 25% de la RAM disponible, `1GB` para 4 GB. Este parámetro determina la memoria asignada a la caché interna de PostgreSQL.\n\n`effective_cache_size`: establecer al 75% de la RAM total, `3GB`. Este parámetro informa al planificador de consultas sobre la memoria disponible para la caché del sistema operativo.\n\n`work_mem`: de `16MB` a `64MB` según la complejidad de las consultas de ordenación. Este parámetro se aplica por operación de ordenación y por conexión; un valor demasiado alto en una instancia con muchas conexiones simultáneas agota la memoria.\n\n`maintenance_work_mem`: `256MB` para las operaciones de mantenimiento (`VACUUM`, `CREATE INDEX`).\n\n`max_connections`: `100` es suficiente para la mayoría de aplicaciones que usan un pool de conexiones. Si la aplicación abre una conexión por petición sin pool, usar PgBouncer como intermediario.\n\nPara `pg_hba.conf`, restringir las conexiones remotas a la dirección IP del servidor de aplicación y exigir TLS: `hostssl all appuser 10.0.0.5\u002F32 scram-sha-256`.\n\nHabilitar TLS generando un certificado (Let's Encrypt o certificado interno) y configurando `ssl = on`, `ssl_cert_file` y `ssl_key_file` en `postgresql.conf`.",{"type":36,"title":116,"body":117},"El riesgo de los procedimientos almacenados y desencadenadores T-SQL","Los procedimientos almacenados T-SQL son el principal punto de fricción en una migración de SQL Server a PostgreSQL. T-SQL es un dialecto propietario con estructuras de control, gestión de cursores y manejo de errores (bloques `TRY...CATCH`) que no tienen equivalente directo en PL\u002FpgSQL.\n\nLos cursores `FAST_FORWARD` de SQL Server pasan a ser bucles `FOR` en PL\u002FpgSQL, pero el rendimiento es similar y en cualquier caso el uso de cursores debe cuestionarse: una consulta basada en conjuntos reemplaza casi siempre a un cursor de forma más eficiente.\n\nEl bloque `TRY...CATCH` pasa a ser `BEGIN...EXCEPTION WHEN OTHERS THEN` en PL\u002FpgSQL.\n\nLas tablas temporales locales (`#temp`) corresponden a las tablas temporales de sesión en PostgreSQL, creadas con `CREATE TEMPORARY TABLE`. Las tablas temporales globales (`##temp`) no tienen equivalente directo — deben reemplazarse por tablas permanentes con gestión explícita del ciclo de vida.\n\nLos desencadenadores que referencian `INSERTED` y `DELETED` (tablas virtuales de SQL Server) deben reescribirse para usar `NEW` y `OLD` en PostgreSQL. La estructura de activación también difiere: PostgreSQL distingue entre desencadenadores `BEFORE` y `AFTER`, y entre `FOR EACH ROW` y `FOR EACH STATEMENT`.\n\nUn enfoque pragmático consiste en mover la lógica de los procedimientos almacenados a la capa de aplicación durante la migración, lo que simplifica las pruebas y reduce el acoplamiento entre la aplicación y la base de datos.",{"type":119,"title":120,"body":121},"tip","Prueba de carga antes del corte: pgbench y comparación de planes de consulta","Antes del corte a producción, validar el rendimiento con `pgbench`. Inicializar una base de datos de prueba representativa: `pgbench -i -s 50 nombre_bd` crea un esquema de referencia con 5 millones de filas. Ejecutar una simulación de carga: `pgbench -c 20 -j 4 -T 60 nombre_bd` simula 20 conexiones paralelas durante 60 segundos e informa de las transacciones por segundo. Para las consultas críticas de la aplicación, comparar los planes de ejecución entre SQL Server (`SET STATISTICS IO ON; SELECT ...`) y PostgreSQL (`EXPLAIN (ANALYZE, BUFFERS) SELECT ...`). Vigilar los escaneos completos de tabla inesperados (índice faltante o estadísticas no calculadas — ejecutar `ANALYZE` tras la migración) y las uniones `NESTED LOOP` sobre grandes volúmenes que se beneficiarían de un `HASH JOIN`. Actualizar las estadísticas tras la migración inicial con `ANALYZE nombre_tabla` o `VACUUM ANALYZE` para toda la base de datos.",{"type":36,"title":123,"body":124},"Resolución de problemas — errores frecuentes en una migración SQL Server → PostgreSQL","Varias categorías de errores aparecen sistemáticamente en las primeras migraciones.\n\n`ERROR: column is of type uuid but expression is of type character varying`: una columna `UNIQUEIDENTIFIER` migrada a `UUID` recibe una cadena con formato UUID sin conversión explícita. Adaptar la consulta de la aplicación para enviar un tipo UUID real, añadir una conversión implícita en PostgreSQL (`CREATE CAST`), o migrar la columna a `TEXT` si no se explota la semántica UUID.\n\n`ERROR: operator does not exist: boolean = integer`: una columna `BIT` migrada a `BOOLEAN` se compara con `0` o `1`. Reemplazar `col = 1` por `col = true` o simplemente `col` en las cláusulas `WHERE`.\n\n`ERROR: function isnull(character varying, text) does not exist`: reemplazar todas las ocurrencias de `ISNULL` por `COALESCE`.\n\n`ERROR: syntax error at or near \"TOP\"`: la sintaxis `SELECT TOP N` no existe en PostgreSQL. Reemplazar por `SELECT ... LIMIT N`.\n\nDesbordamientos silenciosos en columnas `MONEY` → `NUMERIC`: verificar que los valores extremos de la tabla de origen caben en la precisión objetivo `NUMERIC(19,4)`. SQL Server `MONEY` tiene un rango de ±922.337.203.685.477,5807; `NUMERIC(19,4)` cubre ±999.999.999.999.999,9999, suficiente en casi todos los casos.\n\nPérdida de datos en columnas `DATETIME` sin zona horaria: `DATETIME` y `DATETIME2` de SQL Server no almacenan la zona horaria. Si la base de datos era alimentada por aplicaciones en múltiples zonas horarias, las marcas de tiempo migradas a `TIMESTAMPTZ` sin conversión previa se interpretarán como UTC. Definir una convención (UTC u hora local) y aplicar un `AT TIME ZONE` durante la migración si es necesario.",{"type":36,"title":126,"body":127},"Verificar la migración y restablecer el acceso de usuarios","Tras el corte, una lista de verificación estructurada reduce el riesgo de devolver a los usuarios a una base de datos incompleta.\n\nVerificar el conteo de filas para todas las tablas críticas: consultar `information_schema.tables` con un `COUNT(*)` por tabla, comparado con las cifras registradas en SQL Server antes de la migración.\n\nVerificar la integridad referencial: `SELECT * FROM pg_constraint WHERE contype = 'f'` lista todas las restricciones de clave foránea; intentar una inserción que violaría una restricción para confirmar que está activa.\n\nVerificar los índices: `SELECT indexname, indexdef FROM pg_indexes WHERE schemaname = 'public'` lista todos los índices creados. Comparar con la lista de índices de SQL Server.\n\nProbar las funciones críticas de la aplicación: flujo de compra, autenticación, informes, exportaciones — como mínimo los flujos que tocan las tablas más voluminosas y las consultas más complejas.\n\nMonitorizar los logs de PostgreSQL durante las primeras 24 horas: `tail -f \u002Fvar\u002Flog\u002Fpostgresql\u002Fpostgresql-*.log`. Los errores de tipo (`character varying` vs `uuid`), los tiempos de espera de conexión o los planes de consulta subóptimos suelen manifestarse en las primeras horas de tráfico real.\n\nMantener SQL Server en modo solo lectura durante 48 horas con acceso restringido al equipo técnico. La reversión consiste en apuntar el DSN de la aplicación de vuelta a SQL Server y reproducir los datos escritos en PostgreSQL durante la ventana de corte.","VPS listos para PostgreSQL 16","VPS de ServOrbit configurados para PostgreSQL 16: SSD NVMe, snapshot diario, acceso root completo. Despliega tu base de datos migrada sin restricciones de licencia.","Ver VPS de ServOrbit","\u002Fsolutions\u002Fprofessionnels",[133,148],{"id":134,"slug":135,"slugs":136,"title":140,"excerpt":141,"readTime":142,"views":18,"isPinned":19,"publishedAt":143,"updatedAt":21,"category":144,"categories":145,"featuredImage":30,"bgImage":31,"posterImage":147,"relatedSolution":30},464,"mysql-8-0-fin-de-soporte-migracion-vps",{"fr":137,"en":138,"ar":139,"es":135},"mysql-8-0-eol-migration-vps","mysql-8-0-end-of-life-migration-vps","mysql-8-0-انتهاء-الدعم-ترقية-vps","Migrar MySQL 8.0 a 8.4 LTS en un VPS: guía paso a paso","MySQL 8.0 fin de vida el 30 de abril de 2026. Migra a MySQL 8.4 LTS — cambios incompatibles, requisitos previos, actualización in-place y cuándo elegir MariaDB 11.x.",10,"2026-10-17T00:00:00+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[146],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fmysql-8-0-eol-migration-vps-poster.svg",{"id":149,"slug":150,"slugs":151,"title":155,"excerpt":156,"readTime":157,"views":18,"isPinned":19,"publishedAt":158,"updatedAt":21,"category":159,"categories":160,"featuredImage":30,"bgImage":31,"posterImage":162,"relatedSolution":30},461,"migrar-postgresql-de-rds-cloud-sql-o-supabase-a-un-vps",{"fr":152,"en":153,"ar":154,"es":150},"postgresql-migrer-cloud-vers-self-hosted-vps","migrate-postgresql-from-rds-cloud-sql-supabase-to-vps","نقل-postgresql-من-rds-و-cloud-sql-و-supabase-إلى-vps","Migrar PostgreSQL de RDS o Cloud SQL a un VPS","Migración PostgreSQL desde RDS, Cloud SQL y Supabase hacia un VPS autogestionado: comandos exactos, trampas por fuente y cambio sin tiempo de inactividad.",13,"2026-10-16T00:00:00+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[161],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fpostgresql-migrer-cloud-vers-self-hosted-vps-poster.svg",1792361170285]