22

我有一个用作 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;

我想在通知中添加一个指示有多少行受到影响(又名:已删除)。我该怎么做(使用语言'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;
4

3 回答 3

13

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

SQL%ROWCOUNT

在 DELETE / INSERT / UPDATE 语句之后和提交之前,您可以将 SQL%ROWCOUNT 存储在 NUMBER 类型的变量中。请记住,COMMIT 或 ROLLBACK 会将 SQL%ROWCOUNT 的值重置为零,因此您必须在 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的东西?请帮忙。

问候斯卡蒂

也许:

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 的表后才有用。

一个例子:

获取诊断 integer_var = ROW_COUNT; 确定命令效果的第二种方法是检查名为 FOUND 的特殊变量,它是布尔类型。FOUND 在每个 PL/pgSQL 函数调用中开始为 false。它由以下每种类型的语句设置:

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

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

如果至少有一行受到影响,UPDATE、INSERT 和 DELETE 语句将 FOUND 设置为 true,如果没有行受到影响,则设置为 false。

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

如果 FOR 语句迭代一次或多次,则将 FOUND 设置为 true,否则设置为 false。这适用于 FOR 语句的所有三种变体(整数 FOR 循环、记录集 FOR 循环和动态记录集 FOR 循环)。FOUND 在 FOR 循环退出时设置为这种方式;在循环执行过程中,FOUND 不会被 FOR 语句修改,尽管它可能会被循环体内其他语句的执行所改变。

FOUND 是每个 PL/pgSQL 函数中的局部变量;对其进行的任何更改仅影响当前功能。

于 2010-06-25T06:10:45.093 回答
12

对于一个非常强大的解决方案,它是 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;

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

于 2013-11-12T06:27:49.243 回答
3

我想分享我的代码(我从 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;
于 2013-12-27T08:06:11.857 回答