Я никогда не писал "вручную" код создания объекта для SQL Server, и отклонение внешнего ключа, по-видимому, отличается между SQL Server и Postgres. Вот мой sql:
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
);
Когда я запускаю запрос, я получаю эту ошибку:
Msg 8139, Level 16, State 0, Line 9 Number of referencing columns in foreign key differs from number of referenced columns, table 'question_bank'.
Вы можете заметить ошибку?


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)
);
Также может быть полезно назвать ограничение внешнего ключа. Это помогает при поиске и устранении нарушений fk. Например: «внешний ключ fk_questionbank_exams (question_exam_id) ссылается на экзамены (exc_id)»
Я согласен с тем, что ограничения именования - это хороший план, но, по крайней мере, в SQL Server 2008 R2 синтаксис последней строки должен быть "ограничение внешнего ключа fk_questionbank_exams (question_exam_id) ссылок на экзамены (exc_id)"
Важно отметить, что при создании внешнего ключа нет создает индекс. Присоединение другой таблицы к этой может привести к очень медленному запросу.
Не знаю, почему это по-другому, но мне пришлось сдать экзамены CONSTRAINT fk_questionbank_exams FOREIGN KEY (question_exam_id) REFERENCES (exc_id)
Необходимо ли писать NON NULL для первичного ключа, или это явно, когда мы пишем ограничение первичного ключа для столбца, например, я сижу достаточно, чтобы обозначить столбец в качестве первичного ключа, чтобы иметь ненулевое ограничение, или должен указать NON NULL, т.е. записать явно?
Вы также можете назвать свое ограничение внешнего ключа, используя:
CONSTRAINT your_name_here FOREIGN KEY (question_exam_id) REFERENCES EXAMS (exam_id)
При использовании ORM полезно иметь именованные ограничения с несколькими ссылками на внешнюю таблицу ... Использовать именованные ограничения в свойствах с EF4, чтобы я знал, какая запись в таблице контактов предназначена для покупателя, продавца и т. д.
И если вы просто хотите создать ограничение самостоятельно, вы можете использовать ALTER TABLE
alter table MyTable
add constraint MyTable_MyColumn_FK FOREIGN KEY ( MyColumn ) references MyOtherTable(PKColumn)
Я бы не рекомендовал синтаксис, упомянутый Сарой Чиппс, для встроенного создания, просто потому, что я бы предпочел назвать свои собственные ограничения.
Я знаю, что это очень старый ... но я попал сюда через поиск в Google, и многие другие смогли. Просто быстрое исправление: правильный способ ссылки: ССЫЛКИ MyOtherTable (MyOtherIDColumn)
Как и вы, я обычно не создаю внешние ключи вручную, но если по какой-то причине мне нужен сценарий для этого, я обычно создаю его с помощью ms sql server management studio и перед сохранением изменений выбираю Table Designer | Создать сценарий изменения
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
);
- Это тоже сработает. Может быть, более интуитивно понятная конструкция?
Это то, что я делаю, но у меня вопрос: есть ли смысл добавлять ключевые слова "внешнего ключа"? - кажется, работает и без этого, например: question_exam_id uniqueidentifier not null Ссылки на экзамены (exc_id)
Ключевые слова «Внешний ключ» необязательны. На мой взгляд, это делает код более читабельным.
Мне нравится ответ AlexCuse, но то, на что вы должны обращать внимание всякий раз, когда вы добавляете ограничение внешнего ключа, - это то, как вы хотите, чтобы обновления указанного столбца в строке указанной таблицы обрабатывались, и особенно то, как вы хотите удалять строки в указанном стол для лечения.
Если ограничение создается следующим образом:
alter table MyTable
add constraint MyTable_MyColumn_FK FOREIGN KEY ( MyColumn )
references MyOtherTable(PKColumn)
.. затем обновления или удаления в ссылочной таблице будут выдаваться с ошибкой, если в ссылочной таблице есть соответствующая строка.
Это может быть то поведение, которое вы хотите, но, по моему опыту, чаще всего это не так.
Если вы вместо этого создадите его так:
alter table MyTable
add constraint MyTable_MyColumn_FK FOREIGN KEY ( MyColumn )
references MyOtherTable(PKColumn)
on update cascade
on delete cascade
..тогда обновления и удаления в родительской таблице приведут к обновлению и удалению соответствующих строк в ссылающейся таблице.
(Я не предлагаю менять значение по умолчанию, ошибки по умолчанию из соображений осторожности, и это хорошо. Я просто говорю, что это то, что человек, создающий constaints всегда следует обращать внимание на.)
Это, кстати, можно сделать при создании таблицы, например:
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
)
Лучше работает с «изменить таблицу MyTable (...)». :)
Некромантинг.
На самом деле сделать это правильно немного сложнее.
Сначала вам нужно проверить, существует ли первичный ключ для столбца, на который вы хотите указать внешний ключ.
В этом примере создается внешний ключ в таблице T_ZO_SYS_Language_Forms, ссылающийся на 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
Чтобы создать внешний ключ для любой таблицы
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)
Этот сценарий предназначен для создания таблиц с внешним ключом, и я добавил ограничение ссылочной целостности sql-сервер.
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
);
Если вы хотите создать связь между двумя столбцами таблицы с помощью запроса, попробуйте следующее:
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)
Я всегда использую этот синтаксис для создания ограничения внешнего ключа между двумя таблицами
Alter Table ForeignKeyTable
Add constraint `ForeignKeyTable_ForeignKeyColumn_FK`
`Foreign key (ForeignKeyColumn)` references `PrimaryKeyTable (PrimaryKeyColumn)`
т.е.
Alter Table tblEmployee
Add constraint tblEmployee_DepartmentID_FK
foreign key (DepartmentID) references tblDepartment (ID)
К вашему сведению, всегда лучше называть ваши ограничения, особенно с использованием ORM.