Добавить FK / Constraint в подраздел таблицы - PullRequest
2 голосов
/ 01 мая 2019

Настройка

Вот две упрощенные * таблицы, которые иллюстрируют мою проблему
* Фактические таблицы построены так, что я не могу по-настоящему реорганизовать столбцы или легко разделить их

Таблица: CodeValues

<code>| <b>Code<i>Set</i></b> | <b>Code<i>Value</i></b> | <b>Code<i>Text</i></b> |
|---------|-----------|----------|
| States  | 1         | Vermont  |
| States  | 2         | Hawaii   |
| YN      | 1         | Yes      |
| YN      | 2         | No       |

Где CodeSet + CodeValue - составной первичный ключ

Таблица: Address

<code>| <b>AddressID</b> | <b>Zip</b>   | <b>State</b> |
|-----------|-------|-------|
| 1         | 96701 | 2     |
| 2         | 05001 | 1     |
| 3         | 05602 | 1     |

Где AddressID - первичный ключ


Какое подходящее ограничение БД добавить к Address.State?

Оно должно всегда быть значением, которое присутствует в CodeValues Where CodeSet = 'States', но я нене верю, что я могу создать внешний ключ, который является частью составного первичного ключа

Должно ли это быть проверочное ограничение, основанное на запросе , подобном этому?

CREATE FUNCTION checkCodeValues(
    @codeSet   VARCHAR(50),
    @codeValue SMALLINT

)
RETURNS BIT
AS
BEGIN
    IF EXISTS (SELECT * FROM CodeValues WHERE CodeSet = @codeSet
                                          AND CodeValue = @codeValue)
        RETURN 1
    RETURN 0
END
ALTER TABLE Address
    WITH CHECK ADD CONSTRAINT CK_State
    CHECK (checkCodeValues('States', State))

Меня беспокоит то, что инструменты проектирования БД не будут в полной мере распознавать полное влияние этого ограничения, когда оно действительно является FK, а только против подраздела таблицы.

1 Ответ

3 голосов
/ 01 мая 2019

Один метод использует немного больше памяти, но он выполняет то, что вы хотите:

create table addresses (
    . . .,
    codeset as (convert(varchar(?), 'states')) persisted,
    foreign key (codeset, state) references codevalues (codeset, codevalue)
);

? - это длина столбца varchar() в таблице codevalues.

К счастью, для этого вам не нужны триггеры или пользовательские функции.

К несчастью, вам нужно сохранить codeset в каждом ряду, так что это займет немного места в таблице.

...