Ограничение Sybase с внешним ключом и условная проверка по значению столбца внешней таблицы - PullRequest
1 голос
/ 07 марта 2012

Возможно ли в Sybase определить ограничение (я), которые требуют, чтобы столбец являлся внешним ключом, а также удовлетворяли условию на основе значения внешнего столбца, например, в приведенных ниже таблицах примеров может быть создано ограничение длятаблица «product» такая, что «product.code» является внешним ключом brand.code с действительным значением = 1 "?

CREATE TABLE brand (
    code        char(8)       NOT NULL,
    valid       int           NOT NULL,
    rowid       numeric(10,0) IDENTITY,
    CONSTRAINT brand_pk PRIMARY KEY (code),
    CONSTRAINT valid_check CHECK (valid IN (0,1))
)

CREATE TABLE product (
    code        char(8)       NOT NULL,
    CONSTRAINT product_pk PRIMARY KEY (code)
)

Ответы [ 2 ]

3 голосов
/ 07 марта 2012

Я думаю, что лучше всего немного изменить структуру.

CREATE TABLE brand (
    code        char(8)       NOT NULL,
    valid       int           NOT NULL,
    rowid       numeric(10,0) IDENTITY,
    CONSTRAINT brand_pk PRIMARY KEY (code),

    -- The following UNIQUE constraint lets the pair of values be the target of 
    -- a foreign key reference.
    CONSTRAINT brand_is_valid UNIQUE (code, valid),

    CONSTRAINT valid_check CHECK (valid IN (0,1))
);

CREATE TABLE product (
    code        char(8)       NOT NULL,
    valid       int           NOT NULL,

    -- The column "code" is a PK in the referenced table, so this still works. It's 
    -- a 1:0 or 1:1 relationship.
    CONSTRAINT product_pk PRIMARY KEY (code),

    -- The next constraint requires a unique constraint on the pair of 
    -- columns in the table "brand".  By itself, it references every row
    -- in "brand". That's too many rows.
    CONSTRAINT product_fk FOREIGN KEY (code, valid) 
                          REFERENCES brand (code, valid),

    -- But this constraint restricts the foreign key references to only those 
    -- rows that have valid = 1 in the table "brand".
    CHECK (valid = 1)
);
1 голос
/ 07 марта 2012

Чтобы обойти создание внешнего ключа на основе «действительного» условия, вам нужно будет изменить дизайн таблицы и создать триггер для установки product.code = NULL.Извините за синтаксис (я давно не кодировал Sybase), но это общая идея:

Добавить новый столбец, который будет служить первичным ключом, так как нам нужно будет установить product.code = NULL, когдаvalid = 0:

CREATE TABLE product (
    rowid       int identity primary key,
    code        char(8) NULL,
    CONSTRAINT brand_fk FOREIGN KEY (code) REFERENCES brand(code)
)

Затем создайте триггер, подобный этому:

create trigger FK_WhenValid 
on product 
for insert 
AS
  IF (SELECT COUNT(*) FROM brand b inner join inserted i on b.code = i.code AND b.valid=0 ) > 0 
  BEGIN
    UPDATE product SET code = NULL WHERE code in (SELECT i.code from brand b join inserted i on b.code = i.code and b.valid = 0)
  END

Примечание: этот триггер поддерживает только вставки продукта.Если «valid» может измениться, требуется другой подход.

Вы также можете реализовать внешний ключ в качестве триггера вместо декларативного ограничения и устанавливать product.code = insert.code только тогда, когда valid = 1

...