Funciones de string — Referencia de SQL en Marketing Cloud
Las funciones de string que MC SQL soporta — LEN, LEFT, RIGHT, SUBSTRING, LTRIM, RTRIM, LOWER, UPPER, REPLACE, CHARINDEX, CONCAT — más las reglas de producción para normalización, manejo de NULL, y la trampa del case-fold-mata-el-índice.
Las funciones de string en MC SQL son un subset de las de T-SQL. La lista es corta, la sintaxis es estándar, y los bugs de producción son mayormente sobre tres cosas: propagación de NULL a través de concatenación con +, truncación de longitud cuando hacés LEFT() para encajar en una columna de destino, y el efecto matador-de-índice de envolver una columna en LOWER() adentro de un WHERE.
Sintaxis oficial
-- Largo (en caracteres, no bytes — Unicode-safe)
SELECT LEN(EmailAddress) AS EmailLen FROM master_subscribers;
-- Extracción de substring
SELECT
LEFT(EmailAddress, 5) AS FirstFive,
RIGHT(EmailAddress, 4) AS LastFour,
SUBSTRING(EmailAddress, 2, 6) AS PositionTwoLenSix
FROM master_subscribers;
-- Trim de espacios
SELECT LTRIM(RTRIM(SubscriberKey)) AS KeyClean FROM _Subscribers;
-- Conversión de case
SELECT
LOWER(EmailAddress) AS EmailLower,
UPPER(LoyaltyTier) AS TierUpper
FROM master_subscribers;
-- Replace
SELECT REPLACE(PhoneNumber, '-', '') AS PhoneClean
FROM master_subscribers;
-- Encontrar posición (devuelve 0 si no se encuentra, NO -1)
SELECT
EmailAddress,
CHARINDEX('@', EmailAddress) AS AtPosition
FROM master_subscribers;
-- Concatenación: usá CONCAT (NULL-safe) sobre + (NULL-poisoning)
SELECT
CONCAT(FirstName, ' ', LastName) AS FullNameSafe,
FirstName + ' ' + LastName AS FullNameRisky
FROM master_subscribers;El set soportado entre la mayoría de los tenants SFMC:
| Función | Qué hace | Devuelve |
|---|---|---|
| LEN(s) | Largo en caracteres (espacios trailing ignorados) | INT |
| LEFT(s, n) | Primeros n caracteres | NVARCHAR |
| RIGHT(s, n) | Últimos n caracteres | NVARCHAR |
| SUBSTRING(s, start, len) | len chars empezando en posición start (1-indexada) | NVARCHAR |
| LTRIM(s) / RTRIM(s) | Trim de espacios leading / trailing | NVARCHAR |
| LOWER(s) / UPPER(s) | Case fold | NVARCHAR |
| REPLACE(s, old, new) | Reemplaza todas las ocurrencias de old con new | NVARCHAR |
| CHARINDEX(needle, haystack) | Posición 1-indexada de needle en haystack, o 0 si no se encuentra | INT |
| CONCAT(s1, s2, ...) | Concatenar, NULL-safe (NULLs se vuelven strings vacíos) | NVARCHAR |
| s1 + s2 | Concatenar, NULL-poisoning (NULL en cualquier lado → NULL en resultado) | NVARCHAR |
Referencia:
Lo que sobrevive en producción
Usá CONCAT, no +, cuando algún operando puede ser NULL
'Hello ' + NULL + 'World' devuelve NULL, no 'Hello World'. Cada concatenación con + que involucre una columna que puede ser NULL es una trampa de NULL silenciosa.
-- EN RIESGO — si FirstName o LastName es NULL, el resultado es NULL
SELECT FirstName + ' ' + LastName AS FullName
FROM master_subscribers;
-- DURABLE — CONCAT trata NULL como string vacío
SELECT CONCAT(FirstName, ' ', LastName) AS FullName
FROM master_subscribers;
-- O, si tenés que usar + (ej. para un alias que necesita el espacio
-- explícito en el medio), envolvé cada operando en COALESCE
SELECT COALESCE(FirstName, '') + ' ' + COALESCE(LastName, '') AS FullName
FROM master_subscribers;+ propaga NULL por compatibilidad backward de T-SQL. CONCAT no. Elegí CONCAT por default salvo que quieras el comportamiento NULL a propósito.
LTRIM(RTRIM(...)) es la red de seguridad de SubscriberKey
Cuando joineás SubscriberKey entre DEs (o contra _Subscribers), los espacios trailing de un import CSV o un export de CRM son el killer silencioso. Siempre normalizá en los dos lados, incluso cuando estés seguro de que el dato está limpio — el costo es una llamada de función extra por fila, el ahorro es el post-mortem que no tenés que escribir.
-- DEFENSIVO — incluso cuando SubscriberKey parece limpio, normalizá
SELECT s.SubscriberKey, e.LoyaltyTier
FROM _Subscribers s
INNER JOIN ext_loyalty e
ON LTRIM(RTRIM(CAST(s.SubscriberKey AS NVARCHAR(255))))
= LTRIM(RTRIM(CAST(e.UserId AS NVARCHAR(255))));Ver JOIN y gotchas — #9 para la trampa completa de SubscriberKey type-coercion + trim.
LOWER() / UPPER() en WHERE mata el índice — stagéa en su lugar
Envolver una columna en LOWER() para una comparación case-insensitive fuerza un full table scan porque el índice no se puede usar. En un Data Extension de 5M filas es la diferencia entre una query de 30 segundos y un timeout de 30 minutos.
-- EN RIESGO — LOWER() en la columna mata el índice, full scan
SELECT SubscriberKey
FROM master_subscribers
WHERE LOWER(LoyaltyTier) = 'gold';
-- MEJOR CUANDO ES POSIBLE — normalizá en momento de escritura, no de lectura.
-- Stagéa una columna LoyaltyTierLower en un de_stg_*, después indexá esa.
INSERT INTO de_stg_subscribers_normalized
SELECT
SubscriberKey,
LoyaltyTier,
LOWER(LoyaltyTier) AS LoyaltyTierLower
FROM master_subscribers;
-- Después producción lee contra la columna normalizada:
SELECT SubscriberKey
FROM de_stg_subscribers_normalized
WHERE LoyaltyTierLower = 'gold';El trade es más almacenamiento + un paso de staging, a cambio de lecturas rápidas para siempre. Pagalo una vez.
LEFT() para encajar en una columna de destino = truncación silenciosa
Si tu DE de destino tiene EmailAddress VARCHAR(50) y tu fuente es de hasta 75 chars, LEFT(EmailAddress, 50) trunca silenciosamente sin surfacear qué filas perdieron datos. O redimensioná el destino, o contá las truncaciones explícitamente.
-- DIAGNÓSTICO — contá filas que se truncarían, antes de hacerlo
SELECT
COUNT(*) AS TotalRows,
SUM(CASE WHEN LEN(EmailAddress) > 50 THEN 1 ELSE 0 END) AS WouldTruncate
FROM master_subscribers;Corré esto contra producción antes de cambiar largos de columna o agregar llamadas a LEFT(). Ver gotchas — #5.
Decisión rápida
Usá CONCAT en lugar de + cuando:
- Algún operando puede ser NULL.
- Default para código nuevo.
+solo es útil cuando querés propagación de NULL específicamente.
Usá LTRIM(RTRIM(...)) siempre cuando:
- Joineás o comparás
SubscriberKeyo cualquier identificador externo.
Stagéa los resultados de LOWER() / UPPER() en una columna cuando:
- El DE de origen es grande y la comparación corre seguido. Normalización en momento de lectura está bien para queries one-shot; para producción, normalizá en momento de escritura.
Usá LEFT() / SUBSTRING() con cuidado cuando:
- El largo de columna del destino es fijo. Corré el diagnóstico de conteo primero.
Andá a CHARINDEX en lugar de LIKE cuando:
- Solo necesitás saber si un substring está presente (y no necesitás wildcards). Es más rápido que
LIKE '%x%'y la intención es más clara.
Relacionado
- Basics — subset de T-SQL soportado
- SELECT — funciones de string en proyección
- WHERE — funciones de string en filtros (y la trampa de matar el índice)
- JOIN —
LTRIM(RTRIM())para seguridad de SubscriberKey - LIKE — pattern matching (relacionado pero distinto a
CHARINDEX) - MC SQL gotchas — ver #5 (truncación de longitud), #9 (SubscriberKey trim/cast)
Próximas páginas de referencia de funciones: Date · Numeric · Conversion · Aggregate · Null Functions.
Más snippets how-to para debugging común en producción — sends de email, largo de valores, alcance de contactos, etc.