Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

ORACLE cập nhật các bản ghi có mối quan hệ từ 1 đến nhiều bảng trong một trình kích hoạt

Đừng sử dụng một trình kích hoạt cho việc này. Hầu hết các điều kiện mà bạn đã mã hóa thành các IF lồng nhau (của trình kích hoạt của bạn) có thể được thực hiện thông qua các ràng buộc khóa ngoại và các ràng buộc kiểm tra. Ngoài ra, bạn không cần phải lưu trữ 'X' cho WOMAN_ACT ở bất kỳ đâu, vì nó là "giá trị bắt nguồn" tức là bạn có thể lấy hoặc tạo nó khi truy vấn dữ liệu của mình. Có thể ví dụ sau (dựa trên bảng và dữ liệu ban đầu của bạn) sẽ giúp bạn tìm ra giải pháp. Vui lòng đọc các bình luận trong mã.

Mã DDL

create table person (
  id number primary key
, registration_number varchar2(9) unique
, primary_number varchar2(9)
-- , women_act varchar2(1)   <- not needed!
); 
  
create table consolidated_numbers (
  secondary_number varchar2(9) references person( registration_number )
, person_id number references person( id )
); 

create table code (
  valid_code varchar2(2) primary key
);

-- CHECK constraint added to allow only certain TYPE_IDs
create table history_transaction (
  reason varchar2(2) references code( valid_code ) -- valid REASONSs enforced by FK constraint
, person_id number references person( id )
, type_id number check (
    type_id in (
      120, 140, 1420, 1440, 160, 180, 150, 1520, 1540, 1560  -- only allow these type_ids
    )
  )
, action_date date
);

Dữ liệu thử nghiệm

-- INSERT your initial test data
begin
  insert into person (ID,registration_number,primary_number) values(132, '000000001', null);
  insert into person (ID,registration_number,primary_number) values (151, '000000002', '000000001');
  insert into consolidated_numbers (SECONDARY_NUMBER,person_id) values ('000000002', 132);
  insert into code (valid_code) values ('A1');
  insert into code (valid_code) values ('T1');
  insert into code (valid_code) values ('N2');
  insert into history_transaction (reason,person_id,type_id,action_date)
    values ('A1', 132, 1420, DATE '2019-01-01');
  commit ;
end;
/

VIEW sau đây sẽ chọn person_id từ các bảng HISTORY_TRANSACTION, thêm và 'X' vào mỗi bảng trong số đó và cũng chọn tất cả những người "được liên kết" với (hoặc:được ánh xạ tới) các id này từ CONSOLIDATED_NUMBERS, đồng thời thêm một 'X' vào id của họ. (Lưu ý:có vẻ như bảng PERSON của bạn chứa mối quan hệ đệ quy, vì vậy người ta có thể viết một truy vấn đệ quy. Tuy nhiên, bạn sẽ có lý do để lập mô hình bảng CONSOLIDATED_NUMBERS, vì vậy chúng tôi sẽ sử dụng một JOIN tại đây.)

XEM

create or replace view personx
as
with PID as (
  select distinct person_id
  from history_transaction
)
select person_id, 'X' as woman_act  -- [Q1] all person_ids from history_transaction
from PID
union
select P.id, 'X' as woman_act       -- [Q2] all person_ids associated with ids from Q1
from person P
  join consolidated_numbers C
    on P.registration_number = C.secondary_number
    and C.person_id in (
      select person_id from PID
    )
;

-- with your initial test data, we get:
select * from personx ;
+---------+---------+
|PERSON_ID|WOMAN_ACT|
+---------+---------+
|132      |X        |
|151      |X        |
+---------+---------+

Bây giờ, hãy xóa / thêm một số dữ liệu và chạy một vài thử nghiệm (xem thêm: DBfiddle ):

-- test 1
delete from history_transaction ;
select * from personx ;
-- result: no rows selected -> OK

-- test 2
insert into history_transaction (reason,person_id,type_id,action_date) 
  values ('A1', 132, 1420, DATE '2019-01-01');
  
select * from personx ;
+---------+---------+
|PERSON_ID|WOMAN_ACT|
+---------+---------+
|132      |X        |
|151      |X        |
+---------+---------+

-- test 3: add more associations
begin   
-- new: person 345 associated with person 132
  insert into person (ID,registration_number,primary_number) values (345, '000000345', '000000001');
  insert into consolidated_numbers (SECONDARY_NUMBER,person_id) values ('000000345', 132);
  commit ;
end ;
/

select * from personx ;
+---------+---------+
|PERSON_ID|WOMAN_ACT|
+---------+---------+
|132      |X        |
|151      |X        |
|345      |X        |
+---------+---------+

Một bài kiểm tra khác trước khi chúng ta đi vào chi tiết hơn:

-- test 4
-- add more associations 
-- no entry in history_transactions for person(id) 1000        
begin   
  insert into person (ID,registration_number,primary_number) values(1000, '000000777', null);
  insert into person (ID,registration_number,primary_number) values (2000, '000000778', '000000777');
  insert into consolidated_numbers (SECONDARY_NUMBER,person_id) values ('000000778', 1000);
  commit ;
end ;
/   

-- output must be the same as before -> result OK
select * from personx ;
+---------+---------+
|PERSON_ID|WOMAN_ACT|
+---------+---------+
|132      |X        |
|151      |X        |
|345      |X        |
+---------+---------+

THAM GIA chế độ xem bàn cá nhân

-- test 5
-- add an entry from person 1000 into the history_transaction table
insert into history_transaction (reason,person_id,type_id,action_date) 
    values ('N2', 1000, 1420, sysdate);  

