3

I have next table

create table use_flags3 (
    id INTEGER,
    flag_name VARCHAR NOT NULL,        
    flag_description VARCHAR NOT NULL,
    flag_type_id INTEGER NOT NULL,
    package_id INTEGER,
    FOREIGN KEY (flag_type_id) REFERENCES use_flags_types(id),
    FOREIGN KEY (package_id) REFERENCES packages(id),
    PRIMARY KEY (id)
);

I need flag_name column to be unique only when flag_type_id equals to 1. I tried to achieve this with next constraint

CONSTRAINT idx1_chk CHECK (
    flag_type_id in (select id from use_flags_types where flag_type="local") or
    flag_type_id in (select id from use_flags_types where flag_type="expand") or
    flag_type_id in (select id from use_flags_types where flag_type="expand_hidden") or
    (
         flag_type_id in (select id from use_flags_types where flag_type="global") and
         flag_name not in (select flag_name from use_flags)
    )
)

sqlite says 'subqueries prohibited in CHECK constraints'. I can replace

flag_type_id in (select id from use_flags_types where flag_type="local")

with

flag_type_id = ${ID_HERE} -- id from `select id from use_flags_types where flag_type="local"`

but I can not do same trick for 2nd subpart of the last part of constraint

flag_name not in (select flag_name from use_flags)

Is there any chance to do what I originally want within one table (I would really don't like to split those data in 2(+) tables)?

// hope description is quite clear

Sam
  • 7,252
  • 16
  • 46
  • 65
ZuBB
  • 124
  • 2
  • 8

1 Answers1

4

If you have a complex constraint, you should use triggers:

http://sqlfiddle.com/#!7/2094c

CREATE TABLE use_flags3 (
    id INTEGER,
    flag_name VARCHAR NOT NULL,
    flag_description VARCHAR NOT NULL,
    flag_type_id INTEGER NOT NULL,
    package_id INTEGER,
    FOREIGN KEY (flag_type_id) REFERENCES use_flags_types(id),
    FOREIGN KEY (package_id) REFERENCES packages(id),
    PRIMARY KEY (id)
);

/* TRIGGER BEFORE UPDATE version omitted */

CREATE TRIGGER fake_unique
BEFORE INSERT ON use_flags3
FOR EACH ROW
WHEN (
    EXISTS (SELECT NULL
            FROM use_flags_types
            WHERE flag_type IN( "local", "expand", "expand_hidden")
              AND flag_type_id = id
           )
    OR (
         EXISTS (SELECT NULL
                 FROM use_flags_types
                 WHERE flag_type="global"
                 AND flag_type_id = id)
         AND flag_name NOT IN (SELECT flag_name FROM use_flags)
    )
)
BEGIN
  SELECT RAISE( ABORT, 'duplicate rows' );
END;
biziclop
  • 14,466
  • 3
  • 49
  • 65
  • for now I just allowed _flag_name_ field to be non unique. After all data is inserted I just run a simple check (its acceptable to go this way in my case; at least for now, while its just a prototype). Anyway, thanks for responce – ZuBB Jul 27 '12 at 06:55