Skip to main content

Debugging de largo de valores con SQL

La truncación silenciosa de strings es el bug que te encuentra semanas después — emails que se mergean al subscriber equivocado, códigos perdiendo su sufijo, nombres cortados en el caracter N. Tres queries para encontrar valores truncados, auditar anchos de columna del DE de destino, y prevenir el próximo.

Cómo hacerlo·Actualizado 2026-05-07·Escrito por Lira · Editado por German Medina

Estás seguro de que las direcciones de email que importaste eran correctas. El CSV tenía german.medina@reallylongdomain.example.com. El DE de destino tiene EmailAddress guardado. Una semana después, dos subscribers no relacionados están recibiendo cada uno el mail del otro porque las dos direcciones de email guardadas ahora son german.medina@reallylongdomain.example. La columna del DE de destino es VARCHAR(40) y Marketing Cloud truncó las dos direcciones al mismo prefijo de 40 caracteres.

Esto es truncación silenciosa de longitud. Es gotcha #5 a escala, y aparece más seguido en tres escenarios: campos de dirección después de imports de CRM, campos de código/SKU custom con sufijos más largos de lo esperado, y campos SubscriberKey cuando el origen es un UUID o un identificador hasheado. Las queries de diagnóstico abajo encuentran valores truncados que ya aterrizaron y las columnas en riesgo de truncar futuras escrituras.

El flujo de diagnóstico

1. Auditar anchos de columna del DE de destino (¿cuál es el cap en cada columna?)
2. Medir MAX(LEN()) del origen (¿qué se insertaría, sin truncar?)
3. Encontrar filas ya truncadas (LEN() == max para la columna del destino)
4. Encontrar colisiones aguas abajo (duplicados creados por truncación)

Step 1 — Auditar anchos de columna del DE de destino

La UI de Marketing Cloud te dice el setting Length de cada columna en las propiedades del DE, pero si tenés muchos DEs para auditar, queryea las System Data Views _DataExtension y _DataExtensionField (fuente de verdad) una vez y hacé snapshot:

-- Auditoría one-time: schema + largo de cada columna en cada DE que sos dueño.
-- Snapshot a un de_log_ así podés comparar contra corridas futuras.
INSERT INTO de_log_de_field_widths
SELECT
  de.Name                     AS DEName,
  def.Name                    AS ColumnName,
  def.FieldType               AS FieldType,
  def.MaxLength               AS MaxLength,
  def.IsNullable              AS IsNullable,
  def.IsPrimaryKey            AS IsPrimaryKey,
  GETDATE()                   AS SnapshotAt
FROM _DataExtensionField def
INNER JOIN _DataExtension de
  ON def.DataExtensionCustomerKey = de.CustomerKey
WHERE def.FieldType IN ('Text', 'EmailAddress')
  AND de.Name LIKE 'DE\_%' ESCAPE '\';   -- solo tus master DEs

Ahora tenés un snapshot del MaxLength de cada columna de texto. Diffeá el snapshot semana-a-semana para surfacear columnas a las que alguien les cambió el largo editando el DE en la UI.

Step 2 — Medir MAX(LEN()) del origen

Para cada columna de texto que está por insertarse, corré una sola query contra el origen para encontrar el valor más largo:

-- Reemplazá master_subscribers con tu DE de origen
SELECT
  COUNT(*)                            AS TotalRows,
  MAX(LEN(EmailAddress))              AS MaxEmailLen,
  MAX(LEN(FirstName))                 AS MaxFirstNameLen,
  MAX(LEN(LastName))                  AS MaxLastNameLen,
  MAX(LEN(LoyaltyTier))               AS MaxTierLen,
  MAX(LEN(SubscriberKey))             AS MaxSubKeyLen
FROM master_subscribers;

Compará estos números contra el MaxLength del DE de destino del step 1. Cada columna donde el max del origen excede el cap del destino va a truncar en la próxima inserción.

La defensa:

-- Diagnóstico: ¿qué filas se truncarían, y por cuánto?
SELECT
  SubscriberKey,
  EmailAddress,
  LEN(EmailAddress)         AS SourceLen,
  50                        AS DestinationLen,   -- el cap del destino
  LEN(EmailAddress) - 50    AS WouldTruncateBy
FROM master_subscribers
WHERE LEN(EmailAddress) > 50
ORDER BY LEN(EmailAddress) DESC;

Corré esto contra volumen de producción antes de un INSERT INTO ... SELECT que apunta a un destino más angosto. O redimensioná la columna del destino, o escribí una llamada LEFT() documentada así la truncación es intencional.

Step 3 — Encontrar filas ya truncadas

