2011-09-27 53 views
12

Tôi đang cố gắng tạo một hàng mới trong một bảng. Có hai ràng buộc trên bảng - một là trên trường khóa (DB_ID), các ràng buộc khác một giá trị là một trong một số trường ENV. Khi tôi làm một chèn, tôi không bao gồm các lĩnh vực chủ chốt là một trong những lĩnh vực tôi đang cố gắng để chèn, nhưng tôi nhận được lỗi này:Vi phạm ràng buộc duy nhất trong quá trình chèn: tại sao? (Oracle)

unique constraint (N390.PK_DB_ID) violated 

Đây là SQL gây ra lỗi:

insert into cmdb_db 
    (narrative_name, db_name, db_type, schema, node, env, server_id, state, path) 
values 
    ('Test Database', 'DB', 'TYPE', 'SCH', '', 'SB01', 381, 'TEST', '') 

Điều duy nhất tôi có thể bật lên là khả năng Oracle có thể đang cố gán một DB_ID đã được sử dụng nếu các hàng được chèn thủ công. Dữ liệu trong cơ sở dữ liệu này đã được khôi phục/di chuyển từ cơ sở dữ liệu sản xuất bằng cách nào đó, nhưng tôi không có chi tiết về cách thực hiện.

Mọi suy nghĩ?

Trả lời

34

Có lẽ, kể từ khi bạn không cung cấp giá trị cho cột DB_ID, giá trị đó đã được dân cư của một row-level trước khi chèn kích hoạt được xác định trên bàn. Kích hoạt đó, có lẽ, đang chọn giá trị từ một chuỗi.

Vì dữ liệu đã được di chuyển (có lẽ gần đây) từ cơ sở dữ liệu sản xuất, đặt cược của tôi sẽ là khi dữ liệu được sao chép, trình tự cũng không được sửa đổi. Tôi đoán rằng trình tự tạo ra các giá trị thấp hơn nhiều so với số lớn nhất DB_ID hiện đang nằm trong bảng dẫn đến lỗi.

Bạn có thể xác nhận sự nghi ngờ này bằng cách nhìn vào kích hoạt để xác định thứ tự đang được sử dụng và thực hiện một

SELECT <<sequence name>>.nextval 
    FROM dual 

và so sánh đó để

SELECT MAX(db_id) 
    FROM cmdb_db 

Nếu, như tôi nghi ngờ, trình tự đang tạo ra các giá trị đã tồn tại trong cơ sở dữ liệu, bạn có thể tăng chuỗi cho đến khi nó tạo ra các giá trị không sử dụng hoặc bạn có thể thay đổi nó để đặt INCREMENT thành thứ gì đó rất lớn, nhận được lần kế tiếp một lần và đặt INCREMENT trở lại 1.

+9

+1 Phỏng đoán hợp lý – APC

1

Dường như bạn không cung cấp giá trị cho trường khóa chính DB_ID. Nếu đó là khóa chính, bạn phải cung cấp một giá trị duy nhất cho cột đó. Cách duy nhất không cung cấp nó sẽ là tạo ra một kích hoạt cơ sở dữ liệu, khi chèn, sẽ cung cấp một giá trị, rất có thể xuất phát từ một chuỗi.

Nếu đây là khôi phục từ cơ sở dữ liệu khác và có một chuỗi trên phiên bản mới này, có thể bạn đang cố gắng sử dụng lại giá trị. Nếu dữ liệu cũ có các khóa duy nhất từ ​​1 đến 1000 và chuỗi hiện tại của bạn là 500, nó sẽ tạo ra các giá trị đã tồn tại. Nếu một chuỗi tồn tại cho bảng này và nó đang cố gắng sử dụng nó, bạn sẽ cần phải điều hòa các giá trị trong bảng của bạn với giá trị hiện tại của chuỗi.

Bạn có thể sử dụng SEQUENCE_NAME.CURRVAL để xem giá trị hiện tại của chuỗi (nếu nó tồn tại tất nhiên)

+0

Thông tin của tôi trên cơ sở dữ liệu cho biết khóa sẽ tự động được tạo khi chèn hàng mới - đó là lý do tại sao tôi không cung cấp giá trị cho DB_ID. Hơn nữa, kỹ thuật tương tự này hoạt động trên các bảng khác trong cơ sở dữ liệu tương tự - chúng có khóa ID được tạo tự động. – Sean

+0

Bạn có thể truy vấn từ điển dữ liệu để xem các trình kích hoạt/trình tự cần thiết có tồn tại trong môi trường mới không? Có lẽ không phải mọi thứ đã được đưa ra từ môi trường cũ. –

1

lỗi của bạn trông giống như bạn đang sao chép một Primary Key đã tồn tại trong DB của bạn. Bạn nên sửa đổi mã sql của bạn để thực hiện khóa chính của chính nó bằng cách sử dụng một cái gì đó giống như từ khóa IDENTITY.

CREATE TABLE [DB] (
    [DBId] bigint NOT NULL IDENTITY, 
    ... 

    CONSTRAINT [DB_PK] PRIMARY KEY ([DB] ASC), 

); 
+1

IDENTITY không phải là một từ khóa hợp lệ trong Oracle. –

+0

Đó là một tuyên bố không hợp lệ đối với Oracle –

+1

Bạn, thưa bạn, là chính xác. Giải pháp của tôi hoạt động trong SQL, không phải trong Oracle. Nếu bạn muốn nhân bản SQL's Identity trong Oracle, bạn sẽ muốn sử dụng Sequences [link] (http://www.techonthenet.com/oracle/sequences.php) @Justin_Cave có một thực thi tốt trong câu trả lời của mình. –

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