Soru SQL Server'da nasıl bir yabancı anahtar oluştururum?


SQL Server için hiçbir zaman "el-kodlu" nesne oluşturma kodu ve yabancı anahtar beyanı SQL Server ve Postgres arasında farklı görünüyor. İşte sql'im şu ana kadar:

drop table exams;
drop table question_bank;
drop table anwser_bank;

create table exams
(
    exam_id uniqueidentifier primary key,
    exam_name varchar(50),
);
create table question_bank
(
    question_id uniqueidentifier primary key,
    question_exam_id uniqueidentifier not null,
    question_text varchar(1024) not null,
    question_point_value decimal,
    constraint question_exam_id foreign key references exams(exam_id)
);
create table anwser_bank
(
    anwser_id           uniqueidentifier primary key,
    anwser_question_id  uniqueidentifier,
    anwser_text         varchar(1024),
    anwser_is_correct   bit
);

Sorguyu çalıştırdığımda şu hatayı alıyorum:

Msg 8139, Seviye 16, Durum 0, Satır 9   İçindeki referans sütunlarının sayısı   yabancı anahtar sayısından farklıdır   başvurulan sütunlar, tablo   'soru bankası'.

Hatayı fark edebilir misin?


209
2017-09-07 20:49


Menşei


FYI, kısıtlamalarınızı, özellikle de kullanımdaki ORM'leri adlandırmak için her zaman en iyisidir. - Tracker1


Cevaplar:


create table question_bank
(
    question_id uniqueidentifier primary key,
    question_exam_id uniqueidentifier not null,
    question_text varchar(1024) not null,
    question_point_value decimal,
    constraint fk_questionbank_exams foreign key (question_exam_id) references exams (exam_id)
);

174
2017-09-07 20:57



Yabancı anahtar kısıtlamasını da belirtmek faydalı olabilir. Bu fk ihlallerini gidermede yardımcı olur. Örneğin: "yabancı anahtar fk_questionbank_exams (question_exam_id) sınavlara başvurur (exam_id)" - John Vasileff
Adlandırma kısıtlamalarının iyi bir plan olduğuna katılıyorum, ancak SQL Server 2008 R2'de en azından son satırın sözdizimi "kısıtlama fk_questionbank_exams yabancı anahtar (question_exam_id) başvuru sınavları (exam_id)" olmalıdır. - Jonathan Sayce
Dikkat edilmesi gereken önemli bir nokta yabancı anahtarın değil dizin oluştur. Buna başka bir tablo eklemek, çok yavaş bir sorguya neden olabilir. - Rocklan
Neden farklı olduğuna emin değilim, ama ben CONSTRAINT fk_questionbank_exams YABANCI ANAHTARI (question_exam_id) REFERANSLAR sınavları (exam_id) yapmak zorundaydım - tenmiles
bu sözdizimi yanlış. msdn.microsoft.com/en-us/library/ms189049.aspx - Mo Hrad A


Ve sadece kısıtlamayı kendi başına oluşturmak istiyorsanız, ALTER TABLE'ı kullanabilirsiniz.

alter table MyTable
add constraint MyTable_MyColumn_FK FOREIGN KEY ( MyColumn ) references MyOtherTable(PKColumn)

Sara Chipps'in satır içi oluşturma için bahsettiği sözdizimini tavsiye etmem, çünkü kendi kısıtlarımı belirtmem.


295
2017-09-07 23:14



Bunun ölü olduğunu biliyorum ... ama buraya bir google aramadan geldim ve çok daha fazlası olabilir. Sadece hızlı bir düzeltme: referans için doğru yol: REFERANSLAR MyOtherTable (MyOtherIDColumn) - PedroC88
Çok zaman kaydettim. :) - Manprit Singh Sahota
MyTable_MyColumn_FK en iyi adlandırma uygulamasıdır. - stom


Yabancı anahtar kısıtlamasını aşağıdakileri kullanarak da adlandırabilirsiniz:

CONSTRAINT your_name_here FOREIGN KEY (question_exam_id) REFERENCES EXAMS (exam_id)

65
2017-09-07 22:12



