变量包含受前一个DELETE影响的行数? (在一个函数中)

时间:2010-06-25 06:07:36

标签: postgresql triggers plpgsql

我有一个用作INSERT触发器的函数。此函数删除与正在插入的行中的[序列号]冲突的行。它工作得很漂亮,所以我真的不想辩论这个概念的优点。

DECLARE
re1 feeds_item.shareurl%TYPE;
BEGIN
SELECT regexp_replace(NEW.shareurl, '/[^/]+(-[0-9]+\.html)$','/[^/]+\\1') INTO re1;
RAISE NOTICE 'DELETEing rows from feeds_item where shareurl ~ ''%''', re1;

DELETE FROM feeds_item where shareurl ~ re1;
RETURN NEW;
END;

我想在NOTICE中添加一个指示有多少行受影响(也就是:已删除)。我该怎么做(使用LANGUAGE'plpgsql')?

更新 根据“厨房里的鸡肉”的一些出色指导,我将其改为:

DECLARE
re1 feeds_item.shareurl%TYPE;
num_rows int;
BEGIN
SELECT regexp_replace(NEW.shareurl, '/[^/]+(-[0-9]+\.html)$','/[^/]+\\1') INTO re1;

DELETE FROM feeds_item where shareurl ~ re1;
IF FOUND THEN
    GET DIAGNOSTICS num_rows = ROW_COUNT;
    RAISE NOTICE 'DELETEd % row(s) from feeds_item where shareurl ~ ''%''', num_rows, re1;
END IF;
RETURN NEW;
END;

3 个答案:

答案 0 :(得分:11)

在Oracle PL / SQL中,用于存储已删除/插入/更新的行数的系统变量是:

SQL%ROWCOUNT

在DELETE / INSERT / UPDATE语句和BEFORE COMMITTING之后,您可以将SQL%ROWCOUNT存储在NUMBER类型的变量中。请记住,COMMIT或ROLLBACK将SQL%ROWCOUNT的值重置为ZERO,因此您必须在变量BEFORE COMMIT或ROLLBACK中复制SQL%ROWCOUNT值。

示例:

BEGIN
   DECLARE
      affected_rows   NUMBER DEFAULT 0;
   BEGIN
      DELETE FROM feeds_item
            WHERE shareurl = re1;

      affected_rows := SQL%ROWCOUNT;
      DBMS_OUTPUT.
       put_line (
            'This DELETE would affect '
         || affected_rows
         || ' records in FEEDS_ITEM table.');
      ROLLBACK;
   END;
END;

我也找到了这个有趣的解决方案(来源:http://markmail.org/message/grqap2pncqd6w3sp

  

2007年4月7日,Karthikeyan Sundaram写道:

     

您好,

I am using 8.1.0 postgres and trying to write a plpgsql block.  In that I am inserting a row.  I want to check to see if the row has been
     

是否插入。

     

在oracle,我们可以这样说

begin
  insert into table_a values (1);
  if sql%rowcount > 0
  then
    dbms.output.put_line('rows inserted');
  else
    dbms.output.put_line('rows not inserted');
 end if;  end;
     

在postgres中是否有与sql%rowcount相同的内容?请帮忙。

     

关心skarthi

     

也许:

     

http://www.postgresql.org/docs/8.2/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-SQL-ONEROW

     

点击上面的链接,您会看到以下内容:

     

37.6.6。获取结果状态有几种方法可以确定命令的效果。第一种方法是使用GET   DIAGNOSTICS命令,其格式为:

     

GET DIAGNOSTICS variable = item [,...];此命令允许   检索系统状态指标。每个项目都是关键词   标识要分配给指定变量的状态值   (应该是接收它的正确数据类型)。目前   可用状态项是ROW_COUNT,即处理的行数   发送到SQL引擎的最后一个SQL命令,以及RESULT_OID,   最近一次SQL命令插入的最后一行的OID。注意   RESULT_OID仅在INSERT命令进入表后才有用   包含OID。

     

一个例子:

     

GET DIAGNOSTICS integer_var = ROW_COUNT;第二种方法   确定命令的效果是检查特殊变量   名为FOUND,类型为boolean。 FOUND在内部开始是假的   每个PL / pgSQL函数调用。它由以下各种类型设置   声明:

     

如果指定了行,则SELECT INTO语句将FOUND设置为true,如果为,则设置为false   没有返回任何行。

     

如果PERFORM语句产生(并丢弃)a,则它将FOUND设置为true   row,如果没有生成行,则为false。

     

UPDATE,INSERT和DELETE语句设置FOUND为真,如果至少有一个   row受影响,如果没有行受影响,则为false。

     

如果FETCH语句返回一行,则设置FOUND为true,如果没有行则设置为false   退回。

     

FOR语句如果迭代一次或多次,则设置FOUND为true,否则为   假。这适用于FOR语句的所有三个变体   (整数FOR循环,记录集FOR循环和动态记录集FOR   循环)。当FOR循环退出时,FOUND以这种方式设置;在 - 的里面   执行循环时,FOR语句不修改FOUND,   虽然可以通过执行其他语句来改变它   循环体。

     

FOUND是每个PL / pgSQL函数中的局部变量;任何变化   它只影响当前的功能。

答案 1 :(得分:9)

对于非常强大的解决方案,这是PostgreSQL SQL的一部分,而不仅仅是plpgsql,您还可以执行以下操作:

with a as (DELETE FROM feeds_item WHERE shareurl ~ re1 returning 1)
select count(*) from a;

您实际上可以获得更多信息,例如:

with a as (delete from sales returning amount)
select sum(amount) from a;

要查看总计,通过这种方式,您可以获得任何聚合甚至组并对其进行过滤。

答案 2 :(得分:1)

我想分享我的代码(我从Roelof Rossouw那里得到了这个想法):

CREATE OR REPLACE FUNCTION my_schema.sp_delete_mytable(_id integer)
  RETURNS integer AS
$BODY$
  DECLARE
    AFFECTEDROWS integer;
  BEGIN
    WITH a AS (DELETE FROM mytable WHERE id = _id RETURNING 1)
    SELECT count(*) INTO AFFECTEDROWS FROM a;
    IF AFFECTEDROWS = 1 THEN
      RETURN 1;
    ELSE
      RETURN 0;
    END IF;
  EXCEPTION WHEN OTHERS THEN
    RETURN 0;
  END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;