Si el DE de destino estuvo recibiendo valores truncados un tiempo, el bug ya está en producción. La firma de un valor truncado es LEN(col) = destination_max_length.

-- Encontrar cada fila en el DE de producción donde la dirección de email
-- es exactamente el largo máximo de la columna del destino. Estas son las
-- filas donde el valor original era POR LO MENOS de ese largo; algunas son
-- legítimas, muchas están truncadas.
SELECT
  SubscriberKey,
  EmailAddress,
  LEN(EmailAddress) AS Len
FROM destination_de
WHERE LEN(EmailAddress) = 50    -- el largo máximo del destino
ORDER BY EmailAddress;

Una fila donde EmailAddress termina en .com, .org, .net etc. lo más probable no está truncada — el dominio terminó limpio. Una fila donde EmailAddress termina a mitad de palabra ('german.medina@reallylongdomain.example', sin TLD) está casi seguro truncada.

Para IDs numéricos / SubscriberKeys, la firma es la misma: LEN(SubscriberKey) = destination_max_length más el valor no teniendo los separadores estructurales que esperarías (un UUID sin sus caracteres finales, un ID entero que es múltiplo exacto del ancho de columna).

Step 4 — Encontrar colisiones aguas abajo

El daño de la truncación generalmente no es el valor truncado en sí — son los duplicados que la truncación crea. Dos valores de origen distintos que comparten los mismos primeros N caracteres se vuelven el mismo valor en el destino, y la lógica de joins / dedup aguas abajo ahora los trata como el mismo subscriber.

-- Encontrar emails truncados que colisionan con otro email en el DE
SELECT
  EmailAddress,
  COUNT(*) AS DuplicateCount
FROM destination_de
WHERE LEN(EmailAddress) = 50
GROUP BY EmailAddress
HAVING COUNT(*) > 1
ORDER BY DuplicateCount DESC;

Cada fila con DuplicateCount > 1 representa N subscribers de origen distintos que ahora son indistinguibles en el destino. Si la Send Definition deduplica por EmailAddress, solo uno va a recibir cada email. Si tus cálculos de loyalty agrupan por EmailAddress, sus puntos ahora están pooleados.

Causas comunes rankeadas por frecuencia

| Causa | Dónde mirar | |---|---| | El DE de destino se creó con un VARCHAR(50) por default cuando el origen permite más | Snapshot del Step 1 vs mediciones de max del Step 2 | | Un import CSV agregó una columna nueva y el destino no se redimensionó | Diff de_log_de_field_widths semana-a-semana | | LEFT(col, n) se agregó al SELECT para "encajar" la columna sin chequear el costo | Auditar commits recientes a la SQL Activity | | El origen migró y ahora contiene UUIDs / hashes / formatos más largos | Step 2 contra origen vs snapshot de la semana previa | | Campo de código custom dimensionado para SKU de 6 chars pero los proveedores ahora mandan códigos compuestos de 12 chars | Step 3 contra la columna SKU |

Playbook de remediación

Una vez confirmada la truncación:

  1. Detené el sangrado. Desactivá la Activity que está escribiendo los valores truncados hasta que el destino se redimensione.
  2. Redimensioná la columna del DE de destino en la UI (propiedades del DE → columna → Length). Notá que redimensionar es no-destructivo para data existente — las filas ya truncadas quedan truncadas; solo las nuevas escrituras obtienen el ancho nuevo.
  3. Re-importá las filas truncadas desde el origen si podés identificarlas. La query del Step 4 te da los SubscriberKeys; un INSERT INTO ... SELECT desde el origen original con modo Update las reescribe con los valores completos.
  4. Agregá la auditoría de ancho de columna (step 1) a una Automation de diagnósticos scheduleada así cualquier edición futura de propiedades de DE dispara una fila en de_log_de_field_widths que podés revisar.
  5. Documentá la nueva política de ancho de columna en la Style Guide del equipo — para columnas EmailAddress usamos 254 (el max RFC), para SubscriberKey usamos 254 mínimo, etc.

Relacionado

  • INSERT INTO — el path de escritura donde la truncación pasa silenciosa
  • Funciones de stringLEN() para medir valores de origen, LEFT() para truncación intencional
  • SELECT — proyección de columnas explícita así los cambios de ancho del destino son visibles
  • FROM — SDVs _DataExtension / _DataExtensionField para auditorías de ancho de columna
  • MC SQL gotchas — ver #5 para el comportamiento subyacente de truncación de longitud
  • Style Guide — la política de ancho de columna que esto previene
  • Debugging de email sends — el how-to relacionado para discrepancias de send-vs-esperado (seguido causadas por emails truncados)