У меня возникла странная проблема в SSMS.Alter Table Добавить Constraint vs Alter Table Add Check Constraint
Мой настольный дизайн сильно использует составные клавиши для обеспечения строгой и надежной ссылочной целостности во всех транзитивных отношениях - ценой нарушения BCNF, но на практике это оказывается весьма удобным, особенно с автоматическими навигационными свойствами Entity Framework на этот вопрос я опубликовал ранее: How can I enforce second-degree relationships without composite keys?).
В любом случае, у меня возникают проблемы с добавлением отношений внешнего ключа с использованием редактора диаграмм SSMS 2014.
Вот упрощенный пример моей проблемы:
CREATE TABLE Tenants (
TenantId bigint IDENTITY(1,1) PRIMARY KEY
)
CREATE TABLE Shops (
TenantId bigint, -- Is a FOREIGN KEY(Tenants REFERENCES TenantId)
ShopId bigint IDENTITY(1,1)
PRIMARY KEY(TenantId, ShopId)
)
CREATE TABLE Job (
TenantId bigint, -- Is a FOREIGN KEY(Tenants REFERENCES TenantId)
ShopId bigint, -- Is a FOREIGN KEY(Shops REFERENCES TenantId)
JobId bigint IDENTITY(1,1)
PRIMARY KEY(TenantId, ShopId, JobId)
)
У меня есть много таблиц со столбцами, как эти, и используя Diagram Editor, чтобы создать отношения с ссылочной целостностью для составных ключей работает отлично (просто Ctrl + клик каждый композитный столбец FK, а затем перетащить на первичную таблицу ключей, и нажмите кнопку OK, и это все.
Однако с несколькими раз, он терпит неудачу. Например, если выбрать TenantId
и ShopId
в Jobs
и перетащить их на к таблице Shops
, это дает мне это e rror:
The columns in table 'Shops' do not match an existing primary key or UNIQUE constraint.
... даже если эти две колонки являются первичный ключ в таблице Shops
!
Я получил SSMS для создания SQL для ограничения он пытается добавить, и он дал мне это (форматирование мой, дополнительный TRANSACTION
код удален):
ALTER TABLE
dbo.Jobs
ADD CONSTRAINT
FK_Jobs_Shops
FOREIGN KEY
(ShopId, TenantId) REFERENCES dbo.Shops (ShopId, TenantId)
ON UPDATE
NO ACTION
ON DELETE
NO ACTION
Когда я побежал прямо, SQL Server дал мне эту ошибку:
Msg 1776, Level 16, State 0, Line 1 There are no primary or candidate keys in the referenced table '
dbo.Shops
' that match the referencing column list in the foreign key 'FK_Jobs_Shops
'.Msg 1750, Level 16, State 0, Line 1 Could not create constraint or index. See previous errors.
Обратите внимание, что другие таблицы уже имели определенный внешнего ключа отношения к Shops
таблице - так что я задавался вопросом, что происходит. Так что я сказал SSMS в скрипт для создания, казалось бы, рабочими ограничений - то я переименовал вещи, чтобы сделать это создать ограничение я хотел первоначально (между Jobs
и Shops
), и он дал мне эту разные выхода (форматирование мой):
ALTER TABLE
[dbo].Jobs WITH CHECK
ADD CONSTRAINT
[FK_Jobs_Shops]
FOREIGN KEY
([TenantId], [ShopId]) REFERENCES [dbo].[Shops] ([TenantId], [ShopId])
GO
ALTER TABLE
[dbo].[Jobs]
CHECK CONSTRAINT
[FK_Jobs_Shops]
GO
Когда я побежал, это сработало!
Обратите внимание на различия:
- Добавление
WITH CHECK
- Отсутствие
ON UPDATE
/ON DELETE
заявления - Ограничение было осуществлено в двух операторов, а не один.
Мои вопросы:
- ли я обнаружил ошибку в SQL Server?
- Есть ли семантическая разница между двумя синтаксисами определения ограничений?
- Вернее, почему один работает, но не другой?
Вы могли видеть http://stackoverflow.com/questions/529941/with-check-add-constraint-followed-by-check-constraint-vs-add-constraint, возможно, полезно – Kiquenet