How i can solve ORACLE problem in foreign key - oracle

I have a problem in oracle and I need help. I have the following query:
1 CREATE TABLE TEST1 (
2 NAME VARCHAR(20)
3 ID VAR(9)
4 PRIMARY KEY(ID)
5 FOREIGN KEY(NAME) References TEST2(ANAME)
6 ON DELETE CASCADE ON UPDATE SET NULL );
If I want to delete line #6 what should i do?

"How I can change the value of primary key and based of that the foreign keys of this pk will change too?"
First, you should never need to do that. Primary keys like this are really just numbers that identify a row, they have no meaning in themselves. It's like asking how you would change the ROWID of a row.
If you must, you could:
Find the foreign keys pointing to this table and disable them with ALTER CONSTRAINT myconstraint DISABLE
Update your primary table and catch the new id value with UPDATE test1 SET id = mysequence.NEXTVAL WHERE id = :oldid RETURNING id INTO :newid, assuming it's set by a sequence.
Update the ids in your other tables with the new id.
Reenable your constraints.
Note that altering constraints is DDL and will do an implicit commit and this approach will leave your tables unprotected by the foreign key constraints.
A second approach would be to:
Insert a new row in the primary table and catch the new id.
Update the id in the foreign tables with the new id.
Delete the old row in the primary table.
Now that I think about it, that second approach seems better to me. No DDL and it just seems cleaner.

Related

how to add sequence to primary key in plSQL

I'm using pl sql developer 12.what i want is to add the make the primary key sequential using oracle 12' windows and forms , not by scripting. I can't find out how?.
aslo, how can i make one to one relation between 2 tables (user,role), in user table i added role_id as foreign key; but the relation seem one to many!!!
In Oracle 12c and above, you define that column as identity columns:
CREATE TABLE mytable (
id NUMBER GENERATED ALWAYS AS IDENTITY,
-- other columns ...
);
A #Mureinik already said, in Oracle 12 and higher versions you can define your primary key column as NUMBER GENERATED ALWAYS AS IDENTITY to get a unique sequential value.
To enforce a one-to-one relationship in the database you'd want to have your ROLE_ID column defined as a primary key on one table, and as either a UNIQUE or PRIMARY key on the second table, with a foreign key relationship between the tables. In other words:
CREATE TABLE T1 (ROLE_ID NUMBER
CONSTRAINT PK_T1
PRIMARY KEY
...);
CREATE TABLE T2 (ID_T2 NUMBER
PRIMARY KEY,
ROLE_ID NUMBER
CONSTRAINT T2_U1
UNIQUE
CONSTRAINT T2_FK1
REFERENCES T1(ROLE_ID)
ON DELETE CASCADE,
...);
After the above ROLE_ID will be the primary key on T1, a unique key on T2, and T2.ROLE_ID will be a foreign key to T1.
Best of luck.
what I have done lastly is that i downloaded sql developer 64 w, and from it; I connected with the database then I made the column sequential

ORA-00955 "name is already used by an existing object"

I need to modify an existing PK. Therefore I drop an recreate it.
ALTER TABLE B DROP CONSTRAINT PK_B;
ALTER TABLE B ADD CONSTRAINT PK_B PRIMARY KEY ("TYP", "NR", "HH", "QUART");
Unfortunately the last Statement will give me an error ORA-00955
If I create the PK constraint like it was defined originally with:
ALTER TABLE B ADD CONSTRAINT PK_B PRIMARY KEY ("TYP", "NR", "HH");
everything works fine.
Perhaps there is an INDEX associated with the PRIMARY KEY CONSTRAINT, and it is also named as PK_B.
You can check it as :
SELECT * FROM USER_INDEXES WHERE TABLE_NAME='<table_name>';
If that's true, then do :
ALTER INDEX "PK_B" RENAME TO "PK_XYZ";
Update : Regarding ALTER INDEX statement, few important points as mentioned by Justin in the comments
Oracle implicitly creates an UNIQUE index to support the PRIMARY KEY CONSTRAINT. Since, the index is of the same name that of the primary key, and now that the primary key is being modified, it is better to drop and re-create the index again as per the definition of the old primary key.
My conclusion :
The primary key constraint is enforced through a unique index.
If Oracle already finds an index – unique or non-unique – it uses it
for the primary key.
If the index was initially created as non-unique, it will continue to
show as non-unique, however it will actually be a unique index.
A good demonstration and quite detailed on other aspects too, by Arup : Primary Keys Guarantee Uniqueness? Think Again.
I had the same issue where I had to do the following to delete reference to a table from the view whilst recreating the database from the scratch. I was searching for the same in tables and indexes first.
connect sys/oracle as sysdba;
select * from all_tables
select * from all_indexes
(finally located the reference in the views)
select * from all_views where view_name like '%WKSTSTATE%';
drop view RUEGEN.WKSTSTATE;

Oracle Partial Foreign Key that is not unique

