Estou trabalhando em um projeto com gatilhos que fazem referência a diversas tabelas.
Estrutura das tabelas:
CREATE TABLE TabelaA
(
id NUMBER NOT NULL,
naziv VARCHAR2(20),
datum DATE,
cijeliBroj NUMBER,
realniBroj NUMBER,
CONSTRAINT PK_TabelaA PRIMARY KEY(id),
CONSTRAINT realniBrojOgranicenjeA CHECK(realniBroj >5),
CONSTRAINT cijeliBrojOgranicenjeA CHECK(cijeliBroj NOT BETWEEN 5 AND 15)
);
CREATE TABLE TabelaB
(
id NUMBER,
naziv VARCHAR2(20),
datum DATE,
cijeliBroj NUMBER,
realniBroj NUMBER,
FKTabelaA NUMBER,
CONSTRAINT PK_TabelaB PRIMARY KEY(id),
CONSTRAINT FK_TabelaA
FOREIGN KEY(FKTabelaA) REFERENCES TabelaA(id),
CONSTRAINT cijeliBrojOgranicenjeB UNIQUE(cijeliBroj)
);
CREATE TABLE TabelaC
(
id NUMBER,
naziv VARCHAR2(20) NOT NULL,
datum DATE,
cijeliBroj NUMBER NOT NULL,
realniBroj NUMBER,
FKTabelaB NUMBER,
CONSTRAINT PK_TabelaC PRIMARY KEY(id),
CONSTRAINT FkCnst
FOREIGN KEY(FKTabelaB) REFERENCES TabelaB(id)
);
Crie um gatilho t1 que, após adicionar cada nova linha à tabela TableB, aumente o valor do seu número real na linha correspondente da tabela TableA em 25% se o valor inteiro da nova linha da tabela TableB for menor que 50 e, caso contrário, diminua o valor do seu número real em 25%.
Crie um gatilho t2 que, antes de adicionar ou alterar cada linha na tabela TableC, adicione uma nova linha à tabela TableB. A nova linha deve referenciar a mesma linha da tabela TableA que a linha correspondente da tabela TableB à qual a linha fornecida da tabela TableC se refere (em caso de alteração, use o novo valor). Defina a data de hoje para a nova linha, duplique o valor inteiro máximo da tabela TableB para o inteiro e defina o próximo valor da sequência counterB usada para a entrada inicial das linhas 1-5 na tabela TableB para o id. Defina os outros valores da coluna como nulos. Se você não criou a sequência counterB antes de inserir as linhas, crie-a posteriormente com as configurações apropriadas. Para alunos que usam o SQLTools, é necessário que a sequência counterB tenha um valor mínimo e comece do valor 0, e para alunos que usam o Oracle Live, é necessário que a sequência counterB comece do valor 1.
Crie uma tabela de backup vazia TableABekap. A tabela TableABekap é idêntica à tabela TableA, exceto que ela tem colunas adicionais integerB (do tipo INTEGER) e sequence (do tipo INTEGER).
Crie um gatilho t3 que preencha a tabela de backup TableABekap. Após adicionar qualquer nova linha à tabela TableB, a linha referenciada da tabela TableA é salva na tabela de backup. Neste processo, a coluna integerB é preenchida com o inteiro da linha inserida da tabela TableB. Caso uma linha com a mesma chave primária já tenha sido inserida na tabela TableABekap, é necessário apenas incrementar a coluna integerB pelo valor da coluna integerB da linha inserida da tabela TableB. Na coluna sequence é necessário inserir o próximo valor da sequência seq que foi criada antes do gatilho propriamente dito. Esta sequência assume valores entre 1 e 10 em ordem circular. Para todos os alunos é necessário que a sequência seq tenha valor mínimo e comece a partir do valor 1 (nenhum valor 0 deve ser usado para esta sequência).
CREATE TRIGGER t1
AFTER INSERT
ON TabelaB
FOR EACH ROW
BEGIN
IF(:NEW.cijeliBroj < 50)
THEN
UPDATE TabelaA
SET realniBroj = realniBroj * 1.25
WHERE id = :NEW.FKTabelaA;
ELSE
UPDATE TabelaA
SET realniBroj = realniBroj * 0.75
WHERE id = :NEW.FKTabelaA;
END IF;
END;
/
CREATE SEQUENCE brojacB
MINVALUE 0
START WITH 1
INCREMENT BY 1
CACHE 20;
CREATE TRIGGER t2
BEFORE INSERT OR UPDATE OR DELETE
ON TabelaC
FOR EACH ROW
DECLARE maxCijeliBroj NUMBER;
BEGIN
SELECT MAX(cijeliBroj)
INTO maxCijeliBroj
FROM TabelaB;
maxCijeliBroj := maxCijeliBroj * 2;
INSERT INTO TabelaB
VALUES (brojacB.NEXTVAL, NULL, SYSDATE, maxCijeliBroj, NULL, :NEW.FKTabelaB);
END;
/
CREATE TABLE TabelaABekap
AS
SELECT * FROM TabelaA;
ALTER TABLE TabelaABekap
ADD (cijeliBrojB NUMBER, sekvenca NUMBER);
CREATE SEQUENCE seq
MINVALUE 1
MAXVALUE 10
START WITH 1
INCREMENT BY 1
CYCLE
CACHE 9;
CREATE TRIGGER t3
AFTER INSERT
ON TabelaB
FOR EACH ROW
BEGIN
INSERT INTO TabelaABekap (id, naziv, datum, cijeliBroj, realniBroj)
SELECT id, naziv, datum, cijeliBroj, realniBroj
FROM TabelaA
WHERE id = :NEW.FKTabelaA;
DECLARE brojac INTEGER;
BEGIN
SELECT COUNT(*)
INTO brojac
FROM TabelaABekap
WHERE id = :NEW.FKTabelaA;
IF brojac > 0
THEN
UPDATE TabelaABekap
SET cijeliBrojB = cijeliBrojB + :NEW.cijeliBroj
WHERE id = :NEW.FKTabelaA;
ELSE
INSERT INTO TabelaABekap(id, naziv, datum, cijeliBroj, realniBroj, cijeliBrojB)
SELECT id, naziv, datum, cijeliBroj, realniBroj, :NEW.CijeliBroj
FROM TabelaA
WHERE id = :NEW.FKTabelaA;
END IF;
END;
UPDATE TabelaABekap
SET sekvenca = seq.NEXTVAL;
END;
/
CASOS DE TESTE: depois de chamar esses comandos de inserção:
INSERT INTO TabelaB (id, naziv, datum, cijeliBroj, realniBroj, FkTabelaA) VALUES (brojacB.nextval, null,null, 2, null, 1);
INSERT INTO TabelaB (id, naziv, datum, cijeliBroj, realniBroj, FkTabelaA) VALUES (brojacB.nextval, null,null, 4, null, 2);
INSERT INTO TabelaB (id, naziv, datum, cijeliBroj, realniBroj, FkTabelaA) VALUES (brojacB.nextval, null, null, 8, null, 1);
INSERT INTO TabelaC (id, naziv, datum, cijeliBroj, realniBroj, FkTabelaB) VALUES (4, 'NO', null, 5, null, 3);
INSERT INTO TabelaC (id, naziv, datum, cijeliBroj, realniBroj, FkTabelaB) VALUES (5, 'YES', null, 7, null,3);
INSERT INTO TabelaC (id, naziv, datum, cijeliBroj, realniBroj, FkTabelaB) VALUES (6, 'NO', null, 9, null, 2);
UPDATE TabelaC SET cijeliBroj = 10 WHERE id = 2;
DELETE FROM TabelaB WHERE id NOT IN (SELECT FkTabelaB FROM TabelaC);
DELETE FROM TabelaA WHERE id IN (3, 4, 6);
Após essas inserções, os resultados dos testes devem ser:
SELECT SUM(id*3 + cijeliBrojB*3) FROM TabelaABekap;--Result: 2031
SELECT SUM(id*3 + cijeliBroj*3) FROM TabelaC;--Result: 420
SELECT SUM(MOD(id,10)*3) FROM TabelaB;--Result: 30
SELECT SUM(id + realniBroj)*10 FROM TabelaA;--Result: 264
Não consigo executar comandos insert. Recebo esse erro e erros semelhantes que estão relacionados a referências a várias tabelas, relação pai-filho e restrições.
1 1 ORA-02291: restrição de integridade (USER.FK_TABELAA) violada - chave pai não encontrada
Banco de dados utilizado: Oracle
Existe alguma maneira de consertar isso? Eu ficaria muito grato se você pudesse ajudar com isso.