select * from personx ;
+---------+---------+
|PERSON_ID|WOMAN_ACT|
+---------+---------+
|132      |X        |
|151      |X        |
|345      |X        |
|1000     |X        |
|2000     |X        |
+---------+---------+

-- test 5: show more details
select P.id, P.registration_number, P.primary_number, PX.woman_act
from personx PX right join person P on PX.person_id = P.id ;

+----+-------------------+--------------+---------+
|ID  |REGISTRATION_NUMBER|PRIMARY_NUMBER|WOMAN_ACT|
+----+-------------------+--------------+---------+
|132 |000000001          |NULL          |X        |
|151 |000000002          |000000001     |X        |
|345 |000000345          |000000001     |X        |
|1000|000000777          |NULL          |X        |
|2000|000000778          |000000777     |X        |
+----+-------------------+--------------+---------+

Kết nối bên ngoài là cần thiết cho các PERSON_ID không có hàng tương ứng trong bảng HISTORY_TRANSACTION, ví dụ:

-- test 6
-- add more associations
-- no entry in history_transactions for person(id) 10000!
begin
  insert into person (ID,registration_number,primary_number) values(10000, '000007777', null);
  insert into person (ID,registration_number,primary_number) values (20000, '000007778', '000007777');
  insert into consolidated_numbers (SECONDARY_NUMBER,person_id) values ('000007778', 10000);
  commit ;
end ;
/

-- after TEST 6 data have been inserted:
select P.id, P.registration_number, P.primary_number, PX.woman_act
from personx PX right join person P on PX.person_id = P.id ;

+-----+-------------------+--------------+---------+
|ID   |REGISTRATION_NUMBER|PRIMARY_NUMBER|WOMAN_ACT|
+-----+-------------------+--------------+---------+
|132  |000000001          |NULL          |X        |
|151  |000000002          |000000001     |X        |
|345  |000000345          |000000001     |X        |
|1000 |000000777          |NULL          |X        |
|2000 |000000778          |000000777     |X        |
|20000|000007778          |000007777     |NULL     |
|10000|000007777          |NULL          |NULL     |
+-----+-------------------+--------------+---------+

CHỈNH SỬA

Nếu - như đã nêu trong nhận xét của bạn - bạn phải lưu trữ một giá trị trong cột WOMAN_ACT (mặc dù nó rõ ràng là "giá trị dẫn xuất"), bạn có thể viết một gói chứa các thủ tục cho tất cả các hoạt động DML bắt buộc - vẫn không cần sử dụng trình kích hoạt. Tuy nhiên, nếu không biết toàn bộ câu chuyện, thật khó để quyết định liệu đây có phải là cách tốt nhất về phía trước hay không. Ví dụ sau sử dụng một gói nhỏ chứa các thủ tục để đặt các giá trị WOMAN_ACT của bảng PERSON và một trình kích hoạt sẽ kích hoạt sau các INSERT / UPDATE (bảng:HISTORY_TRANSACTIONS). DBfiddle tại đây .

Bảng PERSON

create table person (
  id number primary key
, registration_number varchar2(9) unique
, primary_number varchar2(9)
, woman_act varchar2(1) check ( woman_act in ( null, 'X' ) )
);
-- all other tables: same as before

TRỌN GÓI

create or replace package pxpkg
is
  -- find out whether a certain id (table: PERSON) is a "parent" or a "child"
  function isparent( id_ number ) return boolean ;
  -- set 'X' values: id_ is a "parent"
  procedure setx_parentchildren( id_ number ) ;
  -- set 'X' values: id_ is a "child" 
  procedure setx_childsiblings( id_ number ) ;
end pxpkg ;
/

CƠ THỂ TRỌN GÓI

create or replace package body pxpkg
is
  function isparent( id_ number )
  return boolean
  is
    secondarynumbers pls_integer := 0 ;
  begin
    select count(*) into secondarynumbers
    from consolidated_numbers
    where person_id = id_ ;
    if secondarynumbers = 0 then
      return false ;
    else
      return true ;
    end if ;
  end isparent ;
--
  procedure setx_parentchildren ( id_ number )
  is
  begin
    update person
    set woman_act = 'X'
    where id in ( 
      select id from person where id = id_ -- parent id
      union
      select id from person 
      where primary_number = ( 
        select registration_number from person where id = id_ -- parent id
      )
    ) ;
  end setx_parentchildren ;
--
  procedure setx_childsiblings ( id_ number )
  is
  begin
    update person
    set woman_act = 'X'
    where id in ( 
      with PID as (
        select id, primary_number from person
        where id = id_                    -- current id
          and primary_number is not null  -- child ids only
      )
      select id from PID
      union
      select id 
      from person 
      where registration_number in ( select primary_number from PID )
         or primary_number in ( select primary_number from PID )
    ) ;
  end setx_childsiblings ;
end pxpkg ;
/

TRIGGER

create or replace trigger pxtrigger
after insert or update on history_transaction
for each row
begin
  if pxpkg.isparent( :new.person_id ) then
    pxpkg.setx_parentchildren( :new.person_id )  ;
  else
    pxpkg.setx_childsiblings( :new.person_id )  ;
  end if ;
end pxtrigger ;
/

KIỂM TRA:xem DBfiddle




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle SQL để thay đổi kiểu cột từ số thành varchar2 trong khi nó chứa dữ liệu

  2. Làm cách nào để lưu trữ một chuỗi dài hơn 4000 ký tự trong Cơ sở dữ liệu Oracle bằng Java / JDBC?

  3. Truy vấn sql Oracle cần thay đổi dựa trên múi giờ

  4. Tạo khóa tự động Hibernate với MySQL và Oracle

  5. Khi nào tôi cần sử dụng dấu chấm phẩy và dấu gạch chéo trong Oracle SQL?