2009-06-06 20 views
10

SQL'de, bir sütun grubunun yalnızca bir sütununun bir değeri olduğunu ve diğerlerinin boş olduğunu zorunlu kılmanın bir yolu var mı? Belki bir kısıtlama mı yoksa tetikleyici mi? Bu tip bir şey bir arama tablosu için olabilir, ancak bunu daha iyi başarabilecek alternatif masa tasarımları var mı? ÖrneğinSQL: bir sütun sütununda yalnızca tek bir sütunun ayarlanması zorunluluğudur

:

ID OtherTable1ID OtherTable2ID OtherTable3ID 
----------------------------------------------------- 
1  23    NULL    NULL 
2  NULL    45    NULL 
3  33    55    NULL -- NOT ALLOWED 

ana konu bu sütunlar diğer tablolara tüm FKs olmasıdır, bu yüzden tek bir sütun için onları daraltmak mümkün değil.

SQL Server kullanıyorum, ancak herhangi bir cevap yapacak. Aşağıdaki çalışmalıdır gibi

+0

Güncelleştirme için teşekkürler, ancak veritabanı tasarımı hakkında daha ayrıntılı bilgi vermek isteyebilirsiniz. Örneğin bu, bu tablonun diğer tabloların bir ve bir alt türünün alt tipi olabileceği bir alt türleme durumudur. Ayrıca, tüm "Diğer" sütunların boş olması mümkün mü? –

+0

Bir arama tablosu gibi görünüyor. Temel olarak, bir tane daha FK eklediğinizde ona bir tane daha sütun eklemeniz gerektiği anlamına mı geliyor? –

+0

Evet, temelde benim için bir arama tablosu. Başka bir arama parametresi eklemem gerekirse, başka bir FK sütunu eklemem gerekir. Bunu başarmanın daha iyi yolları var mı? –

cevap

13

üç sütun için Tamam çalışır, ancak miktarı (yerine "quadratically büyüyen" nin) "doğrusal büyüyen" ile herhangi bir sayıda sütun daha genelleştirerek çünkü genelliği için ben

(cast(col1 is not null, int) + 
cast(col2 is not null, int) + 
cast(col3 is not null, int)) = 1 

tercih kodlama (SQL lehçeleri, boole aka biti'nin int için açıkça dökümünü gerektirmeyen, hatta SQL Server'da bunlardan biri olduğundan emin değilim).

+4

SQL Server için bu durum daha iyi çalışır ... col1 NULL OLARDU NULLADIR 1 else 0 son + case col2 IS NOT NULL sonra 1 else 0 end <2) –

+1

@Glen Little: Sunulan sözdizimi ile katılıyorum ama OP'nin durumu için karşılaştırma hala "... = 1 '. –

6

bir kısıtlama:

(column1 is null and column2 is null) 
    or (column1 is null and column3 is null) 
    or (column2 is null and column3 is null) 

Ancak bu boş olmayan bir sütun içeren zorlamak olmaz. bu başka kısıtlama eklemek yapmak için:

column1 is not null 
    or column2 is not null 
    or column3 is not null 
0

bana geliyor sen şeylerden kümesi için bir sütun kullanıyor istermiş gibi. Belki de Foo,3 veya Bar,7 veya Baz,9 olduğunu söylemek için bir çeşit etiket kullanabilirsiniz. tvanfosson önerdiği kısıtlamaları @

+0

Bu soruyu açıklığa kavuşturmalıydım, fakat karşı karşıya olduğum sorun, sütunların diğer tablolara FKS olmasıdır. Soruyu güncellememe izin verin, üzgünüm –

+0

Ah, şimdi ilginç oluyor! Bu konuda biraz düşünmeme izin verin, ama temel olarak zayıf bir RDBMS uygulamasıyla ilgili bir sorun gibi görünüyor. Ne yazık ki, bu anlamda, orada iyi bir tane olduğunu düşünmüyorum ... –

+0

(Açıklığa kavuşturmak için, bir sütunun türünü bildirme konusunda hiçbir nedeniniz olmamalıdır) ya da buna bir başvuru ya da diğerine yapılan bir gönderme, "tüm bunların üzerinde tam bir FK desteği ile, ancak şu anki DBMS'ler bunun yakınına gelmeyebilir.) –

1
CREATE TABLE Repro.Entity 
(
    entityId INTEGER IDENTITY (1, 1) NOT NULL, 
    column1 INTEGER, 
    column2 INTEGER, 
    column3 INTEGER, 
    CONSTRAINT Entity_PK PRIMARY KEY(entityId), 
    CONSTRAINT Entity_CK CHECK(
     (column1 IS NOT NULL AND column2 IS NULL AND column3 IS NULL) OR 
     (column1 IS NULL AND column2 IS NOT NULL AND column3 IS NULL) OR 
     (column1 IS NULL AND column2 IS NULL AND column3 IS NOT NULL)) 
) 
1

Benim için kötü bir tasarım kararı gibi görünüyor. Kimlik bu tablonun birincil anahtarı olduğundan, tüm yabancı anahtar ilişkileri için yasal bir değer olacaktır. Bu, değerlerin kabul edilen aralıkta olduğunu garanti etmek için ön uç/iş katmanında fazladan fazla çalışmak zorunda olduğunuz anlamına gelir.

Örneğin, tabloların ayarlanma şekli, tablo 2 için 1'in 2 yerine arama değeri olarak kullanılması gerekmesi kesinlikle yasaldır - ve veritabanı bunu yakalamaz.

Muhtemelen bu rotaya gitmeyecektim. Sadece arama adında bir şema oluşturacağım ve arama değeri başına bir arama tablosu oluşturacağım. Bu şekilde veritabanı tüm kısıtlamaları uygun şekilde uygulayacaktır.

Arama tablosunu ayarlama şekliniz, şu anda tamsayı yabancı anahtarlarla sınırlıdır. Bazı durumlarda iyi bir fikir olmayabilir - örneğin, ülke kodunu/kodlarını, onları temsil eden tamsayı değerleri yerine depolamak istersiniz.

+0

Ayrıca NULLable sütunlardan kaçınmayı tercih ediyorum ama OP'nin tasarımı (kısıtlama gereği çalıştığı gibi) sizin için bir avantaj sunuyor (doğru olarak anladığımı varsayarak), tam olarak bir NULL olmayan değeri zorlamak için bir kısıtlama yazabilirler. kendi 'dağıtılmış yabancı anahtarlarınızı (google Hugh Darwen) tetikleyiciler (veya benzerleri) kullanarak yuvarlamadıkça, referans tablolarında sıfır satırın olabileceği duruma sahip olabilirsiniz. – onedaywhen

İlgili konular