จำนวนแถวที่ได้รับผลกระทบจาก UPDATE ใน PL / SQL


162

ฉันมีฟังก์ชั่น PL / SQL (ทำงานบน Oracle 10g) ซึ่งฉันจะอัพเดตบางแถว มีวิธีการตรวจสอบว่ามีกี่แถวที่ได้รับผลกระทบจาก UPDATE หรือไม่ เมื่อดำเนินการแบบสอบถามด้วยตนเองมันจะบอกฉันว่ามีกี่แถวที่ได้รับผลกระทบฉันต้องการรับหมายเลขนั้นใน 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; 

4
และการมอบหมายจะต้องนำหน้าข้อผูกพันใด ๆ
rshdev

@ ไคลเอนต์ฉันมีขั้นตอนด้วยINSERT INTO.. COMMITและยังอยู่ในขั้นตอนเดียวกันหลังจากแทรกฉันมีUPDATE SET WHERE EXISTS..COMMITแต่ฉันi := SQL%rowcount;จะกลับแถวทั้งหมดแทนแถวที่มีการปรับปรุงเท่านั้น อาจเป็นอะไร
Guilherme Matheus

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
ฉันคิดว่าจุดของ Ali H คือไม่จำเป็นต้องกำหนดให้กับตัวแปรจนกว่าคุณจะมีคำสั่ง SQL อื่นที่จะมีผลต่อการนับแถว ที่ถูกกล่าวว่าฉันยอมรับว่าควรได้รับมอบหมายให้ตัวแปรเพื่อหลีกเลี่ยงการก่อให้เกิดข้อผิดพลาดในภายหลังควรมีคนเพิ่มคำสั่ง SQL อื่นก่อนที่จะถูกเรียก และคำตอบจาก Ali H นี้ควรเป็นความเห็นต่อคำตอบของคลีฟแทนที่จะโพสต์เป็นคำตอบที่แยกจากกัน
Kirby

1

SQL%ROWCOUNTสามารถใช้งานได้โดยไม่ได้รับมอบหมาย (อย่างน้อยจากOracle 11g )

ตราบใดที่ยังไม่มีการดำเนินการ (อัพเดทลบหรือแทรก) ภายในบล็อกปัจจุบันSQL%ROWCOUNTถูกตั้งค่าเป็น null จากนั้นจะอยู่กับจำนวนบรรทัดที่ได้รับผลกระทบจากการดำเนินการ 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



เพิ่มความคิดเห็นในโซลูชันของคุณโปรดระบุ
Kumar Abhishek

-3

ใช้ฟังก์ชั่นการวิเคราะห์ Count (*) OVER PARTITION BY NULL ซึ่งจะนับจำนวนแถวทั้งหมด


หลังจากเรียกใช้คำสั่งปรับปรุงถ้าคุณตรวจสอบจำนวนในสิ่งที่คุณปรับปรุงจริง - นี่ไม่ได้ให้โซลูชั่นทั่วไป ตัวอย่างเช่นหากตาราง T ของฉันมีหนึ่งคอลัมน์ c1 ซึ่งมี "1" เป็นค่าสำหรับทุกคนและตอนนี้ฉันอัปเดตแถวทั้งหมดสำหรับคอลัมน์นั้นเป็น "2" การแบ่งพาร์ติชันด้วย null จะช่วยได้อย่างไร
nanosoft
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.