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

Thêm các ràng buộc bằng cách sử dụng truy vấn con từ bảng khác

Một công việc xung quanh bạn có thể làm là tạo chế độ xem cụ thể hóa có chứa truy vấn xác định "hàng không hợp lệ".

create table messages(
   message_id  number       not null
  ,sender_id   varchar2(20) not null
  ,primary key(message_id)
);

create table receivers(
   message_id  number       not null
  ,receiver_id varchar2(20) not null
  ,primary key(message_id,receiver_id)
  ,foreign key(message_id) references messages(message_id)
);

create materialized view log 
    on receivers with primary key, rowid including new values;

create materialized view log 
    on messages  with primary key, rowid (sender_id) including new values;

create materialized view mv 
refresh fast on commit
as
select count(*) as bad_rows 
  from messages  m
  join receivers r using(message_id)
 where m.sender_id = r.receiver_id;

alter materialized view mv
  add constraint dont_send_to_self check(bad_rows = 0);

Bây giờ chúng ta hãy thử chèn một số hàng:

SQL> insert into messages(message_id, sender_id)    values(1, 'Ronnie');
1 row created.

SQL> insert into receivers(message_id, receiver_id) values(1, 'Mayank Sharma');
1 row created.

SQL> commit;
Commit complete.

Cũng đã đi. Bây giờ chúng ta hãy gửi một tin nhắn cho chính tôi:

SQL> insert into messages(message_id, sender_id) values(2, 'Ronnie');    
1 row created.

SQL> insert into receivers(message_id, receiver_id) values(2, 'Ronnie');    
1 row created.

SQL> commit;
commit
*
ERROR at line 1:
ORA-12008: error in materialized view refresh path
ORA-02290: check constraint (RNBN.DONT_SEND_TO_SELF) violated

Chỉnh sửa, giải thích thêm: Được rồi, truy vấn này (trong định nghĩa dạng xem cụ thể hóa), xác định và đếm tất cả các tin nhắn đang được gửi cho chính mình. Đó là, tất cả các hàng vi phạm quy tắc bạn đã nêu.

select count(*) as bad_rows 
  from messages  m
  join receivers r using(message_id)
 where m.sender_id = r.receiver_id;

Vì vậy, truy vấn phải trả về 0 hàng mọi lúc, phải không? Chế độ xem cụ thể hóa làm gì, là tự làm mới chính nó khi bất kỳ ai thực hiện thao tác DML đối với các bảng messages hoặc người nhận receivers . Vì vậy, về lý thuyết, nếu ai đó chèn một tin nhắn cho chính cô ấy, truy vấn sẽ trả về bad_rows = 1 . Tuy nhiên, tôi cũng đã bao gồm một ràng buộc đối với chế độ xem cụ thể hóa, nói rằng giá trị được phép duy nhất cho cột bad_rows là 0. Oracle sẽ không cho phép bạn thực hiện bất kỳ giao dịch nào mang lại giá trị khác.

Vì vậy, nếu bạn nhìn vào cặp câu lệnh chèn thứ hai, bạn có thể thấy rằng tôi đã quản lý để chèn hàng bị lỗi trong bộ nhận, nhưng Oracle đưa ra lỗi vi phạm ràng buộc khi tôi cố gắng cam kết.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm cách nào để thay đổi ngôn ngữ Oracle Exceptions trong .Net / C #?

  2. Tiện ích ADODFCMP

  3. sự khác biệt giữa mệnh đề ON và mệnh đề sử dụng trong sql

  4. Các hàm Oracle sử dụng Hibernate

  5. Tải tệp csv khổng lồ vào bảng cơ sở dữ liệu oracle bằng Pyspark