错误,触发器而非无效和重新验证失败

时间:2018-12-01 12:55:15

标签: sql oracle plsql database-trigger

我尝试创建一个触发器,而不是触发器。它的目的是插入3个表而不是我所拥有的视图,但是我遇到了一系列问题。

Create or replace trigger trigg_view
Instead of Insert ON Carti_Beletristica
for each row

Begin

dbms_output.put_line('i dont know');

End;

这是我要开始的非常基本的代码。它让我创建了它,但是当我在视图(Carti_Beletristica)中尝试插入时,出现下一个错误

ORA-04098: trigger 'RO_A372_SQL_S20.INSERT_VIEW_TRIGG' is invalid and failed re-validation

这非常令人沮丧,因为它是一个非常简单的触发器,我无法继续...之后,我将如何生成主键?因为在视图中我没有这样的东西。我的想法是从表的主键中选择最大值,然后添加一个,然后使用此值,但是我遇到很多错误。

CREATE VIEW Carti_Beletristica AS
SELECT titlu, nr_pagini, nr_exemplare, nume AS autor, telefon
FROM Carte NATURAL JOIN Autor JOIN Persoana ON (id_pers = id_aut)
WHERE upper(gen) = 'BELETRISTICA'

这是视图。

Create table Persoana(
    id_pers number(10) not null,
    nume varchar2(100) not null,
    telefon varchar2(15) not null,

    Constraint persoana_id_pers_pk primary key(id_pers)
 );

Create table Carte(
    id_carte number(10) not null,
    titlu varchar2(100) not null,
    nr_pagini number(10) not null,
    nr_exemplare number(10) not null,
    gen varchar2(20) not null,

    Constraint carte_id_carte_pk primary key(id_carte)  
 );

Create table Autor(
    id_carte number(10) not null,
    id_aut number(10) not null,

    Constraint autor_pk primary key(id_carte,id_aut),

    Constraint autor_id_carte_fk foreign key(id_carte) references Carte(id_carte),
    Constraint autor_id_aut_fk foreign key(id_aut) references Persoana(id_pers)

);

您能帮我一下吗?视图上的插入看起来像这样

Insert into Carti_Beletristica(titlu,nr_pagini,nr_exemplare,autor,telefon)
values('tiltu',69,96,'otor','07phonenumber')

编辑:

这是我尝试的主键

Create or replace trigger trigg_view
Instead of Insert ON Carti_Beletristica
for each row
declare
    aux persoana.id_pers%type;
Begin

    select max(id_pers)+1 into aux from Persoana;

    dbms_output.put_line(aux);

End;

1 个答案:

答案 0 :(得分:1)

  

我的想法是从表的主键中选择最大值,然后添加一个,然后使用该值,

您可能会认为“我的想法可行” ,但这是非常糟糕的做法:

select max(id_pers)+1 into aux from Persoana;

这是获取主键标识符的低效率方法。更重要的是它是不安全,因为它在多用户环境中不起作用:两个同时插入该表的用户将得出相同的“下一个值”(由于读取-提交隔离)那么其中一个用户在提交交易时就会收到重复的密钥冲突。

正确的解决方案是使用Oracle内置的唯一密钥生成器。在12c之前意味着序列。对于您的persoana表,这意味着创建一个名为persoana_seq的序列,您将在触发器中将其引用为:

aux := persoana_seq.nextval;

序列是生成一系列保证的唯一数字的最有效的机制。

在Oracle 12c中,我们可以将列定义为IDENTITY列。这为我们提供了一个自动递增的列:

create table persoana (
       id generated always as identity primary key,
       ....

persoana.id会在插入时自动填充一个唯一值,而我们不会采取任何其他措施。 (标识列在序列下有相关的序列,只是我们不必担心它们。)