Количество строк, затронутых ОБНОВЛЕНИЕМ в PL / SQL

162

У меня есть функция PL / SQL (работает на Oracle 10g), в которой я обновляю некоторые строки. Есть ли способ узнать, на сколько строк повлияло ОБНОВЛЕНИЕ? При выполнении запроса вручную он сообщает мне, сколько строк было затронуто, я хочу получить это число в PL / SQL.

Томас Лётцер
источник

Ответы:

245

Вы используете sql%rowcountпеременную.

Вы должны вызывать его сразу после оператора, для которого нужно найти число затронутых строк.

Например:

set serveroutput ON; 
DECLARE 
    i NUMBER; 
BEGIN 
    UPDATE employees 
    SET    status = 'fired' 
    WHERE  name LIKE '%Bloggs'; 
    i := SQL%rowcount; 
    --note that assignment has to precede COMMIT
    COMMIT; 
    dbms_output.Put_line(i); 
END; 
Clive
источник
4
И назначение должно предшествовать любым коммитам
rshdev
@Clive У меня есть процедура с INSERT INTO... COMMITи в той же процедуре после вставки, у меня есть UPDATE SET WHERE EXISTS..COMMIT, но мой i := SQL%rowcount;возвращает все строки вместо строк, которые были только обновлены. Что может быть?
Гильерме Матеус
26

Для тех, кто хочет получить результаты от простой команды, решение может быть:

begin
  DBMS_OUTPUT.PUT_LINE(TO_Char(SQL%ROWCOUNT)||' rows affected.');
end;

Основная проблема заключается в том, что SQL% ROWCOUNT является переменной (или функцией) PL / SQL, и к ней нельзя получить прямой доступ из команды SQL. С помощью блока PL / SQL без имени это может быть достигнуто.

... Если у кого-то есть решение использовать его в команде SELECT, мне было бы интересно.

ЦБС
источник
6

в качестве альтернативы, SQL%ROWCOUNT вы можете использовать это в процедуре без необходимости объявлять переменную

Али Н
источник
4
SQL% ROWCOUNT - это функция, вы не можете просто «использовать ее» - вам нужно что- то с ней делать - будь то сохранение в переменной, или отправка ее в качестве входных данных для другой процедуры, или добавление ее к чему-то еще.
Джеффри Кемп
8
Я думаю, что точка зрения Али Х состоит в том, что нет необходимости присваивать ее переменной, пока у вас не появится другой оператор SQL, который повлияет на количество строк. При этом я согласен с тем, что она должна быть назначена переменной, чтобы избежать возникновения ошибки позже, если кто-то добавит другой оператор SQL до его вызова. И этот ответ от Али Х должен быть комментарием к ответу Клайва, а не размещаться как отдельный ответ
Кирби
1

SQL%ROWCOUNTтакже может использоваться без назначения (по крайней мере, из Oracle 11g ).

Пока в текущем блоке не было выполнено ни одной операции (обновления, удаления или вставки), SQL%ROWCOUNTустанавливается нулевое значение. Затем он остается с номером строки, затронутой последней операцией DML:

скажем у нас есть таблица КЛИЕНТ

create table client (
  val_cli integer
 ,status varchar2(10)
)
/

Мы бы проверили это так:

begin
  dbms_output.put_line('Value when entering the block:'||sql%rowcount);

  insert into client 
            select 1, 'void' from dual
  union all select 4, 'void' from dual
  union all select 1, 'void' from dual
  union all select 6, 'void' from dual
  union all select 10, 'void' from dual;  
  dbms_output.put_line('Number of lines affected by previous DML operation:'||sql%rowcount);

  for val in 1..10
    loop
      update client set status = 'updated' where val_cli = val;
      if sql%rowcount = 0 then
        dbms_output.put_line('no client with '||val||' val_cli.');
      elsif sql%rowcount = 1 then
        dbms_output.put_line(sql%rowcount||' client updated for '||val);
      else -- >1
        dbms_output.put_line(sql%rowcount||' clients updated for '||val);
      end if;
  end loop;  
end;

В результате чего:

Value when entering the block:
Number of lines affected by previous DML operation:5
2 clients updated for 1
no client with 2 val_cli.
no client with 3 val_cli.
1 client updated for 4
no client with 5 val_cli.
1 client updated for 6
no client with 7 val_cli.
no client with 8 val_cli.
no client with 9 val_cli.
1 client updated for 10
Дж. Чомел
источник
-1

Примерьте вот это..


create table client (
  val_cli integer
 ,status varchar2(10)
);

---------------------
begin
insert into client
select 1, 'void' from dual
union all
select 4, 'void' from dual
union all
select 1, 'void' from dual
union all
select 6, 'void' from dual
union all
select 10, 'void' from dual;
end;

---------------------
select * from client;

---------------------
declare
  counter integer := 0;
begin
  for val in 1..10
    loop
      update client set status = 'updated' where val_cli = val;
      if sql%rowcount = 0 then
        dbms_output.put_line('no client with '||val||' val_cli.');
      else
        dbms_output.put_line(sql%rowcount||' client updated for '||val);
        counter := counter + sql%rowcount;
      end if;
  end loop;
   dbms_output.put_line('Number of total lines affected update operation: '||counter);
end;

---------------------
select * from client;

--------------------------------------------------------

Результат будет как ниже:


2 клиента обновлены для 1
нет клиента с 2 val_cli.
нет клиента с 3 val_cli.
1 клиент обновлен для 4
нет клиентов с 5 val_cli.
1 клиент обновлен для 6
нет клиента с 7 val_cli.
нет клиента с 8 val_cli.
нет клиента с 9 val_cli.
1 клиент обновлен за 10
Количество строк, затронутых операцией обновления: 5


Арун Сундриял
источник
Добавьте комментарии к вашему решению, пожалуйста, будьте конкретны.
Кумар Абхишек
-3

Используйте аналитическую функцию Count (*). OVER PARTITION BY NULL Это будет считать общее количество строк

гость
источник
После запуска оператора обновления, если вы проверите счет того, что вы действительно обновили - это не дает никакого общего решения. Например, если в моей таблице T есть один столбец c1, который содержит «1» в качестве значения для всех, и теперь я обновляю все строки для этого столбца до «2», как поможет разделение по нулю?
Нанософт