Я проектирую тестовую базу данных в SQL Server 2008 R2 и / или SQL Azure. (Пока весь мой код будет работать на обоих.)
У меня есть таблица с внешним ключом, и мне нужно добавить ограничение, которое ссылается на поле во внешней таблице.
Обычно я хотел бы, чтобы сторонняя таблица управляла своими собственными проверками валидации, но бывают случаи, когда это невозможно (или нелогично). Я предоставил пример кода, который отображает то, что я пытаюсь выполнить.
CREATE TABLE CustomerOrder
(
ID INT NOT NULL IDENTITY PRIMARY KEY,
CustomerID INT NOT NULL UNIQUE
FOREIGN KEY REFERENCES Customer(ID)
ON DELETE NO ACTION ON UPDATE CASCADE,
ProductID INT NOT NULL UNIQUE
FOREIGN KEY REFERENCES Product(ID)
ON DELETE NO ACTION ON UPDATE CASCADE,
Quantity INT NOT NULL DEFAULT 1,
IsPaid BIT NOT NULL DEFAULT 0
)
GO
CREATE TABLE RMA
(
ID INT NOT NULL IDENTITY PRIMARY KEY,
CustomerOrderID INT NOT NULL UNIQUE
FOREIGN KEY REFERENCES CustomerOrder(ID)
ON DELETE NO ACTION ON UPDATE CASCADE,
-- Add constraint to prevent RMAs from being
-- created for orders that have not been paid.
-- This could be a column constraint, or a table constraint.
CHECK ( CustomerOrderID.IsPaid = 1 )
-- ERROR: 'The multi-part identifier "CustomerOrderID.IsPaid"
-- could not be bound.'
)
GO
В этом примере не имеет смысла помещать ограничение CHECK
в таблицу CustomerOrder, потому что строка в таблице CustomerOrder полностью удовлетворена тем, что ей не платят, если для заказа нет RMA. Кроме того, ограничение в таблице CustomerOrder по-прежнему должно ссылаться на таблицу RMA для подтверждения наличия RMA, поэтому остается та же проблема.
Я также пробовал:
CHECK (EXISTS(SELECT co.ID FROM CustomerOrder co
WHERE co.ID=CustomerOrderID AND
co.IsPaid=1))
-- ERROR: 'Subqueries are not allowed in this context.
-- Only scalar expressions are allowed.'
Поскольку это статическое ограничение для проверки основных данных, и на него никогда не будут ссылаться никакие другие объекты, я бы хотел избежать превращения этого в скалярную функцию или хранимую процедуру.
Однако, чтобы избежать использования скалярной функции, мне нужно будет определить ограничение в SQL (желательно одновременно с развертыванием моей базы данных и созданием таблицы).
Какой синтаксис SQL я мог бы использовать здесь для определения этого типа ограничения?