Basicamente, a próxima etapa para o erro "Falha na restrição UNIQUE" com chave primária composta : criei um gatilho após a inserção para definir SEQ
o maior SEQ
mais um se for menor que um. Basicamente:
CREATE TRIGGER TRG_NAMES_ADD2 AFTER INSERT ON NAMES FOR EACH ROW
WHEN NEW.SEQ < 1
BEGIN
UPDATE NAMES SET
SEQ = (SELECT IFNULL(MAX(SEQ), 0) + 1 FROM NAMES WHERE TYPE = NEW.TYPE)
WHERE TYPE = NEW.TYPE AND SEQ = NEW.SEQ;
END;
No entanto, eu gostaria de fazer a mesma coisa TYPE
independentemente de SEQ
. Os problemas que encontrei foram que só posso ter um UPDATE
por gatilho e os AFTER INSERT
gatilhos podem ser executados em qualquer ordem.
Eu tentei um segundo gatilho como este:
CREATE TRIGGER TRG_NAMES_ADD1 AFTER INSERT ON NAMES FOR EACH ROW
WHEN NEW.TYPE < 1
BEGIN
UPDATE NAMES SET
TYPE = (SELECT IFNULL(MAX(TYPE), 0) + 1 FROM NAMES),
SEQ = 1
WHERE TYPE = NEW.TYPE AND SEQ = NEW.SEQ;
END;
No entanto, para completar, TRG_NAMES_ADD2
devo executar depois TRG_NAMES_ADD1
, ou eu teria que colocar ambas as ações (definir TYPE
para um valor possivelmente novo (se <1) e, em seguida, usar esse novo valor para possivelmente definir um novo valor para SEQ
(se <1) também) em um gatilho.
Infelizmente isso está além das minhas capacidades.
Por conveniência, aqui está a criação da tabela e alguns exemplos de inserções:
CREATE TABLE NAMES (
TYPE INTEGER NOT NULL, SEQ INTEGER NOT NULL, NAME VARCHAR(20),
PRIMARY KEY (TYPE, SEQ)
);
insert into NAMES (type, seq, name) values (2, 3, "T1");
insert into NAMES (type, seq, name) values (2, 0, "T2");
insert into NAMES (type, seq, name) values (2, 0, "T3");
insert into NAMES (type, seq, name) values (0, 1, "T4");
insert into NAMES (type, seq, name) values (0, 0, "T5");
Então as atribuições deveriam ser assim:
T|S|N
-----
2|3|T1 # T,S set manually
2|4|T2 # S set automatically
2|5|T3 # S set automatically
3|1|T4 # T set automatically
4|1|T5 # T,S set automatically
Você tem certeza de que pode ter apenas uma atualização por gatilho? Não encontrei nenhuma referência a esse limite nos documentos do sqlite.
De qualquer forma, você pode simplesmente combinar as duas atualizações em uma única: