1. Comprende $CHAR(0) vs cadena vacía vs SQL NULL
Puntos Clave
- Cadena vacía `""`: El valor por defecto "indefinido" en ObjectScript; no es lo mismo que SQL NULL
- `$CHAR(0)` (o `$C(0)`): Una cadena de un solo carácter que contiene ASCII 0; se mapea a SQL NULL en InterSystems IRIS
- SQL NULL: Significa "desconocido/ausente"; diferente de la cadena vacía en la semántica SQL
- IS NULL vs = '': `WHERE col IS NULL` verifica SQL NULL (`$C(0)`); `WHERE col = ''` verifica cadena vacía
- Puente objeto-SQL: Cuando una propiedad no tiene valor (cadena vacía en ObjectScript), se proyecta como cadena vacía en SQL, NO como NULL
- NULL explícito: Para almacenar un verdadero SQL NULL vía ObjectScript, establecer la propiedad a `$C(0)`
Notas Detalladas
Descripción general
Uno de los temas más frecuentemente evaluados y comúnmente malentendidos en InterSystems IRIS es la relación entre cadenas vacías, $CHAR(0) y SQL NULL. Esta distinción de tres vías es única de InterSystems IRIS debido a su modelo de datos unificado objeto-SQL, y equivocarse conduce a errores sutiles en consultas y manejo de datos.
Cadena vacía en ObjectScript
En ObjectScript, la cadena vacía "" es el valor inicial por defecto de cualquier variable o propiedad no establecida. Es una cadena de longitud cero, no null, no indefinida en el sentido SQL. Cuando accede a una propiedad que nunca se ha establecido, obtiene "":
SET obj = ##class(MyApp.Patient).%New()
WRITE obj.MiddleName // "" (cadena vacía - el valor por defecto)
WRITE $LENGTH(obj.MiddleName) // 0
WRITE (obj.MiddleName = "") // 1 (verdadero)
En SQL, cuando este objeto se guarda, la columna MiddleName contendrá una cadena vacía, no NULL:
-- Después de guardar el objeto anterior:
SELECT ID, MiddleName FROM MyApp.Patient WHERE ID = 1
-- Devuelve: MiddleName = '' (cadena vacía)
SELECT ID FROM MyApp.Patient WHERE MiddleName IS NULL
-- ¡NO devuelve esta fila!
SELECT ID FROM MyApp.Patient WHERE MiddleName = ''
-- SÍ devuelve esta fila
$CHAR(0) como SQL NULL
$CHAR(0) (abreviado $C(0)) es un solo carácter con código ASCII 0. InterSystems IRIS usa este valor especial como la representación en ObjectScript de SQL NULL. Cuando una propiedad se establece a $C(0), se proyecta como NULL en SQL:
// Establecer una propiedad a SQL NULL vía ObjectScript
SET obj.MiddleName = $CHAR(0)
SET sc = obj.%Save()
// Ahora en SQL:
// SELECT MiddleName FROM MyApp.Patient WHERE ID = 1
// Devuelve: NULL
// SELECT ID FROM MyApp.Patient WHERE MiddleName IS NULL
// SÍ devuelve esta fila
Verificar $CHAR(0) en ObjectScript
// Después de abrir un objeto que tiene NULL en SQL
SET obj = ##class(MyApp.Patient).%OpenId(1)
// Verificar si el valor es SQL NULL
IF obj.MiddleName = $C(0) {
WRITE "Value is SQL NULL", !
}
// Verificar si el valor es cadena vacía
IF obj.MiddleName = "" {
// Esto es FALSE para $C(0) — son cadenas diferentes
// $C(0) es un solo carácter (ASCII 0), "" es longitud cero
WRITE "Value is truly empty", !
}
// Para distinguir $C(0) de cadena vacía y valores reales:
IF obj.MiddleName = $C(0) {
WRITE "This is $C(0) - SQL NULL marker", !
} ELSEIF obj.MiddleName = "" {
WRITE "This is truly empty string", !
} ELSE {
WRITE "This has a value: ", obj.MiddleName, !
}
Comportamiento de SQL NULL en consultas
SQL NULL sigue la lógica estándar de tres valores de SQL (TRUE, FALSE, UNKNOWN):
-- Comparaciones con NULL
SELECT * FROM MyApp.Patient WHERE MiddleName = NULL -- ¡INCORRECTO! Siempre devuelve cero filas
SELECT * FROM MyApp.Patient WHERE MiddleName IS NULL -- Forma correcta de verificar NULL
-- NULL en expresiones
SELECT Name, MiddleName || ' ' || LastName FROM MyApp.Patient
-- Si MiddleName es NULL, el resultado de la concatenación es NULL (NULL se propaga)
-- COALESCE / IFNULL para manejar NULLs
SELECT Name, COALESCE(MiddleName, 'N/A') AS MiddleName FROM MyApp.Patient
-- Devuelve 'N/A' si MiddleName es NULL
-- NULL en agregados
SELECT COUNT(MiddleName) FROM MyApp.Patient
-- COUNT(column) excluye valores NULL
-- COUNT(*) cuenta todas las filas incluyendo aquellas con NULLs
Resumen comparativo
| Concepto | Valor en ObjectScript | $LENGTH() | Proyección SQL | Prueba SQL |
|---|---|---|---|---|
| Cadena vacía | "" | 0 | '' (cadena vacía) | = '' o = "" |
| SQL NULL | $C(0) | 1 | NULL | IS NULL |
| Espacio | " " | 1 | ' ' (espacio) | = ' ' |
| Propiedad no establecida | "" (por defecto) | 0 | '' (cadena vacía) | = '' |
Insertar NULL vía SQL
-- Inserción explícita de NULL
INSERT INTO MyApp.Patient (Name, MiddleName) VALUES ('Smith', NULL)
-- MiddleName será $C(0) cuando se acceda vía ObjectScript
-- Omitir una columna también inserta el valor por defecto (cadena vacía, NO NULL)
INSERT INTO MyApp.Patient (Name) VALUES ('Jones')
-- MiddleName será '' (cadena vacía), NO NULL
Error común: diferencias en cláusula WHERE
// Esta consulta encuentra filas con MiddleName como cadena vacía:
&sql(SELECT COUNT(*) INTO :cnt FROM MyApp.Patient WHERE MiddleName = '')
WRITE "Empty strings: ", cnt, !
// Esta consulta encuentra filas con MiddleName como NULL:
&sql(SELECT COUNT(*) INTO :cnt FROM MyApp.Patient WHERE MiddleName IS NULL)
WRITE "NULLs: ", cnt, !
// ¡Son conjuntos de resultados DIFERENTES!
// Un error común es usar = '' cuando se quería IS NULL, o viceversa
Referencias de Documentación
Resumen de Preparación para el Examen
Conceptos críticos a dominar:
- $C(0) = SQL NULL: Este es el hecho más importante; `$CHAR(0)` es cómo ObjectScript representa SQL NULL
- La cadena vacía NO es NULL: Una propiedad no establecida tiene por defecto `""`, que es cadena vacía en SQL, no NULL
- IS NULL vs = '': Estos verifican cosas completamente diferentes; `IS NULL` coincide con `$C(0)`, `= ''` coincide con cadena vacía
- Propagación de NULL: NULL en cualquier expresión aritmética o de cadena se propaga (el resultado es NULL)
- Comportamiento de COUNT: `COUNT(*)` cuenta todas las filas; `COUNT(column)` excluye NULLs
- Lógica de tres valores: Las comparaciones que involucran NULL devuelven UNKNOWN, no TRUE ni FALSE
Escenarios comunes de examen:
- Dada una asignación de propiedad en ObjectScript, predecir si SQL ve NULL o cadena vacía
- Escribir cláusulas WHERE correctas para encontrar valores NULL vs cadena vacía
- Identificar errores donde se usa `= ''` en lugar de `IS NULL` (o viceversa)
- Entender qué sucede cuando se hace INSERT sin especificar una columna (cadena vacía, no NULL)
- Predecir resultados de COUNT cuando los datos contienen una mezcla de NULLs y cadenas vacías
- Establecer una propiedad a `$C(0)` para crear un valor SQL NULL desde ObjectScript
Recomendaciones de práctica:
- Crear una clase de prueba con propiedades de cadena, guardar objetos con `""`, `$C(0)` y valores reales
- Consultar la tabla con tanto `IS NULL` como `= ''` para ver la diferencia
- Usar `SELECT $LENGTH(col), $ASCII(col) FROM ...` para inspeccionar valores almacenados
- Practicar COALESCE e IFNULL para manejar NULLs en consultas
- Experimentar con propagación de NULL en expresiones: `NULL + 5`, `NULL || 'text'`
- Probar COUNT(*) vs COUNT(column) con datos que contienen NULLs
- Escribir código ObjectScript que distinga correctamente `$C(0)` de `""` usando `$ASCII`