Как ограничить количество записей, разрешенных в таблице SQL? - PullRequest
1 голос
/ 25 ноября 2011

Скажем, у меня есть две таблицы, Родитель и Ребенок.У Parent есть поле MaxChildren (int), а у Child - поле Enabled (bit) и поле ParentID (int), ссылающиеся на родительскую запись.

Я хотел бы иметь такое ограничение, чтобыне должно быть больше записей MaxChildren для каждого родителя, где Enabled = 1. Это будет означать, что любая попытка вставить или обновить любую запись в дочерней таблице потерпит неудачу, если она превысит применимое значение MaxChildren, или любая попытка понизить MaxChildren ниже уровнятекущее количество применимых дочерних записей завершится ошибкой.

Я использую MS SQL Server, но я надеюсь, что есть стандартный способ SQL.

1 Ответ

4 голосов
/ 25 ноября 2011

Это стандартный синтаксис начального уровня SQL-92, т. Е. Используется синтаксис 'vanilla', такой как внешние ключи и ограничения на уровне строк CHECK, которые широко применяются в продуктах SQL (хотя, в частности, не в MySQL):

CREATE TABLE Parent
(
 ParentID INTEGER NOT NULL, 
 MaxChildren INTEGER NOT NULL
    CHECK (MaxChildren > 0), 
 UNIQUE (ParentID),
 UNIQUE (ParentID, MaxChildren)
);

CREATE TABLE Child
(
 ParentID INTEGER NOT NULL, 
 MaxChildren INTEGER NOT NULL, 
 FOREIGN KEY (ParentID, MaxChildren)
    REFERENCES Parent (ParentID, MaxChildren)
    ON DELETE CASCADE
    ON UPDATE CASCADE, 
 OccurrenceNumber INTEGER NOT NULL, 
 CHECK (OccurrenceNumber BETWEEN 1 AND MaxChildren), 
 UNIQUE (ParentID, OccurrenceNumber)
);

Я предлагаю вам избегать использования столбцов битовых флагов. Скорее, у вас может быть вторая таблица без ограничения на MaxChildren, а затем подразумевается столбец Enabled, основанный на том, в какой таблице отображается строка. Возможно, вы захотите три таблицы для моделирования этого: таблица супертипа для всех дочерних элементов с таблицами подтипа. для включен. Затем вы можете создать от VIEW до UNION двух подтипов с подразумеваемым столбцом Enabled, например

CREATE TABLE Parents
(
 ParentID INTEGER NOT NULL, 
 MaxChildren INTEGER NOT NULL
    CHECK (MaxChildren > 0), 
 UNIQUE (ParentID),
 UNIQUE (ParentID, MaxChildren)
);

CREATE TABLE Children
(
 ChildID INTEGER NOT NULL, 
 ParentID INTEGER NOT NULL, 
 MaxChildren INTEGER NOT NULL, 
 FOREIGN KEY (ParentID, MaxChildren)
    REFERENCES Parents (ParentID, MaxChildren)
    ON DELETE CASCADE
    ON UPDATE CASCADE, 
 UNIQUE (ChildID), 
 UNIQUE (ChildID, MaxChildren),  
);

CREATE TABLE EnabledChildren
(
 ChildID INTEGER NOT NULL, 
 MaxChildren INTEGER NOT NULL, 
 FOREIGN KEY (ChildID, MaxChildren)
    REFERENCES Children (ChildID, MaxChildren)
    ON DELETE CASCADE
    ON UPDATE CASCADE, 
 OccurrenceNumber INTEGER NOT NULL, 
 CHECK (OccurrenceNumber BETWEEN 1 AND MaxChildren), 
 UNIQUE (ChildID)
);

CREATE VIEW AllChildren
AS
SELECT ChildID, 1 AS ENABLED
  FROM EnabledChildren
UNION
SELECT ChildID, 0 AS ENABLED
  FROM Children
EXCEPT
SELECT ChildID, 0 AS ENABLED
  FROM EnabledChildren;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...