INSERT INTO with CURSOR 在 TRIGGER 内

Posted

技术标签:

【中文标题】INSERT INTO with CURSOR 在 TRIGGER 内【英文标题】:INSERT INTO with CURSOR within a TRIGGER 【发布时间】:2019-12-21 12:06:24 【问题描述】:

我正在构建一个带有光标的触发器,当表格被更新或插入时,它应该在控制台中给出一个输出。这个想法是为每个品牌计算有多少汽车在桌子。我已经尝试了很多东西,但它似乎不起作用。如果我检查 INSERT INTO 语句的简单逻辑,例如 =

SELECT marca, count(*) as cuenta
FROM coches_seg_mano
GROUP BY marca;

它将返回这些品牌下汽车的总和。但是现在我正在创建一个触发器,每次我插入或更新时,它都会在控制台输出中向我提供这些信息。我试图带来上面查询的逻辑,但它似乎不起作用。

CREATE OR REPLACE TRIGGER t_mostrarmarcas 
AFTER INSERT OR UPDATE 
ON coches_seg_mano
DECLARE
    CURSOR totalmarcas IS
    SELECT matriculo,COUNT(*) as CUENTA
    FROM coches_seg_mano 
    GROUP BY matriculo;
    vmarca coches_seg_mano.marca%TYPE;
BEGIN
    FOR fila IN totalmarcas LOOP
    SELECT marca INTO vmarca FROM coches_seg_mano WHERE fila.matriculo=matriculo; 
    DBMS_OUTPUT.PUT_LINE('Para la marca '|| vmarca ||' tenemos '|| fila.cuenta ||' vehiculos');
    END LOOP;
END;

上面的那个确实给了我一个输出,但它计数。它只会给每个条目一个 1,我会看到品牌再次出现。所以不算每个品牌下的汽车。

CREATE OR REPLACE TRIGGER t_mostrarmarcas 
AFTER INSERT OR UPDATE 
ON coches_seg_mano
DECLARE
    CURSOR totalmarcas IS
    SELECT marca,COUNT(*) as CUENTA -- this
    FROM coches_seg_mano 
    GROUP BY marca;
    vmarca coches_seg_mano.marca%TYPE;
BEGIN
    FOR fila IN totalmarcas LOOP
    SELECT marca INTO vmarca FROM coches_seg_mano WHERE matriculo=matriculo; 
    DBMS_OUTPUT.PUT_LINE('Para la marca '|| vmarca ||' tenemos '|| fila.cuenta ||' vehiculos');
    END LOOP;
END;

这个会出错=

Error report -
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at "SYSTEM.T_MOSTRARMARCAS", line 9
ORA-06512: at "SYSTEM.T_MOSTRARMARCAS", line 9
ORA-04088: error during execution of trigger 'SYSTEM.T_MOSTRARMARCAS'
ORA-06512: at "SYSTEM.ENTRAR_VEHICULO", line 10
ORA-06512: at line 8
01422. 00000 -  "exact fetch returns more than requested number of rows"
*Cause:    The number specified in exact fetch is less than the rows returned.
*Action:   Rewrite the query or change number of rows requested

提前致谢!

【问题讨论】:

应该是FROM coches_seg_mano c WHERE c.matriculo = fila.matriculo。或者更好的是,将其作为连接包含在主光标中。 【参考方案1】:

这样的条件(在where 子句中)几乎总是错误的:

SELECT marca INTO vmarca FROM coches_seg_mano WHERE matriculo=matriculo; 

因为它的意思是“给我一切”,即好像你甚至没有使用那个条件。


看看这样的事情是否有帮助:

SQL> create table coches_seg_mano
  2    (marca      varchar2(10),
  3     matriculo  number
  4    );

Table created.

SQL> insert into coches_seg_mano values ('BMW', 100);

1 row created.

SQL> insert into coches_seg_mano values ('Audi', 200);

1 row created.

SQL>

触发器:

SQL> create or replace trigger t_mostramarcas
  2    after insert or update on coches_seg_mano
  3  begin
  4    for cur_r in (select marca, count(*) as cuenta
  5                  from coches_seg_mano
  6                  group by marca
  7                 )
  8    loop
  9      dbms_output.put_line('Marca = ' || cur_r.marca ||
 10                           ', cuenta = ' || cur_r.cuenta);
 11    end loop;
 12  end;
 13  /

Trigger created.

测试:

SQL> set serveroutput on;
SQL> insert into coches_seg_mano values ('BMW', 300);
Marca = BMW, cuenta = 2
Marca = Audi, cuenta = 1

1 row created.

SQL> insert into coches_seg_mano
  2    select 'BMW', 400 from dual union all
  3    select 'Mercedes', 500 from dual;
Marca = BMW, cuenta = 3
Marca = Mercedes, cuenta = 1
Marca = Audi, cuenta = 1

2 rows created.

SQL>

工作,有点……只是我不明白这种触发器的目的。只有运行插入时,您才会看到输出。最终用户,如果他们使用 - 例如 - Oracle Forms 或 Apex 应用程序 - 将看不到任何东西。即使其他人在他们自己的 SQL*Plus 会话中运行 INSERT,您也不会看到任何内容(因为结果将显示在 他们的屏幕上,而不是您的屏幕上)。

【讨论】:

非常感谢!我有它的工作!!!!!!!我不知道您可以在 FOR 循环中的括号之间创建一个选择语句。我还有很多东西要学,但非常感谢你的帮助!!!!【参考方案2】:

我认为第二个触发器中的 SELECT 不起作用是错误的,因为它返回多行,因为 matriculo=matriculo 总是正确的,例如1=1。

SELECT marca INTO vmarca FROM coches_seg_mano WHERE matriculo=matriculo;

尝试更改 where 子句。

【讨论】:

以上是关于INSERT INTO with CURSOR 在 TRIGGER 内的主要内容,如果未能解决你的问题,请参考以下文章

INSERT INTO WITH SELECT 和 WHERE(问题)

INSERT INTO with VALUES 和 SELECT STATEMENT

“GIS DICTIONARY A-Z” 查询页面开发——INSERT INTO数据库

SQL Insert into with select from multiple tables

“INSERT INTO ... FETCH ALL FROM ...”无法编译

insert into 和 where not exists