Переменная, содержащая количество строк, затронутых предыдущим DELETE?(в функции) - PullRequest
18 голосов
/ 25 июня 2010

У меня есть функция, которая используется как триггер 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;

Я хотел бы добавить в УВЕДОМЛЕНИЕ указание того, сколько строк затронуто (иначе: удалено) Как я могу это сделать (используя LANGUAGE 'plpgsql')?

UPDATE: Основываясь на некоторых отличных руководствах "Курица на кухне", я изменил это на:

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 ]

11 голосов
/ 25 июня 2010

В Oracle PL / SQL системная переменная для хранения количества удаленных / вставленных / обновленных строк:

SQL%ROWCOUNT

После оператора DELETE / INSERT / UPDATE и ПЕРЕД УСТАНОВКОЙ вы можете сохранитьSQL% ROWCOUNT в переменной типа NUMBER.Помните, что COMMIT или ROLLBACK сбрасывают в ноль значение SQL% ROWCOUNT, поэтому необходимо скопировать значение SQL% ROWCOUNT в переменную BEFORE COMMIT или ROLLBACK.

Пример:

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)

4/7/07, Картикеян Сундарам написал:

Привет,

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;

Есть ли что-то, равное sql% rowcount в postgres?Пожалуйста, помогите.

С уважением 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, OID последней строки, вставленной самой последней командой SQL.Обратите внимание, что RESULT_OID полезен только после команды INSERT в таблицу, содержащую OID.

Пример:

GET DIAGNOSTICS integer_var = ROW_COUNT;Второй метод определения эффектов команды - это проверка специальной переменной с именем FOUND, которая имеет тип boolean.FOUND начинает false в каждом вызове функции PL / pgSQL.Он устанавливается каждым из следующих типов операторов:

Оператор 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;любые изменения в ней влияют только на текущую функцию.

9 голосов
/ 12 ноября 2013

Для очень надежного решения, которое является частью 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;

чтобы увидеть итоги, вы можете получить любую совокупность и даже группу и отфильтровать ее.

1 голос
/ 27 декабря 2013

Я хотел бы поделиться своим кодом (у меня была эта идея от 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;
...