2013-05-13 32 views
5

Tôi đã gặp một số sự cố khi chèn dữ liệu hàng loạt từ một bảng khác vào bảng mới. Mục tiêu trông hơi như thế này:INSERT INTO/SELECT DISTINCT dẫn đến vi phạm khóa chính cho SYS_GUID

CREATE TABLE TEST_T (
     T_GUID RAW(16) DEFAULT SYS_GUID() NOT NULL, 
     T_VAL1 NUMBER(10) NOT NULL, 
     T_VAL2 VARCHAR2(10) NOT NULL, 
     PRIMARY KEY (T_GUID) 
) 

các phiên bản đơn giản của bản tuyên bố tôi dự định để điền vào nó với dữ liệu:

INSERT INTO TEST_T (T_VAL1, T_VAL2) 
SELECT DISTINCT 
    CAST(SUBSTR(zip_code, 1,1) AS NUMBER) as t_val1, 
    zip_code as t_val2 
FROM OTHER_TABLE_T 
WHERE ... 
ORDER BY t_val1 

Như tôi không cung cấp một T_GUID có giá trị, tôi sẽ giả định đã tôi nhận được một cái được cung cấp bởi hàm SYS_GUID cho mỗi dòng mới. Nhưng có điều gì đó sai, và tôi nhận được một sự vi phạm ràng buộc duy nhất cho khóa chính.

Nếu tôi xóa DISTINCT, tuyên bố thành công, nhưng tôi nhận được nhiều mục nhập trùng lặp. Và, tất nhiên, nếu tôi cung cấp một cách rõ ràng một cuộc gọi SYS_GUID() trong số SELECT của tôi, có kết quả giống hệt nhau.

Bây giờ tôi thấy rằng nếu tôi chỉ cần đặt một SELECT xung quanh tôi, nó hoạt động ra sao, không có hành vi vi phạm chế và các hàng riêng biệt được chèn vào:

INSERT INTO ... 
SELECT x.* FROM (
    SELECT DISTINCT ... 
) x 

Vì vậy, nơi nào các guids trùng lặp đến từ đâu? Nếu tập hợp đầy đủ các hàng không có vấn đề, tại sao sẽ xóa hàng thông qua sự cố gây ra khác biệt? Vì SYS_GUID tạo một mã định danh duy nhất cho mỗi cuộc gọi, tôi chỉ có thể tưởng tượng rằng trong trường hợp riêng biệt, nó chỉ được gọi một lần cho toàn bộ mệnh đề, được giải quyết bằng gói xung quanh SELECT. Tôi sẽ rất hạnh phúc nếu có ai đó có thể giải thích cách thức thực hiện khác nhau trong trường hợp đó.

+0

Bạn có chắc chắn guids là bản sao? Nhìn rất kỹ vào chúng, chúng trông giống nhau nhưng bạn nên chú ý ít nhất một nhân vật khác nhau trong mỗi chúng. – GriffeyDog

+0

Mã của bạn có vẻ chính xác. Bạn có thể gặp lỗi Oracle, tra cứu "DUPLICATE SYS_GUID được tạo trên AIX có thể dẫn đến lỗi ORA-1 trong quá trình enqueue [ID 1371805.1]" trên Bộ phận Hỗ trợ Oracle của tôi. –

Trả lời

0

Thay CAST bằng to_number() và thêm guid. Kiểm tra bạn chọn đầu tiên, sau đó chèn ...:

SELECT DISTINCT 
    sys_guid() guid 
    To_Number(SUBSTR(zip_code, 1,1)) as t_val1, 
    zip_code as t_val2 
FROM OTHER_TABLE_T 
/

biệt GUID dụ:

SELECT sys_guid() gid, deptno 
    FROM 
(
SELECT distinct deptno FROM scott.emp 
) 
ORDER BY deptno 
/

GID         DEPTNO 
------------------------------------------- 
DC9B9132492C1A45E04011AC3EEB463A 10 
DC9B9132492B1A45E04011AC3EEB463A 20 
DC9B9132492A1A45E04011AC3EEB463A 30 
+0

Cảm ơn gợi ý 'to_number', nhưng điều này không thực sự giải quyết được vấn đề chính của tôi. Nếu tôi giới thiệu một sys_guid vào lựa chọn, thì sự khác biệt sẽ không lọc ra bất kỳ dòng trùng lặp nào (ví dụ: nếu tôi có nhiều hàng có cùng mã zip_code, nhưng một cột khác khác). – mhd

+0

@mhd - Sau đó loại bỏ nhóm sử dụng riêng biệt hoặc tồn tại vv .. Tại sao nên sử dụng guid thay vì một số loại ... – Art

+0

Lựa chọn thiết kế ở đây tại nơi làm việc, hầu hết các bảng đều có GUIDs là ID PK. Và có, có một số cách giải quyết có thể, và tôi đã giải quyết vấn đề của tôi với một gói SELECT đơn giản. Nhưng đó là một chút giống như "Bác sĩ cũ, cánh tay của tôi đau khi tôi làm điều này"/"Sau đó, không làm điều đó" trò đùa. Đối với giáo dục cá nhân của riêng tôi, tôi muốn biết những gì sai với bản gốc, cho dù khái niệm của tôi về mô hình quan hệ chỉ là xấu hoặc cho dù đó chỉ là một lỗi. – mhd

1

Hãy thử một cái gì đó như thế này:

insert into test_t(t_guid, t_val1, t_val2) 
    select sys_guid(), t_val1, t_val2 
    from (select distinct to_number(substr(zip_code, 1, 1)) as t_val1, zip_code as t_val2 
      from other_table_t 
      where ...) 
+0

Tôi thậm chí không cần phải làm điều đó. Như tôi đã viết ở trên, ngay sau khi tôi chọn 'select * từ (chọn khác biệt ...', nó hoạt động.Tôi chỉ không có lý do giải thích tốt. – mhd

Các vấn đề liên quan