I am trying to make foreign key connections between flat and nested tables in SQL Developer.
Scenario One:
Flat table to Nested table using a foreign key connection.
In this scenario, I want to connect the flat table "GRANPARENT_TABLE" directly with the table "CHILD_TABLE", which "CHILD_TABLE" is nested to "PARENT_TABLE".
First I create the nested table "CHILD_TABLE" INSIDE the table "PARENT_TABLE"
CREATE TYPE CHILD_OBJECT AS OBJECT(
CHILD_ID NUMBER
);
CREATE TYPE CHILD_TYPE IS TABLE OF CHILD_OBJECT;
CREATE TABLE PARENT_TABLE (
PARENT_ID NUMBER,
CHILD CHILD_TYPE
)NESTED TABLE CHILD STORE AS CHILD_TABLE;
After creating the tables "PARENT_TABLE" and "CHILD_TABLE",
I declare a primary key to the nested table "CHILD_TABLE"
ALTER TABLE CHILD_TABLE
ADD CONSTRAINT CHILD_TABLE_PK PRIMARY KEY (CHILD_ID);
Finally, I create the "GRANDPARENT_TABLE" and at the same time I make the foreign key connection
between the flat table "GRANDPARENT_TABLE" and the nested table "CHILD_TABLE".
CREATE TABLE GRANDPARENT_TABLE(
GRANDPARENT_ID NUMBER,
CHILD_ID NUMBER,
CONSTRAINT GRANDPARENT_TO_CHILD FOREIGN KEY (CHILD_ID) REFERENCES CHILD_TABLE(CHILD_ID)
);
The result of the above scenario is the successful creation of the foreign key connection,
as shown below:
Flat table to Nested table foreign key connection
So far, so good.
Scenario Two:
Nested table to Flat table using a foreign key connection.
In this scenario, I want to connect the nested table "CHILD_TABLE", which is inside the table "PARENT_TABLE", directly with the flat table "GRANDPARENT_TABLE".
First I create the flat table "GRANDPARENT_TABLE"
CREATE TABLE GRANDPARENT_TABLE(
GRANDPARENT_ID NUMBER,
CHILD_ID NUMBER
);
Then create the the nested table "CHILD_TABLE" inside the table "PARENT_TABLE"
CREATE TYPE CHILD_OBJECT AS OBJECT(
CHILD_ID NUMBER
);
CREATE TYPE CHILD_TYPE IS TABLE OF CHILD_OBJECT;
CREATE TABLE PARENT_TABLE (
PARENT_ID NUMBER,
CHILD_ID CHILD_TYPE
)NESTED TABLE CHILD_ID STORE AS CHILD_TABLE;
I continue declaring the primary key of the nested table "CHILD_TABLE"
ALTER TABLE CHILD_TABLE
ADD CONSTRAINT CHILD_TABLE_PK PRIMARY KEY (CHILD_ID);
Finally, I TRY to make the foreign key connection between the flat table "GRANDPARENT_TABLE" and the nested table "CHILD_TABLE"
ALTER TABLE CHILD_TABLE
ADD CONSTRAINT CHILD_TO_GRANDPARENT FOREIGN KEY (CHILD_ID) REFERENCES GRANDPARENT_TABLE(CHILD_ID);
but, in this scenario, Oracle SQL Developer won't allow such action and return the following error:
Error report -
ORA-30730: referential constraint not allowed on nested table column
30730. 00000 - "referential constraint not allowed on nested table column"
*Cause: An attempt was made to define a referential constraint on a nested
table column.
*Action: Do not specify referential constraints on nested table columns.
Although, in the first scenario, Oracle SQL Developer would let me make the connection between the two tables, in the second one, it won't allow such action. Why is this happening? Is there any way to make the connection possible in the second scenario?
As the ORA-30730 says, you cannot create a referential constraints on nested table columns. This is forbidden. In scenario one you are creating the constraint on GRANDPARENT_TABLE, not the other way around. This is possible.
This link suggests a workaround to do what is forbidden to do, but it's not your case:
http://ksun-oracle.blogspot.com/2011/05/foreign-key-on-nested-table.html
As a general suggestion, avoid the use of nested tables, they cause lots of problems, be sure!
Related
1.In which order should we apply primary key, foreign key constraints and create index if the Oracle table has millions of data and does not have prior constraints?
2.Can we use 'NOLOGGING PARALLEL' while applying primary key and foreign key constraints like we do while applying(creating) indexes? Or any other method so that primary key and foreign key constraints could be applied faster?
Note: I'll use bullets so that it is easier to read, as it is easy to get lost in long sentences.
My thoughts on the subject; see if anything of this helps.
Well,
as you can't create a foreign key constraint if column(s) it references aren't part of primary or unique key
you'll obviously first have to create primary key constraints
and then foreign key constraints
When you
create a primary key constraint,
Oracle automatically creates index that supports it, unless there's already an index you can use (with the USING INDEX clause)
which means that you can "skip" some indexes (those for primary key constraints as they'll already exist) and virtually save some time
and create "other" indexes
On the other hand,
if you first create unique index on future primary key columns and
later add primary key constraint with the USING INDEX clause, Oracle will "skip" check for possible duplicate values because unique index won't allow them
The same goes for
NOT NULL constraint on future primary key columns; primary key doesn't allow NULLs so - if a column already is NOT NULL, enforcing primary key constraint can skip NULL check as well
I don't know
which columns you'll additionally index, but - as you're on Oracle 11g -
don't forget to index all foreign key constraint columns
because you might encounter unexpected table locks if you
update primary key column in parent table, or
delete parent record
Can you do it with no logging and in parallel? Yes:
SQL> create table test (id number, name varchar2(20));
Table created.
SQL> create unique index ui1_test_id on test (id) nologging parallel 20;
Index created.
SQL> alter table test add constraint pk_test primary key (id) using index ui1_test_id nologging parallel 20;
Table altered.
SQL>
But you'll probably want to change the index and table back to NOPARALLEL and LOGGING when the initial creation is done.
SQL> alter index ui1_test_id noparallel;
Index altered.
SQL> alter table test logging noparallel;
Table altered.
I have two schemas, and I am trying to create a table with two foreign key constraint. Creating the foreign key constraint does not work regardless of whether I add the constraint separately or in the table creation DDL. Also regardless of which of the two users I try to run it.
The oracle error is ORA-01031: insufficient privileges.
The table is created when I omit the foreign key constraints.
Intended result: create a table with two constraints.
CREATE TABLE "XXX_MONITORING"."COMPOSITE_STATUS"
( "COMPOSITE_STATUS_ID" NUMBER,
"COMPOSITE_ID" NUMBER,
"STATUS" CHAR(1),
CONSTRAINT "COMPOSITE_FK" FOREIGN KEY ("COMPOSITE_ID")
REFERENCES "XXX_MONITORING_CONFIGURATION"."COMPOSITE_KPI_COMPONENTS" ("COMPONENT_ID") ON DELETE CASCADE ENABLE,
CONSTRAINT "COMPOSITE_STATUS_FK" FOREIGN KEY ("STATUS")
REFERENCES "XXX_MONITORING_CONFIGURATION"."INDICATION_COLOR" ("INDICATION_COLOR_ID") ON DELETE CASCADE ENABLE
);
The table COMPOSITE_KPI_COMPONENTS and INDICATION_COLOR are in different schema i.e. XXX_MONITORING_CONFIGURATION.
That user must grant REFERENCES on COMPOSITE_KPI_COMPONENTS and INDICATION_COLOR to XXX_MONITORING.
-- Grant statement
grant REFERENCES on COMPOSITE_KPI_COMPONENTS to XXX_MONITORING;
grant REFERENCES on INDICATION_COLOR to XXX_MONITORING;
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
I have a primary key PK1 for the table TABLE1. Need to add one more column to the existing primary key.
I was tying the following alter script
ALTER TABLE TABLE1
ADD CONSTRAINT "PRIMARYKEYS" PRIMARY KEY
("PK1",
"PK2");
Error report:
SQL Error: ORA-02260: table can have only one primary key
02260. 00000 - "table can have only one primary key"
*Cause: Self-evident.
*Action: Remove the extra primary key.
How can I add one more column to the primary key, without affecting the data(data has been verified , there are no duplication.)
If you have concern about new data that violates PK can be added during the time interval when the old PK dropped, but the new one is not created, you can create a unique index first :
CREATE UNIQUE INDEX IDXU_TABLE1_PK ON TABLE1(PK1,PK2);
ALTER TABLE TABLE1 DROP CONSTRAINT [old_pk_constraint_name] ;
ALTER TABLE TABLE1 ADD CONSTRAINT "PRIMARYKEYS" PRIMARY KEY
(PK1,PK2) USING INDEX IDXU_TABLE1_PK;
Another option is to keep index associated with the old PK constraint until new PK is created :
ALTER TABLE TABLE1 DROP CONSTRAINT [old_pk_constraint_name] KEEP INDEX;
ALTER TABLE TABLE1 ADD CONSTRAINT "PRIMARYKEYS" PRIMARY KEY
(PK1,PK2) ;
DROP INDEX [name of unique index associated with the old PK constraint];
You need to drop old primary key first.
I've just started a new project and I am confronted with a production application Oracle 10g database that has just 3 foreign key constraints. I am not used to seeing databases with no foreign key constraints. I am guessing that there may be some performance/concurrency considerations to not using FKs. The reason is that in the logical database schema the architect has specified all the relationships, but these relationships are not implemented in the database as Foreign Key constraints.
Question: I read that I can define a Foreign Key Constraint with RELY NOVALIDATE that will not impact performance. Is it worth while to define RELY FK constraints on this database just so that the relationship can be easily seen? this application is not built using ORM, is it really worth while to do without foreign keys?
The database is denormalised with example below
Table 1 : FINProduct(ID (number), Description(varchar(5)), FINproductCode(varchar(10))...)
Table 2: FINProductCode(ID (number, FINproductCode(varchar(10)) , LastUpdated(datetime)...)
So instead of having a relationship between Tables 1 and 2 the FINproductCode column is just replicated in table 1.
It's too early to drink but I think i need one!
I would be very wary about assuming that the absence of foreign key constraints was a reasoned response to performance issues. There is an overhead to enforcing a foreign key constraint (particularly where appropriate indexes are missing) but it is incredibly unlikely that your application can validate the constraint more efficiently than Oracle can. So the question really is whether you want the small overhead of foreign key constraints or the near certainty that you will get invalid data inserted into the database. It would be extremely unlikely that this is a trade-off that you want to make-- I've yet to meet a business user that would be happy to capture incorrect and incomprehensible data even if doing so was a bit faster than capturing correct data.
Unless there is substantially more background, I would tend to create all the missing foreign key constraints. Creating RELY NOVALIDATE constraints is possible but it defeats the major benefit of foreign key constraints-- preventing invalid data from entering the database in the first place.
It depends on whether you want to add the FK only for documentation purposes or whether you want to prevent future INSERTs/UPDATEs with an invalid FK value.
If you want it only for documentation purposes, I'd create the FK constraint with RELY NOVALIDATE and DISABLE it afterwards - otherwise, Oracle will check it for future INSERTs / UPDATEs.
However: DON'T DO THIS UNLESS YOU ABSOLUTELY NEED IT!
I agree with Justin Cave: In most cases, you should just add "plain" FK constraints - this way, you can ensure that your existing data is correct.
I would try to create the constraints and report violations into a exception table. Fix the data and enable the constraint.
Create some test data
create table parent (pk integer
,data varchar2(1)
,CONSTRAINT PARENT_PK PRIMARY KEY (PK) ENABLE );
create table child (pk integer
,pk_parent integer
,data varchar2(1)
,CONSTRAINT CHILD_PK PRIMARY KEY (PK) ENABLE );
insert into parent values (1,'a');
insert into parent values (2,'b');
insert into child values (1,1,'a');
insert into child values (2,2,'b');
insert into child values (3,3,'c');
Create a foreign key constraint:
alter table child add constraint fk_parent foreign key(pk_parent) references parent(pk);
SQL Error: ORA-02298: Kan (ROB.FK_PARENT) niet valideren - bovenliggende sleutels zijn niet gevonden.
02298. 00000 - "cannot validate (%s.%s) - parent keys not found"
*Cause: an alter table validating constraint failed because the table has
child records.
*Action: Obvious
Create the foreign key with 'enable novalidate' option
alter table child add constraint fk_parent foreign key(pk_parent) references parent(pk) enable novalidate;
table CHILD altered.
insert into child values (4,4,'c');
SQL Error: ORA-02291: Integriteitsbeperking (ROB.FK_PARENT) is geschonden - bovenliggende sleutel is niet gevonden.
02291. 00000 - "integrity constraint (%s.%s) violated - parent key not found"
*Cause: A foreign key value has no matching primary key value.
*Action: Delete the foreign key or add a matching primary key.
No new data violating the FK can be inserted.
Now let's fix the data already in the table that violates the FK constraint
Create an exceptions table and try to enable the constraint:
create table exceptions(row_id rowid,
owner varchar2(30),
table_name varchar2(30),
constraint varchar2(30));
ALTER TABLE child ENABLE constraint fk_parent EXCEPTIONS INTO EXCEPTIONS;
Error report:
SQL Error: ORA-02298: Kan (ROB.FK_PARENT) niet valideren - bovenliggende sleutels zijn niet gevonden.
02298. 00000 - "cannot validate (%s.%s) - parent keys not found"
*Cause: an alter table validating constraint failed because the table has
child records.
*Action: Obvious
Check the exceptions table for problems:
select * from exceptions;
ROW_ID OWNER TABLE_NAME CONSTRAINT
------ ------------------------------ ------------------------------ ------------------------------
AABA78 ROB CHILD FK_PARENT
AAFAAA
Ow9AAC
select * from child where rowid = 'AABA78AAFAAAOw9AAC';
Fix the problem
delete from child where pk = 3;
1 rows deleted.
ALTER TABLE child ENABLE constraint fk_parent EXCEPTIONS INTO EXCEPTIONS;
table CHILD altered.
Constraint enabled and data correct