sqlserver fechas example ejemplos sql sql-server tsql stored-procedures

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)



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.