插入后触发错误

时间:2014-11-20 22:53:44

标签: sql oracle

![在此输入图像描述] [1]我创建了一个触发器,每当我将信息插入表格时,我会计算总行数并打印新添加的行。这是我的代码:

Create or replace trigger TR_everyInsert
After INSERT On PERSONS 
For each row

Declare 
rowNumber int;
PERSON_NAME varchar(30);
gender varchar(30);
color varchar(30);

Begin
select PERSON_NAME,GENDER,COLOR
From PERSONS
Where PERSON_NAME=:new.PERSON_NAME;

select count(*) as rowNumber
from PERSONS;

if inserting then
DBMS_OUTPUT.PUT_LINE ('There are ' || To_CHAR(rowNumber));
DBMS_OUTPUT.PUT_LINE ('New added info is ' || PERSON_NAME || 'with gender ' || 
GENDER || 'with color ' || color);
end if;

end;
/

但是,我收到编译错误,说“预期到了条款”,请问有什么问题?

2 个答案:

答案 0 :(得分:1)

首先,您不能拥有只执行SELECT的PL / SQL块。您需要对数据执行某些操作。如果您希望查询恰好返回1行,请执行SELECT INTO。如果您希望查询返回多于1行,则需要打开要迭代的游标。

其次,在行级触发器中,通常无法查询表本身。你通常会得到一个变异表异常(在某些特殊情况下你可以这样做,但这会严重限制你的灵活性,所以应该避免这种情况)。要获取行级信息,只需使用:new伪记录中的各个列。为了获得计数,您实际上想要使用语句级触发器。根据Oracle版本,您可以创建具有行级和语句级组件的复合触发器。

第三,在仅在插入操作上定义的触发器中使用IF inserting语句并不合理。如果您的触发器是在多个操作(例如INSERT OR UPDATE)上定义的,并且您希望根据导致触发器触发的操作而执行不同的操作,那么只有这种语句才有意义。

最后,您需要将您的局部变量命名为与任何列的名称不同的名称。大多数人采用某种命名约定来消除局部变量,包全局变量和列名参数的歧义。我更喜欢前缀l_g_p_用于局部变量,包全局变量和参数,这是Oracle社区中一个相当常见的约定。你可能更喜欢别的东西。

这样的东西
-- A row-level trigger prints out the data that is being inserted
Create or replace trigger TR_everyInsert_row
  After INSERT On PERSONS 
  For each row
Begin
  DBMS_OUTPUT.PUT_LINE ('New added info is ' || :new.PERSON_NAME || 
                        ' with gender ' || :new.GENDER || 
                        ' with color ' || :new.color);
end;

-- A statement-level trigger prints out the current row count
Create or replace trigger TR_everyInsert_stmt
  After INSERT On PERSONS 
Declare
  l_cnt integer;
Begin
  select count(*)
    into l_cnt
    from persons; 

  DBMS_OUTPUT.PUT_LINE ('There are ' || To_CHAR(l_cnt) || ' rows.');
end;

答案 1 :(得分:0)

错误信息非常清楚。您需要将查询的结果放在您声明的变量中:

Create or replace trigger TR_everyInsert
After INSERT On PERSONS 
For each row

Declare 
lv_rowNumber int;
lv-_PERSON_NAME varchar(30);
lv_gender varchar(30);
lv_color varchar(30);

Begin
select PERSON_NAME,GENDER,COLOR
into lv_person_name, lv_gender, lv_color
From PERSONS
Where PERSON_NAME=:new.PERSON_NAME;

select count(*) into lv_rowNumber
from PERSONS;

if inserting then
DBMS_OUTPUT.PUT_LINE ('There are ' || To_CHAR(rowNumber));
DBMS_OUTPUT.PUT_LINE ('New added info is ' || PERSON_NAME || 'with gender ' || 
GENDER || 'with color ' || color);
end if;

end;
/

我建议你给你的变量命名不同于你的列。它可能会使代码混淆阅读...