I have some problems with Oracle Foreign Composite keys. I have an application that is somewhat big (you know, 5000+ tables, that kind of thing) and we store some 'static' (it actually can change) data into some set of tables. This data is referenced by a lot of the tables through the database, so it worked like this:
TABLE StaticData
ID(PK) Data
1 StaticData1
2 StaticData2
...
n StaticDataN
TABLE TypicalTable
ID(PK) StaticDataID(FK to StaticData)
1 1
2 1
3 7
4 2
...
n n
And all was well in Wonderland.
But some changes of spec, and some meetings with the client after, we were tasked with having different 'versions' of the data ready to replace the static data when some time arrives. Last part was easy, we can create jobs that will check every day/week for a date and change the data, but we will have to maintain older and newer versions of the data... in the same table. So now StaticData looks like:
TABLE StaticData
ID(PK) Data KickInDate(Also PK)
1 StaticData1.1 01/01/1900
1 StaticData1.2 10/07/2014
1 StaticData1.3 12/12/2015
2 StaticData2.1 01/01/1900
...
n StaticDataN.1 01/01/1900
And of course all integrity reference has gone off the board. And of course, since I cannot put a UNIQUE constraint in the ID, I cannot keep the foreign keys.
I have searched the net for a solution for this (less restrictive kind of foreign keys) and most of the time the solution is to use triggers checking BEFORE INSERT|UPDATE|DELETE
But that will be kind of a very, very, very big job.
So I ask, Do I have other solutions?
Is there any way to tell Oracle to reference another column of another table even thought is not UNIQUE? (it will definitely be NOT NULL).
Primary keys in Oracle can have duplicates. Primary keys can be built with non-unique indexes and existing values can be excluded by creating the constraint with NOVALIDATE. It is a rarely used feature, will confuse people, and is not a clean solution. But in the real world sometimes data isn't clean and there's no time for the perfect solution.
Sample schema and data.
create table staticData
(
id number not null,
data varchar2(100),
constraint staticData_pk primary key (id)
);
create table typicalTable
(
id number not null,
staticDataID number,
constraint typicalTable_pk primary key (id),
constraint typicalTable_fk foreign key (staticDataID)
references staticData(id)
);
insert into staticData values (1, 'StaticData1');
insert into staticData values (2, 'StaticData2');
insert into typicalTable values(1, 1);
insert into typicalTable values(2, 1);
Process to drop constraints, add duplicate data, and re-enable constraints.
--Drop constraints.
alter table typicalTable drop constraint typicalTable_fk;
alter table staticData drop constraint staticData_pk;
--Add semi-duplicate data.
insert into staticData values (1, 'StaticData1.2');
--Use a non-unique index to build a NOVALIDATE primary key.
create index staticData_pk on staticData(id);
alter table staticData add constraint staticData_pk primary key (id) novalidate;
alter table typicalTable add constraint typicalTable_fk foreign key(staticDataID)
references staticData(id);
No, the target column(s) must be unique, that's the whole idea. However, you can propagate an additional version column from StaticData to TypicalTable:
CREATE TABLE StaticData (
id NUMBER,
version NUMBER,
col1 ... coln,
PRIMARY KEY (id,version)
);
CREATE TABLE TypicalTable (
StaticDataID NUMBER,
version NUMBER,
colx ... coly,
FOREIGN KEY (StaticDataID, version) REFERENCES StaticData(id, version)
);

Foreign Keys or Delete Trigger?

The tables:
SIGN_OBJECT:
ID VARCHAR2(32) PRIMARY KEY,
DESCRIPTION VARCHAR2(100),
X NUMBER(10,3),
Y NUMBER(10,3),
...
GEOMETRYID VARCHAR2(32)
LAMPPOST_OBJECT:
ID VARCHAR2(32) PRIMARY KEY,
DESCRIPTION VARCHAR2(100),
X NUMBER(10,3),
Y NUMBER(10,3),
...
GEOMETRYID VARCHAR2(32)
OBJGEOMETRY:
GEOMETRYID VARCHAR2(32) PRIMARY KEY,
GEOMETRY MDSYS.SDO_GEOMETRY,
...
There are many X_OBJECT tables. Unfortunately the schema designers (in their infinite wisdom) didn't see any crossover between the various object types. I am unable to change these tables without creating much more work.
For each object table there is a trigger that creates the relevant SDO_GEOMETRY value BEFORE insert or update ( GEOMETRYID is unique - it comes from a sequence ). At the moment the trigger calls a package function which inserts the OBJGEOMETRY record and returns the geometryid.
The problem is that if the parent record is deleted I would like the OBJGEOMETRY child record to be also deleted.
Initially I thought this could be done with Foreign Keys cascade delete, but of course the FK requires a Primary Key in the parent table - obviously this won't work.
However, I discovered that actually a FK requires a unique constraint in the parent table. I can make X_OBJECT.GEOMETRYID unique but then I'm finding issues because that GEOMETRYID isn't yet populated in the parent table but the FK requires it exists. I cannot do that inside the trigger ( by setting :NEW.GEOMETRYID ) so do I have to write the GEOMETRYID first and then commit? I'm not sure and this has bad code smell.
So am I wrong? Is this a more suitable case for a delete trigger? or is there something I'm missing.
Thanks.
If you insert both the OBJGEOMETRY and the X_OBJECT rows in the same transaction, then you can set the FK to DEFERRABLE INITIALLY DEFERRED.
In that case it will be evaluated at COMMIT time, not when you run the INSERT statement.
The triggers should fire before insert or update, not after. Then you can set :NEW.GEOMETRYID with the value returned by your package.
Besides, the foreign keys point the wrong way. It should be
ALTER TABLE x_OBJECT ADD FOREIGN KEY (geometryid) REFERENCES objgeometry(geometryid);
Therefore, you'll need a delete trigger...

update primary key in oracle

i have table. which has 5 columns in that 3 of the columns makes primary key combinations.
table (cola, colb, colc, cold, cole)
i want to update one of the column which is in primary key group. how to do that?
its giving primary key constraint error.
You should disable do your modification an re enable the constraints that are linked to your primary key. (Unique, non-null, etc...)
Take a look at this website
If you really need to maintain uniqueness over these three columns, then define a unique constraint on the three columns making up your current PK, and then define a new surrogate primary key column.
Just in case you have to change the referncing data too.
First note contrary to MS-SQL-Server there is no foreign Key contraint with on update cascade see How to create a Foreign Key with “ON UPDATE CASCADE” on Oracle?.
Than I would insert a new row in the primary table, update the referencing table to reference the new row and finally delete the original primary row.

Resources