【问题标题】:Oracle cursor behaviour in trigger body触发器主体中的 Oracle 游标行为
【发布时间】:2014-10-12 07:15:34
【问题描述】:

请帮助我理解以下 Oracle 游标代码。我对get_geog= geography 部分感到特别困惑。 geography 的值是多少?它是否具有 new.geography 的价值?还有c2b_rec.geolevel_id >= c2a_rec.geolevel_id这里的c2b_rec和c2a_rec有什么区别?

CREATE OR REPLACE TRIGGER tr_name
    BEFORE DELETE OR INSERT OR UPDATE OF geography, 
        ON tbl_name
    FOR EACH ROW
DECLARE 

CURSOR c2(get_geog IN VARCHAR2, get_geolevel IN VARCHAR2) IS
        SELECT *
          FROM geolevels
         WHERE get_geog     = geography
           AND get_geolevel = geolevel;
    c2a_rec c2%ROWTYPE;
    c2b_rec c2%ROWTYPE;

IF c2b_rec.geolevel_id >= c2a_rec.geolevel_id THEN
some code 

【问题讨论】:

  • 我理解您作为示例@zaratustra 提供的代码,但不是我最初发布的代码。我的问题仍然在 c2b_rec.geolevel_id >= c2a_rec.geolevel_idWHERE get_geog = geography 上。代码中没有open cursor 或 fetch cursor。

标签: sql-server oracle triggers cursor


【解决方案1】:

这部分:

CURSOR c2(get_geog IN VARCHAR2, get_geolevel IN VARCHAR2) 
IS
SELECT *
  FROM geolevels
 WHERE get_geog = geography
   AND get_geolevel = geolevel;

意味着您声明一个基于其SELECT 语句的结果集的新游标。由于您没有向我们展示其他变量,我可以得出结论 geographygeolevelgeolevels 表的字段。 get_geogget_geolevel是光标的参数。

这行:

c2a_rec c2%ROWTYPE;
c2b_rec c2%ROWTYPE;

声明两个可用于从游标中获取数据的变量。

在这一行之前:

IF c2b_rec.geolevel_id >= c2a_rec.geolevel_id THEN

您必须有一个打开和获取光标的部分。像这样的:

OPEN c2('one', 'two');
fetch c2 into c2a_rec;
fetch c2 into c2b_rec;

当您获取游标时,您会从 select 语句返回的结果集中提取行。因此c2a_rec 变量将具有结果集的第一行,c2b_rec 变量将具有结果集的第二行。然后将光标的geolevel_id 字段的值与此行进行比较:

IF c2b_rec.geolevel_id >= c2a_rec.geolevel_id THEN

所以如果你不知道如何使用参数化游标,看看这个:

create table t1 (
  id number(10)
);
create table t2 (
  id number(10)
);
create OR REPLACE trigger t1_trg 
after insert
on t1
for each row
declare
  cursor c1 (p_id NUMBER)
  is
    select id
      from t2
     where id = p_id
  ;
  c1_row c1%ROWTYPE;
begin
  open c1(1);
  fetch c1 into c1_row;
  IF c1%FOUND
  THEN
    DBMS_OUTPUT.put_line(c1_row.id);
  ELSE
    DBMS_OUTPUT.put_line('There is not such value');
  END IF;
  close c1;
END t1_trg;

INSERT INTO t1 values (1);

There is not such value

1 row(s) inserted.

INSERT INTO t2 values (1);

1 row(s) inserted.

INSERT INTO t1 values (2);

1

1 row(s) inserted.

如您所见,我在打开游标时传递了值 1,并且在打开游标时使用了该值。

【讨论】:

  • 谢谢。 geography 和 geolevel 是 geolevel 表中存在的字段,但我认为 get_geog 和 get_geolevel 是 CURSOR 变量。那么,SELECT * FROM geolevels WHERE get_geog = geography AND get_geolevel = geolevel; 可以返回多个匹配的行,c2a_rec c2%ROWTYPE;c2b_rec c2%ROWTYPE; 将保存 geolevel 表中的第一行和第二行?但是这两个变量不存在于tbl_name 中,触发器打开了,所以它到底从哪里获取值?
  • 我不明白你的意思。如果除了 c2 之外没有显示任何其他游标,get_geog 和 get_geolevel 怎么能成为游标变量?
  • 抱歉,但我对游标不熟悉,因为在 SQL Server 中不惜一切代价避免使用它。我认为它们是游标变量,因为这条线 CURSOR c2(l_geography IN VARCHAR2, l_geolevel_name IN VARCHAR2) ?
  • 好的,现在我明白了,你的游标有参数,所以 get_geog 和 get_geolevel 是游标的参数。所以当你打开它时你必须传递参数:比如open c2('first', 'second'); 但是你的问题是什么?
  • 是的正确,我的问题是,触发器写在tbl_name 上并且它没有地理列,所以当光标匹配 geoghraphty 和 geolevel 的值时,它在哪里得到匹配的值从 ? WHERE get_geog = geography AND get_geolevel = geolevel
猜你喜欢
  • 1970-01-01
  • 2013-11-30
  • 1970-01-01
  • 2021-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多