Мне нужна помощь с ограничениями в SQL Server. Ситуация для каждого OrderID = 1 (внешний ключ не первичный ключ, так что в таблице несколько строк с одинаковым идентификатором), поле бит может быть только 1 для одной из этих строк, а для каждой строки с OrderID = 2, поле бит может быть только 1 для одной строки и т. д. Это должно быть 0 для всех других строк с одинаковым идентификатором OrderID. Любые новые записи, поступающие с 1 в поле бит, должны отклонить, если уже есть строка с этим идентификатором OrderID, у которой бит бит установлен на 1. Любые идеи?Ограничение SQL Server (поле ограничения бит на основе внешнего ключа)
ответ
Вы можете более полно нормализовать схему, которая поможет вам не искать для уже установленного бита, а использовать соединение. Вам нужно удалить поле бит и вставить новую таблицу, где X содержит OrderID и первичный ключ вашей таблицы, причем основным ключом X является все эти поля.
Это означает, что при вставке вам нужно вставить его в исходную таблицу и в X f и только если бы вы установили бит в 1 на свой стол. Вставка завершится неудачно, если в X уже есть строка, которая, как если бы была уже исходная строка с битом, установленным в 1.
Недостатком является то, что это занимает больше места, чем схема, но проще в обслуживании. вы не можете получить эквивалент двух строк с битом, установленным в 1.
Я буду иметь это в виду, если мне нужно изменить структуру таблицы. Благодаря! – user2263882
Единственный способ сделать это - подкласс родительской таблицы. Вы не упомянули об этом, но общей причиной этого шаблона является представление одной уникальной активной строки из набора всех строк с тем же общим значением ключа. Давайте предположим, что ваш битовое поле представляет активные Приказы .... Тогда я хотел бы создать отдельную таблицу под названием ActiveOrders, который будет содержать только одну строку с битовым полем, создаваемым 1
Create Table ActiveOrders(int Orderid Primary Key Null)
и другая таблица с всех строк в нем, с его собственной уникальной Primary Key OrderId
Create Table AllOrders
(OrderId Integer Primary Key Not Null, ActiveOrderId Integer Not Null,
[All other data fields]
Constraint FK_AllOrders2ActiveOrder
Foreign Key(ActiveOrderId) references ActiveOrders(OrderId))
Теперь вам больше не нужно битовое поле, так как наличие строки в таблице ActiveOrders идентифицирует ее как активный порядок ... Чтобы получить только активные Заказы (те, которые на вашей схеме будут иметь заданное битовое поле к 1), просто присоединитесь к двум таблицам.
Спасибо, это хорошее предложение. Я не решаюсь изменить структуру таблицы в данный момент, но я буду помнить об этом. – user2263882
Я общаюсь с другими ответами, и если вы можете изменить схему, тогда сделайте это, но если нет, я думаю, что что-то подобное сделает.
CREATE FUNCTION fnMyCheck
(@id INT)
RETURNS INT
AS
BEGIN
DECLARE @i INT
SELECT @i = COUNT(*)
FROM MyTable
WHERE FkCol = @id
AND BitCol = 1
RETURN @i
END
ALTER TABLE YourTable
ADD CONSTRAINT ckMyCheck CHECK (fnMyCheck(FkCol)<=1)
но есть проблемы, которые могут исходить от этого с помощью UDF в проверочном ограничении, такие как this
Edit, чтобы добавить комментарий относительно проблем с этим «решением»:
Есть более простые проблемы, чем то, с чем вы связались.
INSERT INTO YourTable(FkCol,BitCol) VALUES (1,1),(1,0)
с последующим
UPDATE YourTable SET BitCol=1
преуспевает и оставляет два ряда с FkCol = 1 и BitCol = 1
Есть более простые проблемы, чем то, с чем вы связались. 'INSERT INTO YourTable (FkCol, BitCol) VALUES (1,1), (1,0)', за которым следует 'UPDATE YourTable SET BitCol = 1', и оставляет две строки с' FkCol' = 1 и 'BitCol' = 1 –
CREATE UNIQUE INDEX ON UnnamedTable (OrderID) WHERE UnnamedBitField=1
Это называется Filtered Index. Если вы на предварительно 2008 версии SQL Server, вы можете реализовать бедный-Ман эквивалент фильтрованного индекса с помощью индексированного представления:
CREATE VIEW UnnamedView
WITH SCHEMABINDING
AS
SELECT OrderID From UnnamedSchema.UnnamedTable WHERE UnnamedBitField=1
GO
CREATE UNIQUE CLUSTERED INDEX ON UnnamedView (OrderID)
Вы не можете действительно сделать это как ограничение, так как SQL Server поддерживает только ограничения столбцов и ограничения строк. Существует нет (не-fudging) способ написать ограничение, которое имеет дело со всеми значениями в таблице.
Я использую SQL Server 2000 (грустный знаю), поэтому я использовал представление Indexed, и это сработало для меня. Единственное различие заключалось в том, что мне пришлось использовать «СОЗДАТЬ УНИКАЛЬНЫЙ КЛАСТЕРНЫЙ ИНДЕКС» вместо «СОЗДАТЬ УНИКАЛЬНЫЙ ИНДЕКС». Благодаря! – user2263882
@ user2263882 - Я обновил образец (я признаю, что мне не приходилось много лет прилагать усилия и работать с памятью). –
- 1. Ошибка ограничения внешнего ключа SQL Server 2008
- 2. Ограничение SQL для внешнего ключа
- 3. Преимущества ограничения внешнего ключа SQL Server
- 4. Microsoft SQL Server ограничение внешнего ключа конфликт
- 5. Ошибка SQL Server, создающая ограничение внешнего ключа
- 6. Ограничение внешнего ключа Sql
- 7. Ошибка ограничения внешнего ключа SQL SQL
- 8. Добавить сортировку для ограничения внешнего ключа на SQL Server
- 9. Проблемы с добавлением ограничения внешнего ключа в SQL Server?
- 10. Синтаксис ограничения SQL-внешнего ключа
- 11. Не может увидеть ограничение внешнего ключа на SQL Server 2008
- 12. Проблема SQL, взаимные ограничения, «ограничение внешнего ключа не работает»
- 13. SQL противоречили ограничение внешнего ключа
- 14. Размер ограничения внешнего ключа
- 15. ограничение внешнего ключа в sql
- 16. Добавление ограничения внешнего ключа
- 17. SQL Server - ошибка внешнего ключа
- 18. SQL Server внешнего ключа ссылка
- 19. Добавление ограничения внешнего ключа
- 20. Невозможно добавить ограничение внешнего ключа на поле даты
- 21. Ограничение внешнего ключа Netezza
- 22. Ошибка ограничения внешнего ключа при создании таблицы SQL Server
- 23. Ограничение внешнего ключа
- 24. Ошибка внешнего ключа SQL Server 2008
- 25. Добавление внешнего ключа в SQL Server 2014
- 26. ограничение внешнего ключа Проблема
- 27. SQL - Невозможно добавить ограничение внешнего ключа
- 28. Ограничение внешнего ключа (сложный?)
- 29. Ошибка внешнего ограничения ключа
- 30. Сложное ограничение внешнего ключа
Если вы не отвечаете на вопросы, особенно если в версии до 2008 года вы можете написать триггер вставки/обновления, который отклонит дубликаты – Mark