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

Cách dễ nhất để tạo một cột SN SÀNG trong Oracle là gì?

Nếu có bảng con được điền dữ liệu tham chiếu đến INITIATIVEID , Oracle sẽ tự động gây khó khăn cho việc thay đổi giá trị khóa chính bằng cách ngăn bạn tạo các hàng mồ côi bằng cách thay đổi khóa chính của phụ huynh. Vì vậy, ví dụ:nếu có một bảng con có ràng buộc khóa ngoại đối với TPM_INITIATIVES và có một hàng trong bảng con này có INITIATIVEID trên 17, bạn sẽ không thể thay đổi INITIATIVEID của hàng trong TPM_INITIAITVES bảng có giá trị hiện tại là 17. Nếu không có hàng nào trong bất kỳ bảng con nào tham chiếu đến hàng cụ thể trong TPM_INITIATIVES bảng, bạn có thể thay đổi giá trị nhưng, có lẽ, nếu không có mối quan hệ nào, việc thay đổi giá trị khóa chính là không quan trọng vì theo định nghĩa, nó không thể gây ra sự cố toàn vẹn dữ liệu. Tất nhiên, bạn có thể có mã chèn một hàng mới vào TPM_INITIATIVES với INITIATIVEID mới , thay đổi tất cả các hàng trong bảng con tham chiếu đến hàng cũ để tham chiếu đến hàng mới, sau đó sửa đổi hàng cũ. Nhưng điều này sẽ không bị mắc kẹt bởi bất kỳ giải pháp được đề xuất nào.

Nếu ứng dụng của bạn đã xác định bảng con nhưng không khai báo các ràng buộc khóa ngoại thích hợp, đó sẽ là cách tốt nhất để giải quyết vấn đề.

Điều đó đang được nói, giải pháp tạo khung nhìn của Arnon sẽ hoạt động. Bạn sẽ đổi tên bảng, tạo một dạng xem có cùng tên với bảng hiện có và (có khả năng) xác định một trình kích hoạt INSTEAD OF trên dạng xem sẽ không bao giờ cập nhật INITIATIVEID cột. Điều đó sẽ không yêu cầu thay đổi các bit khác của ứng dụng.

Bạn cũng có thể xác định một trình kích hoạt trên bảng

CREATE TRIGGER trigger_name 
  BEFORE UPDATE ON TPM_INITIATIVES  
  FOR EACH ROW
DECLARE
BEGIN
  IF( :new.initiativeID != :old.initiativeID )
  THEN
    RAISE_APPLICATION_ERROR( -20001, 'Sorry Charlie.  You can''t update the initiativeID column' );
  END IF;
END;

Tất nhiên, ai đó có thể vô hiệu hóa trình kích hoạt và đưa ra bản cập nhật. Nhưng tôi cho rằng bạn không cố gắng ngăn chặn kẻ tấn công mà chỉ là một đoạn mã lỗi.

Tuy nhiên, dựa trên mô tả các triệu chứng bạn đang thấy, sẽ có vẻ hợp lý hơn khi ghi lại lịch sử thay đổi đối với các cột trong bảng này để bạn thực sự có thể xác định điều gì đang xảy ra thay vì đoán và cố gắng cắm các lỗ hổng một. -bởi một. Vì vậy, ví dụ, bạn có thể làm điều gì đó như thế này

CREATE TABLE TPM_INITIATIVES_HIST (
   INITIATIVEID    NUMBER NOT NULL,
   NAME            VARCHAR2(100) NOT NULL,
   ACTIVE          CHAR(1) NULL,
   SORTORDER       NUMBER NULL,
   SHORTNAME       VARCHAR2(100) NULL,
   PROJECTTYPEID   NUMBER NOT NULL,
   OPERATIONTYPE   VARCHAR2(1) NOT NULL,
   CHANGEUSERNAME  VARCHAR2(30),
   CHANGEDATE      DATE,
   COMMENT         VARCHAR2(4000)
);

CREATE TRIGGER trigger_name 
  BEFORE INSERT or UPDATE or DELETE ON TPM_INITIATIVES  
  FOR EACH ROW
DECLARE
  l_comment VARCHAR2(4000);
BEGIN
  IF( inserting )
  THEN
    INSERT INTO tpm_initiatives_hist( INITIATIVEID, NAME, ACTIVE, SORTORDER, SHORTNAME, PROJECTTYPEID, 
                                      OPERATIONTYPE, CHANGEUSERNAME, CHANGEDATE )
      VALUES( :new.initiativeID, :new.name, :new.active, :new.sortOrder, :new.shortName, :new.projectTypeID, 
              'I', USER, SYSDATE );
  ELSIF( inserting )
  THEN
    IF( :new.initiativeID != :old.initiativeID )
    THEN
      l_comment := 'Initiative ID changed from ' || :old.initiativeID || ' to ' || :new.initiativeID;
    END IF;
    INSERT INTO tpm_initiatives_hist( INITIATIVEID, NAME, ACTIVE, SORTORDER, SHORTNAME, PROJECTTYPEID, 
                                      OPERATIONTYPE, CHANGEUSERNAME, CHANGEDATE, COMMENT )
      VALUES( :new.initiativeID, :new.name, :new.active, :new.sortOrder, :new.shortName, :new.projectTypeID, 
              'U', USER, SYSDATE, l_comment );
  ELSIF( deleting )
  THEN
    INSERT INTO tpm_initiatives_hist( INITIATIVEID, NAME, ACTIVE, SORTORDER, SHORTNAME, PROJECTTYPEID, 
                                      OPERATIONTYPE, CHANGEUSERNAME, CHANGEDATE )
      VALUES( :old.initiativeID, :old.name, :old.active, :old.sortOrder, :old.shortName, :old.projectTypeID, 
              'D', USER, SYSDATE );
  END IF;
END;

Sau đó, bạn có thể truy vấn TPM_INITIATIVES_HIST để xem tất cả các thay đổi đã được thực hiện cho một hàng cụ thể theo thời gian. Vì vậy, bạn có thể xem liệu các giá trị khóa chính có đang thay đổi hay ai đó đang thay đổi các trường không phải khóa. Lý tưởng nhất là bạn có thể có các cột bổ sung mà bạn có thể thêm vào bảng lịch sử để giúp theo dõi các thay đổi (tức là có lẽ có điều gì đó từ V$SESSION điều đó có thể hữu ích).



  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 để chuyển các tham số getters và setters của tôi cho lớp kết nối?

  2. Oracle:Xóa từ dưới lên

  3. Bắt đầu với Oracle SQL Developer trên MacOSX

  4. Chuỗi con REGEXP Oracle

  5. Oracle - Cách buộc người dùng CHÈN nhiều hàng