Sử dụng nhiều bảng chèn cho bảng cha mẹ và trẻ em


8

Có an toàn không khi sử dụng câu lệnh chèn nhiều bảng của Oracle để chèn vào bảng cha và con (ràng buộc khóa ngoài)?

Với các ví dụ tối thiểu, tôi đã thấy rằng nó hoạt động miễn là bảng cha xuất hiện trước bảng con trong intodanh sách. Tôi có thể dựa vào điều này hay tôi nên làm cho các ràng buộc có thể được bảo vệ?


Bạn đang nói về INSERT ALL?
Philᵀᴹ

@ Phil: Vâng, tôi đây.
Isaac Kleinman

Còn hai miếng chèn thì sao? Tại sao đi theo đường vòng với các ràng buộc có thể bảo vệ khi phương pháp đơn giản của nhiều lần chèn luôn hoạt động?
Vincent Malgrat

1
@Vincent đôi khi phải mất một phần thời gian để insert all- đó có thể là lý do của Isaac?
Jack nói hãy thử topanswers.xyz

@JackDoumund Hiệu suất là một lý do chính đáng, nhưng INSERT ALLcó rất nhiều hạn chế: không thực hiện song song, không chèn vào chế độ xem. Điều này khiến tôi nghĩ rằng tuyên bố này ít được tối ưu hóa hơn các INSERTtuyên bố tiêu chuẩn , đặc biệt là khi chèn vào nhiều bảng.
Vincent Malgrat

Câu trả lời:


7

Không , bạn không thể phụ thuộc vào điều này. SQL là khai báo, không phải là thủ tục, vì vậy trong một câu lệnh, bạn không thể đảm bảo thứ tự thực hiện. Vì toàn bộ INSERT ALLcâu lệnh được coi là một câu lệnh ( doc ), bạn không thể đảm bảo rằng câu lệnh INSERTsẽ đứng trước câu lệnh khác.

Theo định nghĩa, INSERT FIRSTphải thực hiện đầu tiên INTOvượt qua các điều kiện được đánh giá. Chúng ta có thể mong đợi INSERT ALLhành xử tương tự. Điều này dường như là trường hợp:

DROP TABLE T1;
CREATE TABLE T1 AS (SELECT 'a' c1, 0 c2, 0 c3 FROM dual WHERE 1=2);
INSERT ALL 
   WHEN mod(x,2)<>0 THEN INTO T1 VALUES ('a', x, mod(x,2)) 
   WHEN mod(x,2)=0 THEN INTO T1 VALUES ('b', x, mod(x,2)) 
   SELECT Level x FROM dual CONNECT BY Level <=20;
COMMIT;   
SELECT rowid, c1, c2, c3 FROM t1;

Tuy nhiên, mặc dù chúng tôi có thể chứng minh một hành vi cụ thể trên một nền tảng / phiên bản / bản vá cụ thể vẫn không đảm bảo điều này.

Oracle-developer.net nói rõ ràng:

các điều kiện trong câu lệnh INSERT FIRST sẽ được đánh giá theo thứ tự từ trên xuống dưới. Oracle không đảm bảo như vậy với một tuyên bố INSERT ALL.


1
Oracle thực sự coi hành vi không xác định này là một lỗi (xem bài viết Hỗ trợ Oracle của tôi 265826.1 cho lỗi 2891576). Tuy nhiên, do điều này đã được đưa trở lại vào năm 2003 cho phiên bản 9.2.0.3, tôi nghi ngờ có nhiều khả năng điều này sẽ được khắc phục sớm.
Chris Saxon

1
@Chris Saxon Tuyệt vời tìm thấy. Báo cáo cho thấy một trường hợp trong đó sửa đổi kích thước của cột không liên quan ảnh hưởng đến việc thực hiện trước. Như dự kiến, cách giải quyết là sử dụng DEFERRED CONSTRAINTS.
Leigh Riffel

2

Isaac

Bạn không thể dựa vào điều này vì nhà tiên tri không đảm bảo thứ tự của INSERT. Cách chính xác để làm điều này là, như bạn đã đề cập, với ràng buộc khóa ngoài bị trì hoãn.


Thứ tự không quan trọng, vì các ràng buộc được kiểm tra sau khi lệnh SQL được thực thi. Về mặt lý thuyết là do lỗi được đề cập ở trên, nó không hoạt động chính xác. Xem ví dụ bằng cách sử dụng INSERT ... SELECTtại đây: sqlfiddle.com/#!15/7de0f (lưu ý rằng nó hoạt động với PostreQuery và Oracle, nhưng không phải với MySQL hoặc MS SQL)
David Balažic 17/03/2017
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.