Sınırlamayı kontrol et, üç sütundan yalnızca biri boş değil


61

3 tür sonuç içeren bir (SQL Server) tablom var: FLOAT, NVARCHAR (30) veya DATETIME (3 ayrı sütun). Herhangi bir satır için yalnızca bir sütunun bir sonucu olduğundan ve diğer sütunların NULL olduğundan emin olmak istiyorum. Bunu başarmanın en basit kontrol kısıtı nedir?

Bunun bağlamı, sayısal olmayan sonuçları var olan bir sisteme alma yeteneğini güçlendirmeye çalışıyor. Tabloya satır başına birden fazla sonuç çıkmasını önlemek için bir kısıtlama içeren iki yeni sütun eklemek, en doğru olanı değil, en ekonomik olanıydı.

Güncelleme: Üzgünüz, snafu veri tipi. Ne yazık ki, şu anda düzeltilen genel terimler olan SQL Server veri türleri olarak yorumlanacak belirtilen sonuç türlerini hedeflemiyordum.

Yanıtlar:


72

Aşağıdaki hile yapmalı:

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

24

Muhtemelen kısıtlama dahilinde üç test yapmanız gerekecektir, her bir çift için boş olmasını istediğiniz bir test ve bir tane boş olmamalıdır.

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)
);

Bu o kadar ölçeklenebilir değil, 9 yabancı anahtar içeren bir masam var ve sadece bir tanesi boş olmamalı, @MarkStoreySmith'in çözümünü tercih ediyorum
Amir Pashazadeh

5

Yerleşik dizi işlevlerini kullanan bir PostgreSQL çözümü :

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);

Bu postgreSQL'de sırasıyla Mark Storey ve mrdenny tarafından yayınlanan CASE veya AND / OR çözümlerine göre daha hızlı uygulanacak mı?
Chris Britt
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.