Bir ORM kullanıldığında, yabancı tabloya birden çok referansla adlandırılmış kısıtlamalara sahip olmanız yararlı olur ... EF4 ile özelliklerde belirtilen kısıtlamalar kullanılır, böylece alıcı, satıcı vb. İçin hangi temas tablosu girdisinin olduğunu biliyordum. - Tracker1
Bu cevap Azure veritabanlarıyla çalışır. - Keith John Hutchison


AlexCuse'un cevabını seviyorum, ama yabancı bir anahtar kısıtlaması eklediğinizde dikkat etmeniz gereken bir şey, başvurulan tablonun başvurulan tablonun bir satırında, başvurulan sütunda yapılan güncellemeleri nasıl isteyeceğiniz ve özellikle başvurulan satırlardaki silmelerin nasıl olmasını istediğiniz tedavi edilecek tablo.

Böyle bir kısıtlama oluşturulduysa:

alter table MyTable
add constraint MyTable_MyColumn_FK FOREIGN KEY ( MyColumn ) 
references MyOtherTable(PKColumn)

.. sonra başvuru tablosunda yer alan güncelleştirmeler veya silmeler, başvuru tablosunda karşılık gelen bir satır varsa, bir hatayla birlikte patlar.

İstediğin davranış bu olabilir, ama benim tecrübemde, daha yaygın değil.

Bunun yerine şöyle yaparsanız:

alter table MyTable
add constraint MyTable_MyColumn_FK FOREIGN KEY ( MyColumn ) 
references MyOtherTable(PKColumn)
on update cascade 
on delete cascade

..Alt tablodaki güncellemeler ve silmeler, referans tablosunda ilgili satırların güncellemeleri ve silinmesine neden olacaktır.

(Öntanımlı değerin değiştirilmemesini öneriyorum. Dikkatli olmanın en iyisi, bu da iyi bir şey. Ben sadece bir şey yapmanın bir şey olduğunu söylüyorum. her zaman dikkat etmeli.)

Bu arada, bir tablo oluştururken, şu şekilde yapılabilir:

create table ProductCategories (
  Id           int identity primary key,
  ProductId    int references Products(Id)
               on update cascade on delete cascade
  CategoryId   int references Categories(Id) 
               on update cascade on delete cascade
)

26
2018-06-09 18:15



"MyTable (...) tablosunu değiştir" ile daha iyi çalışır. :) - Sylvain Rodrigue


create table question_bank
(
    question_id uniqueidentifier primary key,
    question_exam_id uniqueidentifier not null constraint fk_exam_id foreign key references exams(exam_id),
    question_text varchar(1024) not null,
    question_point_value decimal
);

- Bu da işe yarayacak. Belki biraz daha sezgisel yapı?


10
2018-05-26 05:14



Yaptığım şey bu, ama bir sorum var, "yabancı anahtar" anahtar kelimeleri eklemek için bir nokta var mı? - o olmadan çalışır gibi görünüyor, örn .: question_exam_id uniqueidentifier null olmayan referanslar sınavları (exam_id) - JSideris
"Yabancı anahtar" anahtar kelimeler isteğe bağlıdır. Benim açımdan, kodu daha okunabilir hale getirir. - Bijimon


Herhangi bir masada yabancı bir anahtar oluşturmak için

ALTER TABLE [SCHEMA].[TABLENAME] ADD FOREIGN KEY (COLUMNNAME) REFERENCES [TABLENAME](COLUMNNAME)
EXAMPLE
ALTER TABLE [dbo].[UserMaster] ADD FOREIGN KEY (City_Id) REFERENCES [dbo].[CityMaster](City_Id)

4
2017-09-09 16:59





Sizin gibi, genellikle yabancı anahtarları el ile oluşturmuyorum, fakat eğer bir sebepten dolayı betiğe ihtiyacım varsa, bunu genellikle ms sql sunucu yönetim stüdyosu kullanarak oluşturuyorum ve daha sonra kaydetmeden önce, Tablo Tasarımcısı'nı seçiyorum. Değişim Komut Dosyası Oluştur


2
2017-07-31 18:05





Bir ilişkiyi kullanarak bir ilişkide iki tablo sütunları oluşturmak istiyorsanız, aşağıdakileri deneyin:

