【问题标题】:Count rows affected by DELETE计算受 DELETE 影响的行数
【发布时间】:2014-01-14 22:24:48
【问题描述】:

我使用这段代码来验证DELETE这句话,但我相信你知道更好的方法:

CREATE OR REPLACE FUNCTION my_schema.sp_delete_row_table(table_name character varying
                                                       , id_column character varying
                                                       , id_value integer)
  RETURNS integer AS
$BODY$
  DECLARE
    BEFORE_ROWS integer;
    AFTER_ROWS integer;
  BEGIN
    EXECUTE 'SELECT count(*) FROM ' || TABLE_NAME INTO BEFORE_ROWS;
    EXECUTE 'DELETE FROM ' || TABLE_NAME || ' WHERE ' || ID_COLUMN || ' = ' || (ID_VALUE)::varchar;
    EXECUTE 'SELECT count(*) FROM ' || TABLE_NAME INTO AFTER_ROWS;

    IF BEFORE_ROWS - AFTER_ROWS = 1 THEN
      RETURN 1;
    ELSE
      RETURN 2;
    END IF;
  EXCEPTION WHEN OTHERS THEN
    RETURN 0;
  END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

如何改进这段代码?我需要它在 Postgres 8.4、9.1 和 9.2 中工作。

【问题讨论】:

  • 当前接受的答案不正确。考虑第二个答案。

标签: sql postgresql plpgsql postgresql-9.1 postgresql-9.2


【解决方案1】:

查看名为foundrow_count 的变量:

http://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-DIAGNOSTICS

found 如果有任何行受到影响,则为真。 row_count 为您提供受影响的行数。

IF FOUND THEN
  GET DIAGNOSTICS integer_var = ROW_COUNT;
END IF;

【讨论】:

  • 执行'删除'||表名 || '在哪里' || ID_COLUMN || '=' || (ID_VALUE)::varchar;
  • 获取诊断 AFFECTED_ROWS = ROW_COUNT;
  • 如果 AFFECTED_ROWS = 1 那么返回 1;如果结束;
  • 这些语句可能都可以更改:RETURN FOUND::int;
  • 公平点。顺便说一句,您应该真正转义这些语句中的变量以避免 sql 注入。根据我指向您的同一页面上的文档,使用 quote_ident()quote_literal()
【解决方案2】:

实际上,您不能FOUNDEXECUTE 一起使用。 The manual:

特别注意EXECUTE 改变了GET DIAGNOSTICS 的输出, 但不会改变FOUND

还有一些其他方面可能需要改进。首先,您的原始文件对 SQL 注入是开放的。我建议:

CREATE OR REPLACE FUNCTION my_schema.sp_delete_row_table(table_name regclass
                                                       , id_column  text
                                                       , id_value   int
                                                       , OUT del_ct int) AS
$func$
BEGIN
   EXECUTE format ('DELETE FROM %s WHERE %I = $1', table_name, id_column);
   USING id_value;                     -- assuming integer columns

   GET DIAGNOSTICS del_ct = ROW_COUNT; -- directly assign OUT parameter

EXCEPTION WHEN OTHERS THEN
   del_ct := 0;
END
$func$  LANGUAGE plpgsql;

format() 需要 Postgres 9.1 或更高版本。您可以将其替换为字符串连接,但请务必使用 quote_ident()!
正确使用转义列名 其余的也适用于 8.4。

密切相关的答案:

【讨论】:

  • 是的 Erwin Brandstetter,我使用 EXECUTE 并在 GET DIAGNOSTICS 之后使用。对于 INSERT、UPDATE、DELETE 语句,我只使用 FOUN。
猜你喜欢
  • 2013-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-08
相关资源
最近更新 更多