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).