Oracle unique constraint error message - oracle

I am maintaining a legacy application and I recently got contacted that people are getting an error message when they try to fill one of our oracle tables. Now, those oracle tables are not in our care, but I still want to try out something to help find the problem.
Anyway, the error message is the following:
java.sql.SQLException: ORA-00001: unique constraint (REO0.PK_TableName) violated :
I know I can find a lot of information online through google and here about this error message. That is not what my question is about.
The question is: the tablename shown here (which I put in bold), is that
the name of the table, or is the
PK_ part added to represent 'primary key' ?
Reason why I ask is: I can't directly get to this database, but somehow I can see all tables in REO0 and I can find one with TableName but not one with *PK_TableName* as the name for a table. So if this PK_ would refer to something like 'primary key' (which the constraint of is violated) then it would make a bit more sense.

PK_tablename is the name of the constraint, and as Alex Poole states in a good comment, it has been specified in the DDL (CREATE TABLE ... (columns, CONSTRAINT PK_tablename PRIMARY KEY(columns...) ), or ALTER TABLE ... ADD CONSTRAINT PK_tablename PRIMARY KEY(columns...) or CREATE UNIQUE INDEX PK_tablename ON ... (columns) for example). When no name has been given, Oracle generates a name which begins with SYS.
Note that usually PK_x suggests a primary key for table x, but your constraint might also be a foreign key constraint or a not null constraint for example.
The following query will tell you all:
SELECT * FROM all_constraints WHERE constraint_name = 'PK_TABLENAME'

Related

Oracle - Why must constraint_name be unique if owned by a different schema?

