it-swarm-eu.dev

Überprüfen Sie, ob nur eine von drei Spalten nicht null ist

Ich habe eine (SQL Server) -Tabelle, die drei Arten von Ergebnissen enthält: FLOAT, NVARCHAR (30) oder DATETIME (3 separate Spalten). Ich möchte sicherstellen, dass für eine bestimmte Zeile nur eine Spalte ein Ergebnis hat und die anderen Spalten NULL sind. Was ist die einfachste Prüfbedingung, um dies zu erreichen?

Der Kontext hierfür ist der Versuch, die Fähigkeit, nicht numerische Ergebnisse in einem vorhandenen System zu erfassen, nachzurüsten. Das Hinzufügen von zwei neuen Spalten zur Tabelle mit einer Einschränkung, um mehr als ein Ergebnis pro Zeile zu verhindern, war der wirtschaftlichste Ansatz, nicht unbedingt der richtige.

Update: Sorry, Datentyp snafu. Leider hatte ich nicht die Absicht, die angegebenen Ergebnistypen als SQL Server-Datentypen zu interpretieren, sondern nur allgemeine Begriffe, die jetzt behoben wurden.

65
David Clarke

Folgendes sollte den Trick tun:

CREATE TABLE MyTable (col1 FLOAT NULL, col2 NVARCHAR(30) NULL, col3 DATETIME NULL);
GO

ALTER TABLE MyTable
ADD CONSTRAINT CheckOnlyOneColumnIsNull
CHECK 
(
    ( CASE WHEN col1 IS NULL THEN 0 ELSE 1 END
    + CASE WHEN col2 IS NULL THEN 0 ELSE 1 END
    + CASE WHEN col3 IS NULL THEN 0 ELSE 1 END
    ) = 1
)
GO
78

Sie müssen wahrscheinlich drei Tests innerhalb der Einschränkung durchführen, einen Test für jedes Paar, das null sein soll, und einen für die Spalte, die nicht null sein soll:

ALTER TABLE table
ADD CONSTRAINT CK_one_is_null
CHECK (
     (col1 IS NOT NULL AND col2 IS NULL AND col3 IS NULL)
  OR (col2 IS NOT NULL AND col1 IS NULL AND col3 IS NULL) 
  OR (col3 IS NOT NULL AND col1 IS NULL AND col2 IS NULL)
);
24
mrdenny

Hier ist eine PostgreSQL-Lösung mit eingebauten Array-Funktionen :

ALTER TABLE your_table
ADD chk_only_one_is_not_null CHECK (array_length(array_remove(ARRAY[col1::text, col2::text, col3::text], NULL), 1) = 1);
5
CrEOF

FÜR POSTGRESQL

CHECK( (col_1 IS NOT NULL)::integer + (col_2 IS NOT NULL)::integer + ... = 1 )

Wir konvertieren die Spalte in boolean mit IS NOT NULL ( true oder false ), dann in :: integer ( 0 oder 1 ) Wir können dann arithmetische Operatoren verwenden

= 1  //must one row is not null  
<= 1 //only one row can be not null
1
Mendes