Foreign key data integrity violation on Oracle X 10g - oracle

I have an integration test running against either a MySQL instance or an Oracle instance.
The test passes fine when building the Maven project against the MySQL instance.
Here is the table structure:
drop table if exists operator;
create table operator (
id bigint(20) unsigned not null auto_increment,
version int(10) unsigned not null,
name varchar(50),
unique key name (name),
description varchar(255),
operator_id varchar(50),
unique key operator_id (operator_id),
image varchar(255),
url varchar(255),
country_id bigint(20) unsigned not null,
primary key (id),
unique key id (id),
key country_id (country_id),
constraint operator_fk1 foreign key (country_id) references country (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
But when the same test runs against the Oracle instance then it gives me the exception:
1. insert into operator (version, country_id, description, image, name, operator_id, url, id) values (0, 19, 'The SFR operator', 'sfr.jpg', 'SFR', NULL, 'sfr.fr', 10)
java.sql.SQLIntegrityConstraintViolationException: ORA-02291: integrity constraint (NITROPROJECT.OPERATOR_FK1) violated - parent key not found
Here is the table structure:
create table operator (
id number(10) not null,
version number(10) not null,
name varchar2(50),
constraint operator_u1 unique (name),
description varchar2(255),
operator_id varchar2(50),
constraint operator_u2 unique (operator_id),
image varchar2(255),
url varchar2(255),
country_id number(10) not null,
constraint operator_pk primary key (id),
constraint operator_fk1 foreign key (country_id) references country (id)
);
create sequence sq_id_operator increment by 1 start with 1 nomaxvalue nocycle cache 10;
create or replace trigger tr_id_inc_operator
before insert
on operator
for each row
declare
begin
if (:new.id is null)
then
select sq_id_operator.nextval into :new.id from dual;
end if;
end;
/
create table country (
id number(10) not null,
version number(10) not null,
code varchar2(4) not null,
constraint country_u1 unique (code),
name varchar2(50) not null,
list_order number(10),
constraint country_pk primary key (id)
);
create sequence sq_id_country increment by 1 start with 1 nomaxvalue nocycle cache 10;
create index country_i1 on country (list_order, name);
create or replace trigger tr_id_inc_country
before insert
on country
for each row
declare
begin
select sq_id_country.nextval into :new.id from dual;
end;
/
The country is created with the following service:
#Modifying
#Transactional(rollbackFor = EntityAlreadyExistsException.class)
#Override
public Country add(Country country) {
if (findByCode(country.getCode()) == null) {
// Save the returned id into the entity
country = countryRepository.saveAndFlush(country);
return country;
} else {
throw new EntityAlreadyExistsException();
}
}
I can see in the console log that the country is actually created and that its primary key id is returned:
2014-09-19 13:00:05,839 DEBUG [sqlonly] com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:147)
1. insert into country (version, code, list_order, name, id) values (0, 'fr', 1, 'France', 19)
In fact, I also added a finder call to make sure the country could be retrieved after it being created:
countryFR = new Country();
countryFR.setCode("fr");
countryFR.setName("France");
countryFR.setListOrder(1);
Country country = countryService.findByCode(countryFR.getCode());
if (country == null) {
countryFR = countryService.add(countryFR);
} else {
countryFR = country;
}
Country myc = countryService.findById(countryFR.getId());
if (myc != null) {
logger.debug("==============>> Found the country id: " + myc.getId());
}
And the console log does show the logger output:
2014-09-19 13:00:05,854 DEBUG [BTSControllerTest] ==============>> Found the country id: 19
NOTE: The console log does NOT show any select statement corresponding to that findById call.
And then comes the attempt to insert an operator:
1. insert into operator (version, country_id, description, image, name, operator_id, url, id) values (0, 19, 'The SFR operator', 'sfr.jpg', 'SFR', NULL, 'sfr.fr', 10)
You can see that the country id is the same as the one for the inserted country.
To sum things up:
The above note about the absence of select statement makes me wonder if the country was really inserted or not.
The primary key id of 19 retrieved after inserting the country leads me to think the country was actually inserted.
So how come Oracle complains it cannot find it for the operator foreign key ?
I'm using JPA2 hibernate-jpa-2.1-api 1.0.0.Final and spring-data-jpa 1.6.2.RELEASE and hibernate 4.3.6.Final
Here are the connection properties:
jpaPropertiesMap.put("hibernate.dialect", databaseProperties.getHibernateDialect());
jpaPropertiesMap.put("hibernate.show_sql", "true");
jpaPropertiesMap.put("hibernate.format_sql", "true");
jpaPropertiesMap.put("hibernate.hbm2ddl.auto", databaseProperties.getHibernateHbm2ddlAuto());
jpaPropertiesMap.put("hibernate.transaction.factory_class", "org.hibernate.transaction.JDBCTransactionFactory");
jpaPropertiesMap.put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
jpaPropertiesMap.put("hibernate.c3p0.min_size", "5");
jpaPropertiesMap.put("hibernate.c3p0.max_size", "20");
jpaPropertiesMap.put("hibernate.c3p0.timeout", "1000");
jpaPropertiesMap.put("hibernate.c3p0.max_statements", "50");
EDIT:
I added the following properties to the JPA setup:
jpaPropertiesMap.put("hibernate.connection.autocommit", "true");
jpaPropertiesMap.put("hibernate.cache.use_query_cache", "false");
jpaPropertiesMap.put("hibernate.cache.use_second_level_cache", "false");
But it didn't change anything in the issue.

I found the solution. My sequence trigger was missing an if statement. Now it has one as in: if (:new.id is null)
create or replace trigger tr_id_inc_country
before insert
on country
for each row
declare
begin
if (:new.id is null)
then
select sq_id_country.nextval into :new.id from dual;
end if;
end;
/
I suppose Hibernate was getting a sequence number for the insert, and then Oracle was getting another one at commit time. I'm just guessing here.

Related

Oracle fetch returns more than requested

So I've got another simple procedure with an error. This time, the fetch is returning more records than requested. I initially checked my query and found an error. My query returns the right results, but the fetch still won't work.
PROCEDURE:
--View Customer Service History
create or replace procedure SERVICEHISTORY(name in customer.name%type) is
carModel char(11);
serviceCharge decimal(7,2);
serviceName char(20);
serviceDate date;
cusName char(15);
cusID number;
--Query tested, it works
cursor nextService is
select name, workOrder.serviceDate, workOrderServices.actualCharge
from workOrder join workOrderServices on workOrder.workOrderID=workOrderServices.workOrderID join services on workOrderServices.serviceID=services.serviceID
where workOrderServices.customerID=cusID;
begin
--Get customer ID from name, another janky work around
select customerID
into cusID
from customer
where customer.name=name;
--Gets the car model
select model
into carModel
from vehicle
where vehicle.customerID=cusID;
open nextService;
fetch nextService into serviceName, serviceDate, serviceCharge;
if nextService%notfound then
dbms_output.put_line('No service history found.');
else
dbms_output.put_line('Service-------Date-------Cost');
loop
dbms_output.put_line(serviceName||' '||serviceDate||' '||serviceCharge);
fetch nextService into serviceName, serviceDate, serviceCharge;
if nextService%notfound then
dbms_output.put_line('Report finished.');
end if;
exit when nextService%notfound;
end loop;
end if;
close nextService;
end serviceHistory;
/
But it throws this error:
ERROR:
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at line 20
ORA-06512: at line 1
Here are the tables:
create table customer
(
customerID number(8) not null primary key constraint lengthCHK13 check(LENGTH(customerID)=8),
name varchar2(20) not null,
address varchar2(20) not null,
insurance varchar2(20) not null,
contactInfo number(10) not null,
customerType varchar2(15) not null,
licenseNumber varchar2(13) not null,
amountOwed decimal(7,2) not null constraint notNeg6 check(amountOwed >=0)
);
create table vehicle
(
--some error about no matching unique or primary key for this column on cusomterID
VIN varchar2(17) not null primary key constraint lengthCHK113 check(length(VIN)=17),
customerID number(8) not null references customer(customerID) constraint lengthCHK12 check(length(customerID)=8),
make varchar2(10) not null,
model varchar2(10) not null,
carYear number(4) not null,
color varchar2(10) not null,
notes varchar2(20),
currentMileage number(6) not null,
engineType varchar2(10) not null,
licenseNumber varchar(12) not null,
amountOwed decimal(7,2) constraint notNeg7 check(amountOwed >=0)
--primary key(VIN, customerID) DOESNT WORK BUT NEEDS TO
);
create table workOrder
(
workOrderID number(8) not null constraint lengthCHK10 check(length(workOrderID)=8),
VIN varchar2(17) not null references vehicle(VIN) constraint lengthCHK14 check(length(VIN)=17),
serviceDate date not null,
--Removing b/c it's a pain serviceTime TIME not null,
serviceBay number(2),
description varchar2(20) not null,
results varchar2(20) not null,
primary key(workOrderID)
);
create table services
(
serviceID number(8) not null primary key constraint lengthCHK17 check(length(serviceID)=8),
name varchar2(20) not null,
price decimal(7,2) not null constraint notNeg8 check(price >=0),
estimatedHours number(2) not null
);
create table workOrderServices
(
serviceID number(8) not null references services(serviceID) constraint lengthCHK20 check(length(serviceID)=8),
workOrderID number(8) not null references workOrder(workOrderID) constraint lengthCHK22 check(length(workOrderID)=8),
customerID number(8) not null references customer(customerID) constraint lengthCHK87 check(length(customerID)=8),
actualHours number(2) not null constraint notNeg11 check(actualHours >=0),
actualCharge decimal(7,2) not null constraint notNeg10 check(actualCharge >=0),
primary key(serviceID, workOrderID)
);
Test data:
INSERT INTO services(serviceID, name, price, estimatedHours)
VALUES(48937322, 'Tire Rotate', 19.99, 1);
INSERT INTO services(serviceID, name, price, estimatedHours)
VALUES(47873231, 'Xmission Flush', 63.99, 1);
INSERT INTO customer (customerID, name, address, insurance, contactInfo, customerType, licenseNumber, amountOwed)
VALUES (45124512, 'Bob Jones', '232 Sycamore Ln.', 'Pekin', 3095555145, 'New', 'SSSSFFFYYDDD', 220.00);
INSERT INTO customer (customerID, name, address, insurance, contactinfo, customertype, licensenumber, amountOwed)
VALUES (12892222, 'Mike Tyson','100 Haters Rd.', 'Progressive', 2175555555, 'Regular', 'FGHJHHHHTYYY', 42.00);
INSERT INTO vehicle(VIN, customerID, make, model, carYear, color, notes, currentMileage, engineType, licenseNumber, amountOwed)
VALUES('KNDKG3A31A7568300', 45124512, 'Ford', 'Focus', 2009, 'Red', 'side door damage', 10346, 'V4', 'h5303h87dk23', 0);
INSERT INTO vehicle(VIN, customerID, make, model, carYear, color, notes, currentMileage, engineType, licenseNumber, amountOwed)
VALUES('SALTW16413A376838', 12892222, 'Chrysler', 'Sebring', 2004, 'Green', 'Basically a Go-Kart', 105098, 'V4', 'r2345h23tx31', 0);
INSERT INTO workOrder( workOrderID, VIN, serviceDate, serviceBay, description, results)
VALUES(12312312, 'KNDKG3A31A7568300', '07-FEB-12', 2, 'Oil Change', 'Changed oil');
INSERT INTO workOrder( workOrderID, VIN, serviceDate, serviceBay, description, results)
VALUES(32132132, 'SALTW16413A376838', '07-FEB-12', 3,'Tire Rotation', 'Rotated the tires');
INSERT INTO workOrderServices(serviceID, workOrderID, customerID, actualHours, actualCharge)
VALUES(17278722, 12312312, 45124512, 5, 45.00);
INSERT INTO workOrderServices(serviceID, workOrderID, customerID,actualHours, actualCharge)
VALUES(48937322, 32132132, 12892222,10, 90.00);
If you had put some extra messaging into your code, as I did, you would have quickly discovered the source of the error.
create or replace procedure SERVICEHISTORY(name in customer.name%type) is
carModel char(11);
serviceCharge decimal(7,2);
serviceName char(20);
serviceDate date;
cusName char(15);
cusID number;
--Query tested, it works
cursor nextService is
select name, workOrder.serviceDate, workOrderServices.actualCharge
from workOrder
join workOrderServices
on workOrder.workOrderID=workOrderServices.workOrderID
join services on workOrderServices.serviceID=services.serviceID
where workOrderServices.customerID=cusID;
begin
dbms_output.put_line('Get customer ID from name, another janky work around');
select customerID
into cusID
from customer
where customer.name=name;
dbms_output.put_line('cusID='||cusID);
--Gets the car model
select model
into carModel
from vehicle
where vehicle.customerID=cusID;
dbms_output.put_line('carModel='||carModel);
open nextService;
fetch nextService into serviceName, serviceDate, serviceCharge;
if nextService%notfound then
dbms_output.put_line('No service history found.');
else
dbms_output.put_line('Service-------Date-------Cost');
loop
dbms_output.put_line(serviceName||' '||serviceDate||' '||serviceCharge);
fetch nextService into serviceName, serviceDate, serviceCharge;
if nextService%notfound then
dbms_output.put_line('Report finished.');
end if;
exit when nextService%notfound;
end loop;
end if;
close nextService;
end serviceHistory;
/
Here's my output:
SQL> exec SERVICEHISTORY(name=>'Bob Jones')
Get customer ID from name, another janky work around
BEGIN SERVICEHISTORY(name=>'Bob Jones'); END;
*
ERROR at line 1:
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at "APC.SERVICEHISTORY", line 23
ORA-06512: at line 1
It's the very first query which hurls. Why does it do that? Because you've given the parameter the same name as the column. In PL/SQL variable naming has scope, with the nearest declaration trumping further ones.
So in your query ...
select customerID
into cusID
from customer
where customer.name=name;
... Oracle interprets name on the right-hand side as being the column of the table, because that's the narrowest scope. Effectively your filter is where 1=1, which is no filter at all.
All you need to do to fix this is change the parameter to something like p_name and use that in your query instead...
SQL> exec SERVICEHISTORY(p_name=>'Mike Tyson')
Get customer ID from name, another janky work around
cusID=12892222
carModel=Sebring
Service-------Date-------Cost
Tire Rotate 07-FEB-12 90
Report finished.
PL/SQL procedure successfully completed.
SQL>
Of course, you will get the same error from the query on VEHICLE should you customer have more than one car, which the data model supports.
At the moment you don't use the result from that query, so the easiest fix would be to remove it. But probably you want to include it in the output, so the best solution might be to include VEHICLE in the main query.

Why it tell "invalid identifier (ORA-00904)"? when I call function in CONSTRAINT CHECK

This is some kind of study database in sql file. I use oracle 11g and process it in sqlplus.
I wrote two function for check the course number and the department number, so its depend on the major and the minor department of each student.
For example, I am student of CS department (major) and BIO department (minor), so I can not enroll the course which is about math department.
When I call it in CHECK but I don't know why it told that.
This is output when I create all table, (from sqlplus)
....
....
....
table created.
ALTER TABLE sections ADD CONSTRAINT CK_course_depart CHECK (FindMYDeparture(stuid,find_dno_from_cno(cno)) = 'true');
ERROR at line 1:
ORA-0094: "FIND_DNO_FROM_CNO":invalid identifier
This is in .sql file
DROP TABLE department CASCADE CONSTRAINTS;
CREATE TABLE department (
dnumber number(4) not null,
dname varchar(25) not null,
primary key (dnumber)
);
DROP TABLE courses CASCADE CONSTRAINTS;
CREATE TABLE courses (
cno number(4) not null,
cname varchar(15) not null,
credit number(1) not null,
dnumber number(4) not null,
primary key (cno),
foreign key (dnumber) references department(dnumber),
CONSTRAINT credits CHECK (credit > 0 AND credit <= 5)
);
DROP TABLE student CASCADE CONSTRAINTS;
CREATE TABLE student (
stuid char(9) not null,
fname varchar(15) not null,
lname varchar(15) not null,
dMjno number(4) not null,
dMnno number(4),
primary key (stuid),
CONSTRAINT depart_M_n CHECK (dMjno <> dMnno),
CONSTRAINT dMinor_check CHECK (dMnno = 1 OR dMnno = 2 OR dMnno = 3)
);
DROP TABLE sections CASCADE CONSTRAINTS;
CREATE TABLE sections (
sno number(4) not null,
cno number(4) not null,
stuid char(9) not null,
semester varchar(6) not null,
year varchar(4) not null,
instructor varchar(15) not null,
CONSTRAINT combine_pk primary key (sno,stuid),
foreign key (cno) references courses(cno),
foreign key (stuid) references student(stuid),
CONSTRAINT cant_enroll CHECK (semester <> 'Spring' AND year <> 2007)
);
DROP TABLE grading CASCADE CONSTRAINTS;
CREATE TABLE grading (
sno number(4) not null,
stuid char(9) not null,
grade numeric(1,2),
foreign key (sno,stuid) references sections(sno,stuid),
foreign key (stuid) references student(stuid),
CONSTRAINT grading_check CHECK (grade >= 0 AND grade <= 4)
);
DROP FUNCTION FindMYDeparture;
CREATE OR REPLACE FUNCTION FindMYDeparture(stuid_in IN char,depart_course IN NUMBER)
RETURN NUMBER AS
departMa_no NUMBER;
departMi_no NUMBER;
report varchar(10);
CURSOR cdno is
SELECT dMjno,dMnno FROM student WHERE stuid = stuid_in;
BEGIN
OPEN cdno;
LOOP
FETCH cdno INTO departMa_no,departMi_no;
IF (departMa_no = depart_course OR departMi_no = depart_course)
THEN
report := 'true';
EXIT;
ELSE
report := 'flase';
END IF;
EXIT WHEN cdno%NOTFOUND;
END LOOP;
CLOSE cdno;
RETURN report;
END;
/
DROP FUNCTION find_dno_from_cno;
CREATE OR REPLACE FUNCTION find_dno_from_cno(cno_in IN NUMBER)
RETURN NUMBER AS
depart_no NUMBER;
CURSOR cdno is
SELECT dnumber FROM courses WHERE cno = cno_in;
BEGIN
OPEN cdno;
FETCH cdno INTO depart_no;
CLOSE cdno;
RETURN depart_no;
END;
/
ALTER TABLE sections ADD CONSTRAINT CK_course_depart CHECK (FindMYDeparture(stuid,find_dno_from_cno(cno)) = 'true');
Not going to happen. You are not allowed to use your pl/sql functions in check constraint by design:
•Conditions of check constraints cannot contain the following
constructs:
•Subqueries and scalar subquery expressions
•Calls to the functions that are not deterministic (CURRENT_DATE,
CURRENT_TIMESTAMP, DBTIMEZONE, LOCALTIMESTAMP, SESSIONTIMEZONE,
SYSDATE, SYSTIMESTAMP, UID, USER, and USERENV)
•Calls to user-defined functions
•Dereferencing of REF columns (for example, using the DEREF function)
•Nested table columns or attributes
•The pseudocolumns CURRVAL, NEXTVAL, LEVEL, or ROWNUM
•Date constants that are not fully specified
http://docs.oracle.com/cd/B19306_01/server.102/b14200/clauses002.htm
Try running every statement in that function, This is the case of non existent column for a table or using a not existing row.

Error when creating a trigger in Oracle

Having hard time with creating a trigger. Here is my code. I create 2 tables:
CREATE TABLE client_table
(
clientid NUMBER(6) PRIMARY KEY,
lastname varchar2(50) NOT NULL,
firstname varchar2(50) NOT NULL,
password varchar2(20) NOT NULL,
email varchar2(100) NOT NULL,
phoneno NUMBER(12) NOT NULL,
zipcode NUMBER(6) NOT NULL ,
street varchar2(60) NOT NULL,
CHECK (email LIKE '%#%.%')
);
CREATE TABLE location_table
(
zipcode NUMBER(6) PRIMARY KEY,
country varchar2(100) NOT NULL,
region varchar2(60) NOT NULL,
town varchar2(60) NOT NULL
);
I add a constraint so that zipcode in client_table is a foreign key.
ALTER TABLE client_table
ADD CONSTRAINT clirefzip
FOREIGN KEY(zipcode) REFERENCES location_table(zipcode)
DEFERRABLE INITIALLY DEFERRED;
Now I want to add a trigger, so that when i delete a location from location_table, it will delete all clients from client_table, that have the same zipcode as the location deleted. So I try something like this:
CREATE OR REPLACE TRIGGER location_delete
AFTER DELETE ON location_table
REFERENCING OLD AS old_buffer
FOR EACH ROW
DELETE FROM client_table WHERE zipcode = old_buffer.zipcode;
Unfortunately it does not work.
Hi there has some syntactical errors in your code. I hope this code works . Thanks
CREATE OR REPLACE TRIGGER location_delete
AFTER DELETE ON location_table
--REFERENCING OLD AS old_buffer
FOR EACH ROW
begin
DELETE FROM client_table WHERE zipcode = zipcode;
end location_trigger;

updating create view - error ORA-01779:

I've used the CREATE VIEW command to create a view (obviously), and join multiple tables. The CREATE VIEW command works perfectly, but when I try to update the VIEW RentalInfoOct, I receive error "ORA-01779: cannot modify a column which maps to a non key-preserved table"
CREATE VIEW RentalInfoOct
(branch_no, branch_name, customer_no, customer_name, item_no, rental_date)
AS
SELECT i.branchNo, b.branchName, r.customerNo, c.customerName, i.itemNo, r.dateFrom
FROM item i
INNER JOIN rental r
ON i.itemNo = r.itemNo
INNER JOIN branch b
ON i.branchNo = b.branchNo
INNER JOIN customer c
ON r.customerNo = c.customerNo
WHERE r.dateFrom
BETWEEN to_date('10-01-2009','MM-DD-YYYY')
AND to_date('10-31-2009','MM-DD-YYYY')
My update command.
UPDATE RentalInfoOct
SET item_no = '3'
WHERE customer_name = 'April Alister'
AND branch_name = 'Kingsway'
AND rental_date = '10/28/2009'
I'm not sure if this will help in solving the problem, but here are my CREATE TABLE commands
CREATE TABLE Branch
(
branchNo SMALLINT NOT NULL,
branchName VARCHAR(20) NOT NULL,
branchAddress VARCHAR(40) NOT NULL,
PRIMARY KEY (BranchNo)
);
--Item Table Definition
CREATE TABLE Item
(
branchNo SMALLINT NOT NULL,
itemNo SMALLINT NOT NULL,
itemSize VARCHAR(8) NOT NULL,
price DECIMAL(6,2) NOT NULL,
PRIMARY KEY (ItemNo, BranchNo),
FOREIGN KEY (BranchNo) REFERENCES Branch ON DELETE CASCADE,
CONSTRAINT VALIDAMT
CHECK (price > 0)
);
-- Customer Table Definition
CREATE TABLE Customer
(
customerNo SMALLINT NOT NULL,
customerName VARCHAR(15) NOT NULL,
customerAddress VARCHAR(40) NOT NULL,
customerTel VARCHAR(10),
PRIMARY KEY (CustomerNo)
);
-- Rental Table Definition
CREATE TABLE Rental
(
branchNo SMALLINT NOT NULL,
customerNo SMALLINT NOT NULL,
dateFrom DATE NOT NULL,
dateTo DATE,
itemNo SMALLINT NOT NULL,
PRIMARY KEY (BranchNo, CustomerNo, dateFrom),
FOREIGN KEY (BranchNo) REFERENCES Branch(BranchNo) ON DELETE CASCADE,
FOREIGN KEY (CustomerNo) REFERENCES Customer(CustomerNo) ON DELETE CASCADE,
CONSTRAINT CORRECTDATES CHECK (dateTo > dateFrom OR dateTo IS NULL)
);
See: Oracle: multiple table updates => ORA-01779: cannot modify a column which maps to a non key-preserved table
You're attempting to update a view with joins, but the join conditions are not based on a uniqueness constraint, which creates the possibility of multiple rows that are created from a single row in one table.
It seems like you need a Unique Key - Foreign Key relationship between the columns your join condition is based on.
EDIT: I just saw your edit. Changing r.branchNo = b.branchNo to i.branchNo = b.branchNo should go a long way. Not sure how well r.customerNo = c.customerNo will work out.

oracle change a column to unique

Table has been created in system this way
CREATE TABLE INSTANCES
(
DM INTEGER NOT NULL,
INSTANCEID VARCHAR2(512) NOT NULL,
INSTANCENAME VARCHAR2(64) NOT NULL UNIQUE,
HOSTNAME VARCHAR2(32) NOT NULL,
CONSTRAINT PK_INSTANCES PRIMARY KEY (INSTANCEID, HOSTNAME)
);
The new crete table statement is as below:
CREATE TABLE INSTANCES
(
DM INTEGER NOT NULL,
INSTANCEID VARCHAR2(512) NOT NULL UNIQUE,
INSTANCENAME VARCHAR2(64) NOT NULL UNIQUE,
HOSTNAME VARCHAR2(32) NOT NULL,
CONSTRAINT PK_INSTANCES PRIMARY KEY (INSTANCEID, HOSTNAME)
);
The differnce is INSTANCEID has UNIQUE in it. How do i Alter the table? I used the below statement and it did not work for me.
ALTER TABLE INSTANCES ADD CONSTRAINT ab UNIQUE ( INSTANCEID);
It gave an error:
ALTER TABLE INSTANCES ADD CONSTRAINT ab UNIQUE ( INSTANCEID)
Error report:
SQL Error: ORA-02261: such unique or primary key already exists in the table
02261. 00000 - "such unique or primary key already exists in the table"
*Cause: Self-evident.
*Action: Remove the extra key.
Please help me to Alter the table as required above. Thanks!
Here is the output of SELECT con.constraint_name, col.column_name, con.constraint_type
FROM user_cons_columns col
JOIN user_constraints con ON (col.constraint_name = con.constraint_name)
WHERE col.table_name = 'INSTANCES';
"CONSTRAINT_NAME","COLUMN_NAME","CONSTRAINT_TYPE"
"SYS_C0016531","DM","C"
"SYS_C0016532","INSTANCEID","C"
"SYS_C0016533","INSTANCENAME","C"
"SYS_C0016534","HOSTNAME","C"
"PK_INSTANCES","HOSTNAME","P"
"PK_INSTANCES","INSTANCEID","P"
"SYS_C0016536","INSTANCENAME","U"
You have already stated that INSTANCEID is supposed to be UNIQUE, so a constraint has been created.
CREATE TABLE INSTANCES
(
DM INTEGER NOT NULL,
INSTANCEID VARCHAR2(512) NOT NULL UNIQUE, -- UNIQUE constraint
INSTANCENAME VARCHAR2(64) NOT NULL UNIQUE,
HOSTNAME VARCHAR2(32) NOT NULL,
CONSTRAINT PK_INSTANCES PRIMARY KEY (INSTANCEID, HOSTNAME)
);
Edit: Ok, after reading your comment, try this:
SELECT con.constraint_name, col.column_name, con.constraint_type
FROM user_cons_columns col
JOIN user_constraints con ON (col.constraint_name = con.constraint_name)
WHERE col.table_name = 'INSTANCES'
AND con.constraint_type = 'U'
;
It will list UNIQUE constraints and associated columns for INSTANCE table. Please check if there is a unique constraint on the INSTANCEID column (and if that constraint has no other associated columns).
Example at SQLFiddle: http://sqlfiddle.com/#!4/43b43/6
Edit #2: creating named constraints, all options:
-- CREATE TABLE - "In Line" Constraints
CREATE TABLE ports (
ID NUMBER CONSTRAINT PORT_ID_PK PRIMARY KEY,
NAME VARCHAR2(20)
);
CREATE TABLE ports (
ID NUMBER,
NAME VARCHAR2(20) CONSTRAINT NAME_NN NOT NULL
);
CREATE TABLE ports (
ID NUMBER,
NAME VARCHAR2(20) CONSTRAINT NAME_UQ UNIQUE
);
CREATE TABLE ports (
ID NUMBER,
STATUS NUMBER CONSTRAINT PROPER_STATUS_CK
CHECK (STATUS IN (4, 5))
);
CREATE TABLE ships (
SHIP_ID NUMBER,
NAME VARCHAR2(20),
HOME_PORT_ID NUMBER CONSTRAINT SHIP_PORT_FK
REFERENCES PORTS (ID)
);
-- CREATE TABLE - "Out of Line" Constraints
CREATE TABLE ports (
ID NUMBER,
NAME VARCHAR2(20),
CONSTRAINT PORT_ID_PK PRIMARY KEY (ID)
);
-- NOT NULL constraints can not be created "Out of Line"!
CREATE TABLE ports (
ID NUMBER,
NAME VARCHAR2(20),
CONSTRAINT NAME_UQ UNIQUE (NAME)
);
CREATE TABLE ports (
ID NUMBER,
STATUS NUMBER,
CONSTRAINT PROPER_STATUS_CK
CHECK (STATUS IN (4, 5))
);
CREATE TABLE ships (
SHIP_ID NUMBER,
NAME VARCHAR2(20),
HOME_PORT_ID NUMBER,
CONSTRAINT SHIP_PORT_FK FOREIGN KEY
(HOME_PORT_ID) REFERENCES PORTS (ID)
);
-- ALTER TABLE - "In Line" Constraints
ALTER TABLE PORTS MODIFY ID
CONSTRAINT PORT_ID_PK PRIMARY KEY;
ALTER TABLE PORTS MODIFY NAME
CONSTRAINT NAME_NN NOT NULL;
ALTER TABLE PORTS MODIFY NAME
CONSTRAINT NAME_UQ UNIQUE;
ALTER TABLE SHIPS MODIFY HOME_PORT_ID
CONSTRAINT SHIP_PORT_FK REFERENCES PORTS (ID);
-- ALTER TABLE - "Out of Line" Constraints
ALTER TABLE PORTS ADD CONSTRAINT
PORT_ID_PK PRIMARY KEY (ID);
-- NOT NULL constraints can not be created "Out of Line"!
ALTER TABLE PORTS ADD CONSTRAINT
NAME_UQ UNIQUE (NAME);
ALTER TABLE PORTS ADD
CONSTRAINT PROPER_STATUS_CK
CHECK (STATUS IN (4, 5));
ALTER TABLE SHIPS ADD CONSTRAINT SHIP_PORT_FK
FOREIGN KEY (HOME_PORT_ID)
REFERENCES PORTS (ID);
NOT NULL constraints cannot be create of out line.

Resources