In Oracle, if you try to explicitly define the schema for a constraint in a CREATE TABLE statement it will result in a ORA-00904: : invalid identifier error:
CREATE TABLE SCHEMA1.MY_TABLE
(
TABLE_ID NUMBER(5)
, FLAG VARCHAR2(1) DEFAULT 'F'
, CONSTRAINT SCHEMA1.MY_TABLE_PK PRIMARY KEY (TABLE_ID) -- Parser doesn't like 'SCHEMA1'
, CONSTRAINT SCHEMA1.MY_TABLE_FLAG_CK CHECK (FLAG IN ('T', 'F')) --Same issue
);
This is no big deal because the constraint OWNER defaults to the same schema as defined in the CREATE TABLE declaration (or at least in the schema you are signed into - my accounts don't have the rights to validate). This can be confirmed by pulling up the constraint in ALL_CONSTRAINTS or DBA_CONSTRAINTS and viewing the OWNER value (which would read SCHEMA1 for the two constraints above).
But if you then follow up this statement with a second duplicate statement under a different schema:
CREATE TABLE SCHEMA2.MY_TABLE
(
TABLE_ID NUMBER(5)
, FLAG VARCHAR2(1) DEFAULT 'F'
, CONSTRAINT MY_TABLE_PK PRIMARY KEY (TABLE_ID) --This constraint already exists
, CONSTRAINT MY_TABLE_FLAG_CK CHECK (FLAG IN ('T', 'F')) --This one too
);
this results in an ORA-00955: name is already used by an existing object error.
My understanding of constraints are that they are just another object on the database which I would have assumed were subject to the same ownership rules with which I'm familiar. But based on the behavior above it is clear that they do not behave like most objects on the database.
Questions
What is it about constraints that requires their names be unique across all schemas (unlike other objects on the database)?
Does anyone know the technical reason for this naming requirement?
For context, I've run into a scenario at work where I had wanted to store duplicate names under different schemas (don't ask... it was inherited duplication and I'm just trying to stay consistent until I have funding to refactor). Now, I realize that I can very simply add the schema to the name and bypass this problem quickly but this rubs my OCD the wrong way so I'd like to better understand just why I can't do what I'm trying to do.
----------------------------- UPDATE ---------------------------
Okay... so I'm a fool. Please note that the above scenario cannot be repeated given a clean environment. After trying to reproduce the issue, I now realize what happened.
I'm currently working on cleaning up some DDL statements in preparation for a production release. I'm not the only developer in this environment and my offshore team has been working on these same tables. I have been editing some preexisting DDL scripts in preparation for a production release and had added some needed constraints to a few CREATE TABLE statements.
It would appear that I had failed to run my DROP scripts before running the second statement in SCHEMA2. My confusion was due to thinking that I was getting the ORA-00955 error because of the new constraints I was adding when in actuality it was because the SCHEMA2.MY_TABLE already existed in this environment. This misdiagnosis was compounded by me changing my constraint names and then rerunning all of my scripts successfully (as I must have run my DROP statements in all schemas before retesting). As a result I thought that I had observed unforeseen behavior when I really had not.
Thank you to everyone who commented for showing me the light!
What's missing in your question is the user under which you run the script. But here's a little experiment.
Connected to the database as user system. I have schemas NGM42 and NGM41 available for the experiment.
CREATE TABLE NGM41.MY_TABLE
(
TABLE_ID NUMBER(5)
, FLAG VARCHAR2(1) DEFAULT 'F'
, CONSTRAINT MY_TABLE_PK PRIMARY KEY (TABLE_ID) -- Parser doesn't like 'SCHEMA1'
, CONSTRAINT MY_TABLE_FLAG_CK CHECK (FLAG IN ('T', 'F')) --Same issue
);
CREATE TABLE NGM42.MY_TABLE
(
TABLE_ID NUMBER(5)
, FLAG VARCHAR2(1) DEFAULT 'F'
, CONSTRAINT MY_TABLE_PK PRIMARY KEY (TABLE_ID)
, CONSTRAINT MY_TABLE_FLAG_CK CHECK (FLAG IN ('T', 'F'))
);
Both statements run succesfully. So what happened to the constraints?
select owner,constraint_name from all_constraints
where constraint_name in ('MY_TABLE_PK','MY_TABLE_FLAG_CK')
NGM42 MY_TABLE_PK
NGM41 MY_TABLE_PK
NGM41 MY_TABLE_FLAG_CK
NGM42 MY_TABLE_FLAG_CK
The constraints are created in the same schema as the table. As you can see they do not need to be globally unique in the database.

Enforcement of unique/primary key - drop index

I am trying to drop an index :
DROP INDEX PK_CHARGES
but I get this error
cannot drop index used for enforcement of unique/primary key
Why I am getting this error? I will provide further information if you need any.
How to solve it?
Edit I have no primary key in the table, but I found this weird index that I don't remember I had added:
index name = SYS_C0040476 which have the same columns
You can query the ALL_CONSTRAINTS performance view to see which constraint the index is used by, and which table it applies to, e.g:
select owner, constraint_name, constraint_type,
table_name, index_owner, index_name
from all_constraints
where index_name = 'PK_CHARGES';
I would expect the table name to be 'CHARGES', the constraint name to match the index name, and the constraint type to be 'P'. But since you have a table in mind, perhaps the names aren't following a helpful convention. Maybe an old version of the table was renamed, which would leave the constraints against the new name (e.g. CHARGES_BACKUP or something).
You said you click on the table, then on the view. Perhaps you're not looking at the table that the constraint/index is on; or perhaps you're looking at a view on top of the actual table. You also mention a SYS_ index on the same columns - which can't be on the same table. Do you have multiple similar tables, or access to multiple schemas? You shold run the above query for that index too. As mentions above, you might find an old version (or versions) of the table.
Once you've identified which table the constraint is on, you'll need to decide whether you should actually be keeping it, and if not you can remove it by dropping the constraint with an ALTER TABLE command.
The problem with
But I found this weird index that I dont rember I hadve add
comes because you didn't add it. You had a primary key, then you dropped it, but when you do that Oracle doesn't drop the associated unique index that every primary key has.
So when you drop a primary key you have to drop the unique index of that primary key, that amazingly has the same name as the primary key had.
So for dropping a MY_TABLE_PK you must do:
ALTER TABLE MY_TABLE DROP PRIMARY KEY DROP INDEX;
so you ensure that the index is dropped as well.
"from pl/sql I right click on the table"
The problem with IDEs is that they make us feel very productive, because we can do things with just a click instead of writing some code. This is a problem because when something unusual happens the IDE is no good for investigation and we lack the understanding of the underlying structure of the database which we need to help ourselves.
If you want to learn the Oracle database the worst thing you can do is download SQL Developer or PLSQL Developer or TOAD. They're all fine tools but the only people who should use them are the people who don't need to use them.
the following worked for me with unique index:
ALTER INDEX UX_CHARGES UNUSABLE
/
DROP INDEX UX_CHARGES
/
see: https://docs.oracle.com/cd/E18283_01/server.112/e17120/indexes004.htm#insertedID3

Using sql oracle to add a foreign key

I'm trying to add a key from my customer table to my reservation table in oracle.
However I keep getting an error message when I try to run my SQL commands which states 'Customer_ID is an invalid identifier'.
What I am trying to do is first use an alter statement to alter the reservation table.
Then I am adding a foreign key, which is called 'Customer_ID'
Then I enter a references statement, which tells it that I am getting the CUSTOMER_ID attribute from the customer table. However to sql this doesn't make sense at all.
To me, logically it makes sense, I don't see anything wrong with the syntax or structure of the statements. Any sharp eyes/minds to help me on this matter would be greatly appreciated.
the statements used are:
ALTER TABLE reservation
ADD FOREIGN KEY (Customer_ID)
REFERENCES Customer(Customer_ID);
There's nothing wrong with your syntax; I was able to create simple one-column tables with the appropriate names then execute exactly the statement you posted. So I suspect the column CUSTOMER_ID does not exist in one or the other table. Describe the two tables and double-check the column names. Keep in mind that normally column names in Oracle are case-insensitive, but they can be case-sensitive if enclosed in double quotes; this can be a reason for a non-obvious column name mismatch.

Oracle unique constraint violation referencing a constraint that doesn't seem to exist

I'm receiving an error that I can't make sense of. The error is pretty straightforward:
ORA-00001: unique constraint (*schema*.*xyz_constraint*) violated
However, what's causing my confusion is the fact that no such constraint seems to exist. It's certainly not defined on the table; the DB in question has almost no referential integrity defined, and the particular table into which I'm inserting data has no key defined.
For what it's worth, I can't find the constraint anywhere in the database:
select *
from all_constraints
where constraint_name like '%xyz_constraint%'
Is there anything I'm overlooking? Thanks.
I had the exact same error and it was not a permissions issue. Rather, the entity turned out to be an INDEX not a CONSTRAINT and I found it with:
SELECT * FROM ALL_INDEXES WHERE INDEX_NAME LIKE '%XYZ_UK1'
...because it did not exist in ALL_CONSTRAINTS or DBA_CONSTRAINTS. Confusing how the error message is the same. I'm running Oracle 11g.
This happens when the constraint belongs to another user and you don't have permissions to it.
Try looking it once again for now from SYS perspective
Schema object names are almost always stored in upper-case. Try
select *
from all_constraints
where constraint_name like '%XYZ_CONSTRAINT%'
ORA-00001 usually happens for duplicate primary keys. Are you sure you don't have one on the table?

Create constraint in alter table without checking existing data

I'm trying to create a constraint on the OE.PRODUCT_INFORMATION table which is delivered with Oracle 11g R2.
The constraint should make the PRODUCT_NAME unique.
I've tried it with the following statement:
ALTER TABLE PRODUCT_INFORMATION
ADD CONSTRAINT PRINF_NAME_UNIQUE UNIQUE (PRODUCT_NAME);
The problem is, that in the OE.PRODUCT_INFORMATION there are already product names which currently exist more than twice.
Executing the code above throws the following error:
an alter table validating constraint failed because the table has
duplicate key values.
Is there a possibility that a new created constraint won't be used on existing table data?
I've already tried the DISABLED keyword. But when I enable the constraint then I receive the same error message.
You can certainly create a constraint which will validate any newly inserted or updated records, but which will not be validated against old existing data, using the NOVALIDATE keyword, e.g.:
ALTER TABLE PRODUCT_INFORMATION
ADD CONSTRAINT PRINF_NAME_UNIQUE UNIQUE (PRODUCT_NAME)
NOVALIDATE;
If there is no index on the column, this command will create a non-unique index on the column.
If you are looking to enforce some sort of uniqueness for all future entries whilst keeping your current duplicates you cannot use a UNIQUE constraint.
You could use a trigger on the table to check the value to be inserted against the current table values and if it already exists, prevent the insert.
http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14251/adfns_triggers.htm
or you could just remove the duplicate values and then enfoce your UNIQUE constraint.
EDIT: After Jonearles and Jeffrey Kemp's comments, I'll add that you can actually enable a unique constraint on a table with duplicate values present using the NOVALIDATE clause but you'd not be able to have a unique index on that constrained column.
See Tom Kyte's explanation here.
However, I would still worry about how obvious the intent was to future people who have to support the database. From a support perspective, it'd be more obvious to either remove the duplicates or use the trigger to make your intent clear.
YMMV
You can use deferrable .
ALTER TABLE PRODUCT_INFORMATION
ADD CONSTRAINT PRINF_NAME_UNIQUE UNIQUE (PRODUCT_NAME)
deferrable initially deferred NOVALIDATE;

Resources