Alter table Foreign_Key_Table_name add constraint 
Foreign_Key_Table_name_Columnname_FK
Foreign Key (Column_name) references 
Another_Table_name(Another_Table_Column_name)

1
2017-10-23 10:02





Necromancing.
Aslında bunu doğru yapmak biraz zor.

İlk önce, yabancı anahtarınızı başvurmak istediğiniz sütun için birincil anahtarın mevcut olup olmadığını kontrol etmeniz gerekir.

Bu örnekte, T_ZO_SYS_Language_Forms tablosundaki bir yabancı anahtar oluşturulmakta, dbo.T_SYS_Language_Forms.LANG_UID

-- First, chech if the table exists...
IF 0 < (
    SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES 
    WHERE TABLE_TYPE = 'BASE TABLE'
    AND TABLE_SCHEMA = 'dbo'
    AND TABLE_NAME = 'T_SYS_Language_Forms'
)
BEGIN
    -- Check for NULL values in the primary-key column
    IF 0 = (SELECT COUNT(*) FROM T_SYS_Language_Forms WHERE LANG_UID IS NULL)
    BEGIN
        ALTER TABLE T_SYS_Language_Forms ALTER COLUMN LANG_UID uniqueidentifier NOT NULL 

        -- No, don't drop, FK references might already exist...
        -- Drop PK if exists 
        -- ALTER TABLE T_SYS_Language_Forms DROP CONSTRAINT pk_constraint_name 
        --DECLARE @pkDropCommand nvarchar(1000) 
        --SET @pkDropCommand = N'ALTER TABLE T_SYS_Language_Forms DROP CONSTRAINT ' + QUOTENAME((SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
        --WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' 
        --AND TABLE_SCHEMA = 'dbo' 
        --AND TABLE_NAME = 'T_SYS_Language_Forms' 
        ----AND CONSTRAINT_NAME = 'PK_T_SYS_Language_Forms' 
        --))
        ---- PRINT @pkDropCommand 
        --EXECUTE(@pkDropCommand) 

        -- Instead do
        -- EXEC sp_rename 'dbo.T_SYS_Language_Forms.PK_T_SYS_Language_Forms1234565', 'PK_T_SYS_Language_Forms';


        -- Check if they keys are unique (it is very possible they might not be) 
        IF 1 >= (SELECT TOP 1 COUNT(*) AS cnt FROM T_SYS_Language_Forms GROUP BY LANG_UID ORDER BY cnt DESC)
        BEGIN

            -- If no Primary key for this table
            IF 0 =  
            (
                SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
                WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' 
                AND TABLE_SCHEMA = 'dbo' 
                AND TABLE_NAME = 'T_SYS_Language_Forms' 
                -- AND CONSTRAINT_NAME = 'PK_T_SYS_Language_Forms' 
            )
                ALTER TABLE T_SYS_Language_Forms ADD CONSTRAINT PK_T_SYS_Language_Forms PRIMARY KEY CLUSTERED (LANG_UID ASC)
            ;

            -- Adding foreign key
            IF 0 = (SELECT COUNT(*) FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_T_ZO_SYS_Language_Forms_T_SYS_Language_Forms') 
                ALTER TABLE T_ZO_SYS_Language_Forms WITH NOCHECK ADD CONSTRAINT FK_T_ZO_SYS_Language_Forms_T_SYS_Language_Forms FOREIGN KEY(ZOLANG_LANG_UID) REFERENCES T_SYS_Language_Forms(LANG_UID); 
        END -- End uniqueness check
        ELSE
            PRINT 'FSCK, this column has duplicate keys, and can thus not be changed to primary key...' 
    END -- End NULL check
    ELSE
        PRINT 'FSCK, need to figure out how to update NULL value(s)...' 
END 

0
2018-05-27 23:00





Bu komut, yabancı anahtarla tablolar oluşturmakla ilgilidir ve referans bütünlüğü kısıtlaması ekledim SQL Server.

create table exams
(  
    exam_id int primary key,
    exam_name varchar(50),
);

create table question_bank 
(
    question_id int primary key,
    question_exam_id int not null,
    question_text varchar(1024) not null,
    question_point_value decimal,
    constraint question_exam_id_fk
       foreign key references exams(exam_id)
               ON DELETE CASCADE
);

0