Etiqueta: sql-server

  • Tipos de datos SSIS vs SQL Server: tabla de equivalencias y errores comunes

    SSIS (SQL Server Integration Services) maneja su propio sistema de tipos de datos internamente, distinto al de SQL Server — cuando un paquete SSIS lee o escribe datos de una tabla, el motor de flujo de datos convierte automáticamente entre ambos sistemas. Conocer esta tabla de equivalencias es clave para evitar truncamientos silenciosos, pérdida de precisión, o errores de conversión que aparecen solo en tiempo de ejecución.

    Tabla de equivalencias

    Tipo SSISExpresión SSISEquivalente en SQL Server
    Entero con signo de 1 byte(DT_I1)— (sin equivalente directo)
    Entero con signo de 2 bytes(DT_I2)smallint
    Entero con signo de 4 bytes(DT_I4)int
    Entero con signo de 8 bytes(DT_I8)bigint
    Entero sin signo de 1 byte(DT_UI1)tinyint
    Entero sin signo de 2 bytes(DT_UI2)— (sin equivalente directo)
    Entero sin signo de 4 bytes(DT_UI4)— (sin equivalente directo)
    Entero sin signo de 8 bytes(DT_UI8)— (sin equivalente directo)
    Flotante(DT_R4)real
    Flotante de doble precisión(DT_R8)float
    Cadena de texto(DT_STR, «longitud», «code_page»)char, varchar
    Texto Unicode(DT_WSTR, «longitud»)nchar, nvarchar, sql_variant, xml
    Fecha(DT_DATE)date
    Booleano(DT_BOOL)bit
    Numérico(DT_NUMERIC, «precisión», «escala»)decimal, numeric
    Decimal(DT_DECIMAL, «escala»)decimal
    Moneda(DT_CY)smallmoney, money
    Identificador único(DT_GUID)uniqueidentifier
    Flujo de bytes(DT_BYTES, «longitud»)binary, varbinary, timestamp
    Fecha de base de datos(DT_DBDATE)date
    Hora de base de datos(DT_DBTIME)— (sin equivalente directo)
    Hora de base de datos con precisión(DT_DBTIME2, «escala»)time(p)
    Timestamp de base de datos(DT_DBTIMESTAMP)datetime, smalldatetime
    Timestamp con precisión(DT_DBTIMESTAMP2, «escala»)datetime2
    Timestamp con zona horaria(DT_DBTIMESTAMPOFFSET, «escala»)datetimeoffset(p)
    Timestamp de archivo(DT_FILETIME)— (sin equivalente directo)
    Imagen(DT_IMAGE)image
    Flujo de texto(DT_TEXT, «code_page»)text
    Cadena Unicode larga(DT_NTEXT)ntext

    Cómo usar estas expresiones en un Derived Column

    Estas notaciones ((DT_WSTR, 50), (DT_I4), etc.) se usan directamente como operadores de conversión (cast) dentro de expresiones de SSIS — típicamente en un componente Derived Column del Data Flow:

    (DT_WSTR, 50) [NombreColumna]
    (DT_I4) [CodigoTexto]
    (DT_NUMERIC, 18, 2) [MontoTexto]

    El operador se coloca entre paréntesis, antepuesto a la columna o expresión a convertir — funciona de forma similar a un CAST() en T-SQL, pero con la sintaxis propia del lenguaje de expresiones de SSIS.

    Errores comunes al trabajar con estos tipos

    1. Truncamiento silencioso de strings

    (DT_WSTR, «longitud») y (DT_STR, «longitud») requieren especificar una longitud fija. Si el dato origen es más largo que la longitud declarada, SSIS trunca el valor sin lanzar error por defecto — a menos que se configure explícitamente el comportamiento de «truncation» del componente como Fail Component en vez de Ignore Failure. Es una causa muy común de datos incompletos en destino que pasan desapercibidos durante meses.

    2. DT_STR vs DT_WSTR: ANSI vs Unicode

    DT_STR corresponde a cadenas ANSI (require especificar code_page, la página de códigos) y se destina a columnas char/varchar. DT_WSTR es Unicode (UTF-16 interno) y corresponde a nchar/nvarchar. Usar el tipo equivocado entre estos dos es una fuente frecuente de errores de conversión o de caracteres especiales (acentos, ñ) que se corrompen al pasar de un sistema a otro.

    3. Precisión y escala en DT_NUMERIC / DT_DECIMAL

    Al convertir hacia (DT_NUMERIC, «precisión», «escala»), ambos parámetros son obligatorios y deben coincidir (o ser compatibles) con la columna destino en SQL Server. Una precisión insuficiente trunca los decimales o genera un error de overflow si el valor origen excede el rango declarado.

    4. DT_DBTIMESTAMP vs DT_DBTIMESTAMP2: rango y precisión

    datetime (mapeado desde DT_DBTIMESTAMP) tiene menor precisión de fracciones de segundo y un rango de fechas más limitado que datetime2 (mapeado desde DT_DBTIMESTAMP2). Si el origen de datos maneja fechas fuera del rango de datetime (años anteriores a 1753) o requiere mayor precisión de milisegundos, es necesario usar explícitamente DT_DBTIMESTAMP2 y una columna destino datetime2.

    5. Tipos sin equivalente directo

    Varios tipos SSIS (DT_I1, DT_UI2, DT_UI4, DT_UI8, DT_DBTIME, DT_FILETIME) no tienen un tipo equivalente exacto en SQL Server. Al mapear estas columnas hacia una tabla destino, es necesario elegir el tipo SQL Server más cercano que pueda contener el rango completo de valores sin pérdida — por ejemplo, un DT_UI4 (entero sin signo de 4 bytes, rango 0 a ~4.29 mil millones) requiere un bigint en SQL Server, ya que int es signado y no cubre ese rango completo.

    Buena práctica: validar el mapeo antes de ejecutar en producción

    Antes de dar por válido un flujo de datos SSIS con conversiones de tipo, conviene ejecutar el paquete contra un subconjunto de datos «límite» (valores máximos de longitud, fechas extremas, números con la mayor cantidad de decimales esperada) para confirmar que ninguna conversión trunca o falla silenciosamente antes de correrlo contra la carga completa en producción.

  • Configurar Database Mail en SQL Server: perfiles, cuentas y sp_send_dbmail

    Database Mail es el mecanismo nativo de SQL Server para enviar correos electrónicos directamente desde la base de datos — usado típicamente para alertas de Agent Jobs, notificaciones de errores, o reportes automáticos. Esta guía cubre cómo crear un perfil nuevo replicando la configuración de uno existente, junto con la prueba de envío y el rollback completo si algo sale mal.

    Add Post

    Conceptos: perfil, cuenta y su relación

    Database Mail separa la configuración en tres piezas independientes, relacionadas entre sí:

    • Cuenta (account) — contiene los datos técnicos de conexión SMTP: servidor, puerto, credenciales, si usa SSL, y el correo/nombre que aparece como remitente.
    • Perfil (profile) — una capa de abstracción por encima de una o varias cuentas. Es el nombre que efectivamente se usa al enviar un correo (por ejemplo, desde un Job de SQL Server Agent) — nunca se referencia la cuenta directamente.
    • Relación perfil-cuenta — vincula ambos, con un sequence_number que define el orden de intento: si la cuenta principal falla, Database Mail prueba la siguiente cuenta asociada al mismo perfil, en orden.

    Esta separación permite, por ejemplo, tener un mismo perfil con dos cuentas SMTP distintas como respaldo, sin que las aplicaciones o jobs que usan el perfil necesiten saber nada sobre el failover.

    Script de creación completo

    USE msdb;
    GO
    
    -- 1. Crear la cuenta SMTP
    EXEC msdb.dbo.sysmail_add_account_sp
        @account_name              = 'cuenta_nuevo_entorno',
        @description               = 'Cuenta SMTP para el nuevo entorno',
        @email_address             = '[email protected]',
        @display_name              = 'Alertas Sistema',
        @replyto_address           = NULL,
        @mailserver_name           = 'smtp.tudominio.com',
        @port                      = 25,
        @enable_ssl                = 0,
        @username                  = NULL,
        @password                  = NULL,
        @use_default_credentials   = 0;
    GO
    
    -- 2. Crear el perfil
    EXEC msdb.dbo.sysmail_add_profile_sp
        @profile_name = 'PERFIL_NUEVO_ENTORNO',
        @description  = 'Perfil de correo para el nuevo entorno';
    GO
    
    -- 3. Vincular la cuenta al perfil
    EXEC msdb.dbo.sysmail_add_profileaccount_sp
        @profile_name    = 'PERFIL_NUEVO_ENTORNO',
        @account_name    = 'cuenta_nuevo_entorno',
        @sequence_number = 1;
    GO
    
    -- 4. Autorizar el perfil para uso público (todos los usuarios de msdb)
    EXEC msdb.dbo.sysmail_add_principalprofile_sp
        @profile_name   = 'PERFIL_NUEVO_ENTORNO',
        @principal_name = 'public',
        @is_default     = 0;
    GO

    Qué hace cada procedimiento almacenado

    ProcedimientoFunción
    sysmail_add_account_spCrea la cuenta SMTP con los parámetros de conexión
    sysmail_add_profile_spCrea el perfil (el nombre lógico que se usará al enviar correos)
    sysmail_add_profileaccount_spVincula una cuenta existente a un perfil existente
    sysmail_add_principalprofile_spOtorga permiso de uso del perfil a un principal (usuario o rol de base de datos); public lo hace disponible para todos

    Sobre @is_default: cuando se marca en 1, ese perfil se usa automáticamente si un envío de correo no especifica ningún @profile_name explícitamente. Es recomendable dejarlo en 0 salvo que se quiera intencionalmente ese comportamiento, para evitar que jobs mal configurados terminen enviando correos por el perfil equivocado.

    Validación de la configuración

    Antes de dar por buena la configuración, conviene confirmar que las tres piezas quedaron correctamente enlazadas consultando las vistas de catálogo correspondientes:

    -- Ver todos los perfiles configurados
    SELECT * FROM msdb.dbo.sysmail_profile;
    
    -- Ver todas las cuentas SMTP configuradas
    SELECT * FROM msdb.dbo.sysmail_account;
    
    -- Ver la relación entre perfiles y cuentas
    SELECT * FROM msdb.dbo.sysmail_profileaccount;
    
    -- Ver qué principals tienen acceso a cada perfil
    SELECT * FROM msdb.dbo.sysmail_principalprofile;

    Prueba de envío

    EXEC msdb.dbo.sp_send_dbmail
        @profile_name = 'PERFIL_NUEVO_ENTORNO',
        @recipients   = '[email protected]',
        @subject      = 'Prueba de perfil',
        @body         = 'El perfil está funcionando correctamente.';

    sp_send_dbmail encola el correo en la cola interna de Database Mail (tabla msdb.dbo.sysmail_mailitems) — el envío real no es instantáneo, lo procesa un proceso externo (DatabaseMail.exe) que SQL Server lanza bajo demanda. Para verificar si el correo realmente salió o quedó atascado:

    -- Ver el estado del último correo enviado
    SELECT TOP 10 * 
    FROM msdb.dbo.sysmail_allitems
    ORDER BY send_request_date DESC;
    
    -- Ver errores específicos de envío, si los hay
    SELECT * FROM msdb.dbo.sysmail_event_log
    ORDER BY log_date DESC;

    La columna sent_status en sysmail_allitems indica si el correo quedó como unsent, sent, o failed — este es el primer lugar a revisar si sp_send_dbmail se ejecutó sin error pero el correo nunca llegó.

    Rollback completo

    Si es necesario deshacer toda la configuración (por ejemplo, tras una prueba en un entorno que no corresponde), el orden de eliminación es el inverso al de creación — primero se deben quitar las relaciones antes que los objetos base:

    USE msdb;
    GO
    
    -- 1. Quitar el permiso del principal sobre el perfil
    EXEC msdb.dbo.sysmail_delete_principalprofile_sp
        @profile_name = 'PERFIL_NUEVO_ENTORNO',
        @principal_name = 'public';
    GO
    
    -- 2. Desvincular la cuenta del perfil
    EXEC msdb.dbo.sysmail_delete_profileaccount_sp
        @profile_name = 'PERFIL_NUEVO_ENTORNO',
        @account_name = 'cuenta_nuevo_entorno';
    GO
    
    -- 3. Eliminar el perfil
    EXEC msdb.dbo.sysmail_delete_profile_sp
        @profile_name = 'PERFIL_NUEVO_ENTORNO';
    GO
    
    -- 4. Eliminar la cuenta SMTP
    EXEC msdb.dbo.sysmail_delete_account_sp
        @account_name = 'cuenta_nuevo_entorno';
    GO

    Requisito adicional: habilitar Database Mail

    Si es la primera vez que se configura Database Mail en una instancia, el subsistema puede estar deshabilitado por defecto — hay que activarlo a nivel de configuración avanzada antes de que cualquiera de los procedimientos anteriores funcione:

    EXEC sp_configure 'show advanced options', 1;
    RECONFIGURE;
    GO
    
    EXEC sp_configure 'Database Mail XPs', 1;
    RECONFIGURE;
    GO

    Notas prácticas

    • El puerto 25 sin SSL (como en el ejemplo) es común en relays SMTP internos dentro de una red corporativa, pero no es apropiado para enviar directamente a través de internet — para eso se necesita normalmente el puerto 587 con @enable_ssl = 1 y credenciales de autenticación.
    • Si @use_default_credentials = 0 y no se especifica @username/@password, la cuenta SMTP asume que el servidor de correo permite retransmisión (relay) sin autenticación desde la IP del servidor SQL — esto debe estar explícitamente autorizado en el servidor de correo o relay correspondiente.
    • Antes de dar por completada la configuración en un entorno productivo, siempre correr la prueba de sp_send_dbmail y confirmar en sysmail_allitems que el estado sea sent, no solo confirmar que el EXEC no arrojó error.