fechas - like sql server ejemplos
Cómo comparar valores que pueden ser ambos nulos es T-SQL (12)
Quiero asegurarme de no insertar una fila duplicada en mi tabla (por ejemplo, solo la clave principal es diferente). Todo mi campo permite NULLS ya que he decidido que null significa "todos los valores". Debido a los nulos, la siguiente declaración en mi procedimiento almacenado no puede funcionar:
IF EXISTS(SELECT * FROM MY_TABLE WHERE
MY_FIELD1 = @IN_MY_FIELD1 AND
MY_FIELD2 = @IN_MY_FIELD2 AND
MY_FIELD3 = @IN_MY_FIELD3 AND
MY_FIELD4 = @IN_MY_FIELD4 AND
MY_FIELD5 = @IN_MY_FIELD5 AND
MY_FIELD6 = @IN_MY_FIELD6)
BEGIN
goto on_duplicate
END
ya que NULL = NULL no es verdadero.
¿Cómo puedo verificar los duplicados sin tener una declaración IF IS NULL para cada columna?
¿Qué sucede si desea hacer una comparación para valores que NO SON iguales? Solo usar un "NO" delante de las comparaciones mencionadas anteriormente no funciona. Lo mejor que pude llegar es:
(Field1 <> Field2) OR (NULLIF(Field1, Field2) IS NOT NULL) OR (NULLIF(Field2, Field1) IS NOT NULL)
¿Revisaste NULLIF? http://msdn.microsoft.com/en-us/library/ms177562.aspx
Crea una clave principal en sus campos y deja que el motor aplique la exclusividad. Hacer la lógica IF EXISTS es incorrecta de todos modos ya que está defectuosa con las condiciones de carrera.
Deberá usar IS NULL o ISNULL. Realmente no hay nada de distancia.
En la misma línea que la respuesta de @ Eric , pero sin usar ''NULL''
símbolo ''NULL''
.
(Field1 = Field2) OR (ISNULL(Field1, Field2) IS NULL)
Esto será cierto solo si ambos valores son non-NULL
e iguales entre sí, o ambos valores son NULL
NULLIF (TARGET.relation_id, SOURCE.app_relation_id) IS NULL Solución simple
Necesitaba una comparación similar cuando hacía una FUSIÓN:
WHEN MATCHED AND (Target.Field1 <> Source.Field1 OR ...)
Las comprobaciones adicionales son para evitar actualizar filas donde todas las columnas ya son iguales. Para mis propósitos, quería que NULL <> anyValue
fuera True y NULL <> NULL
que fuera False.
La solución evolucionó de la siguiente manera:
Primer intento:
WHEN MATCHED AND
(
(
-- Neither is null, values are not equal
Target.Field1 IS NOT NULL
AND Source.Field1 IS NOT NULL
AND Target.Field1 <> Source.Field1
)
OR
(
-- Target is null but source is not
Target.Field1 IS NULL
AND Source.Field1 IS NOT NULL
)
OR
(
-- Source is null but target is not
Target.Field1 IS NOT NULL
AND Source.Field1 IS NULL
)
-- OR ... Repeat for other columns
)
Segundo intento:
WHEN MATCHED AND
(
-- Neither is null, values are not equal
NOT (Target.Field1 IS NULL OR Source.Field1 IS NULL)
AND Target.Field1 <> Source.Field1
-- Source xor target is null
OR (Target.Field1 IS NULL OR Source.Field1 IS NULL)
AND NOT (Target.Field1 IS NULL AND Source.Field1 IS NULL)
-- OR ... Repeat for other columns
)
Tercer intento (inspirado en @ THEn''s answer ):
WHEN MATCHED AND
(
ISNULL(
NULLIF(Target.Field1, Source.Field1),
NULLIF(Source.Field1, Target.Field1)
) IS NOT NULL
-- OR ... Repeat for other columns
)
La misma lógica ISNULL / NULLIF se puede usar para probar la igualdad y la desigualdad:
- Igualdad:
ISNULL(NULLIF(A, B), NULLIF(B, A)) IS NULL
- Inequaltiy:
ISNULL(NULLIF(A, B), NULLIF(B, A)) IS NOT NULL
Aquí hay un SQL-Fiddle que demuestra cómo funciona http://sqlfiddle.com/#!3/471d60/1
Podrías unir cada valor, pero es un poco molesto:
IF EXISTS(SELECT * FROM MY_TABLE WHERE
coalesce(MY_FIELD1,''MF1'') = coalesce(@IN_MY_FIELD1,''MF1'') AND
...
BEGIN
goto on_duplicate
END
También deberá asegurarse de que el valor coalesced
no sea un valor válido en la columna en cuestión. Por ejemplo, si era posible que el valor de MY_FIELD1 pudiera ser ''MF1'', esto causaría muchos errores espurios.
Puede usar SET ANSI_NULLS
para especificar el comportamiento de los operadores de comparación Equals (=) y Not Equal To (<>) cuando se usan con valores nulos.
Use ISNULL
:
ISNULL(MY_FIELD1, ''NULL'') = ISNULL(@IN_MY_FIELD1, ''NULL'')
Puede cambiar ''NULL''
a algo así como ''All Values''
si tiene más sentido hacerlo.
Cabe señalar que con dos argumentos, ISNULL
funciona igual que COALESCE
, que puede usar si tiene algunos valores para probar (es decir, COALESCE(@IN_MY_FIELD1, @OtherVal, ''NULL'')
). COALESCE
también vuelve después de la primera no nula, lo que significa que es (marginalmente) más rápido si espera que MY_FIELD1 esté en blanco. Sin embargo, creo que ISNULL
mucho más legible, así que es por eso que lo utilicé aquí.
Use el operador INTERSECT
.
Es NULL
sensible y eficiente si tiene un índice compuesto en todos sus campos:
IF EXISTS
(
SELECT MY_FIELD1, MY_FIELD2, MY_FIELD3, MY_FIELD4, MY_FIELD5, MY_FIELD6
FROM MY_TABLE
INTERSECT
SELECT @IN_MY_FIELD1, @IN_MY_FIELD2, @IN_MY_FIELD3, @IN_MY_FIELD4, @IN_MY_FIELD5, @IN_MY_FIELD6
)
BEGIN
goto on_duplicate
END
Tenga en cuenta que si crea un índice UNIQUE
en sus campos, su vida será mucho más simple.
IF EXISTS(SELECT * FROM MY_TABLE WHERE
(MY_FIELD1 = @IN_MY_FIELD1
or (MY_FIELD1 IS NULL and @IN_MY_FIELD1 is NULL)) AND
(MY_FIELD2 = @IN_MY_FIELD2
or (MY_FIELD2 IS NULL and @IN_MY_FIELD2 is NULL)) AND
(MY_FIELD3 = @IN_MY_FIELD3
or (MY_FIELD3 IS NULL and @IN_MY_FIELD3 is NULL)) AND
(MY_FIELD4 = @IN_MY_FIELD4
or (MY_FIELD4 IS NULL and @IN_MY_FIELD4 is NULL)) AND
(MY_FIELD5 = @IN_MY_FIELD5
or (MY_FIELD5 IS NULL and @IN_MY_FIELD5 is NULL)) AND
(MY_FIELD6 = @IN_MY_FIELD6
or (MY_FIELD6 IS NULL and @IN_MY_FIELD6 is NULL)))
BEGIN
goto on_duplicate
END
Wordy En comparación con la solución IFNULL / COALESCE. Pero funcionará sin tener que pensar en qué valor no aparecerá en los datos que pueden usarse como soporte para NULL.