Can a composite foreign key reference a composite primary key and not have all the values NOT match (Oracle)? And in the same table? - oracle12c

This is an existing table in Production. Adding a new row with a unique primary key causes failure to enable the foreign key with 'parent does not exist' but the data is there. PK does not prevent insert so I know it's unique.
ALTER TABLE tableA ADD (CONSTRAINT tableA_PK
PRIMARY KEY
(SEGMENT, STEP)
USING INDEX tableA.tableA_PK
ENABLE VALIDATE;
ALTER TABLE tableA ADD (
CONSTRAINT tableA_FK
FOREIGN KEY (SEGMENT, PREDECESSOR_STEP)
REFERENCES tableA (SEGMENT, STEP)
ENABLE VALIDATE);
Note: PREDECESSOR_STEP will never be = to STEP. SEGMENT, PREDECESSOR_STEP each have their own non-unique index:
SEGMENT - unique index
STEP - unique index
STEP - also has a non-unique index
PREDECESSOR_STEP - non-unique index
A primary key values look like:
AEM CAL_NVR_ID
The foreign key values:
AEM CAL_NVR
When I try to insert a row with these exact values I am getting : 'parent does not exist' when enabling the fk constraint.

Related

Postgres - remove record from parent table without deleting foreign key child table records

I have an odd use case. A datbase I'm working with has a primary key column that got duplicated for one record - and I'm trying to remove the duplicate, but cannot due to foreign key relations.
Parent table:
id
title
1
some
1
other
2
anoth
Child table: child.parent_id = parent.id
id
title
parent_id
1
some
1
2
other
2
3
anoth
2
I need to remove the duplicated record from parent table (id=1) but cannot delete it due to foreign key constraints. What is the best path forward here?
Not sure how you managed to create a foreign key that references columns that are not a unique key.
Just drop the foreign key, delete the offending row, and add the foreign key again. Of course, you should only do this when the database is not in use. And probably within a transaction.
You can drop the foreign key with:
ALTER TABLE child DROP CONSTRAINT the_foreign_key_name;
And add it with:
ALTER TABLE child ADD FOREIGN KEY (parent_id) REFERENCES parent (id);

use one part of composite primary key as foreign key

I'm using PostgreSQL.
I have a table accounts with account_id as the primary key. I also have a second table called relations with a composite primary key (follower_id, following_id). Each relation must be unique.
ALTER TABLE accounts ADD CONSTRAINT users_pk PRIMARY KEY (account_id);
ALTER TABLE relations ADD CONSTRAINT relations_pk PRIMARY KEY (follower_id, following_id);
I want to create a foreign key constraint from follower_id (relations) -> account_id (accounts), and the same with following_id.
ALTER TABLE relations ADD CONSTRAINT follower_id_fk FOREIGN KEY (follower_id) REFERENCES accounts (account_id) ON DELETE CASCADE
This foreign key is not accepted by the database. I get the following error:
ERROR: insert or update on table "relations" violates foreign key constraint "follower_id_fk"
DETAIL: Key (follower_id)=(4) is not present in table "accounts".
I understand this, because it's a composite primary key.
What I want to achieve:
When an account is deleted, I want to delete all the records where the account_id is the follower_id (ON DELETE CASCADE) AND where it is the following_id.
I could do this in my nodejs code or with a trigger function, but I don't know what will be the best performance-wise. Does anyone knows a/the best solution?

How to change value of a primary key when its a foreign key reference in another table in postgresql

I have a table user_type and user_type_id is the primary key of that table and I have another table user_details where user_type_id is a reference of the foreign key.
I want to change the id value of the user_type_id column.
First update user_details to set the foreign key column to NULL for the rows that depend on the primary key, then update user_type, then change the rows in user_details to the updated value.
You can make this easier in two ways:
define the foreign key with ON UPDATE CASCADE, then this happens automatically
define the foreign key as DEFERRABLE, the you can defer the check to the end of the transaction

Alter the table by adding constraint and using index in postgresql getting an error syntax error at or near "("IDX_emp_PK

CREATE INDEX IDX_emp_PK ON
EMP(ID);
ALTER TABLE EMP ADD
CONSTRAINT PK_emp PRIMARY KEY (ID)
USING INDEX IDX_emp_PK;
There are two errors in your script:
First: you can't use a non-unique index for a primary key constraint, so you need
CREATE UNIQUE INDEX idx_emp_pk ON emp(id);
When you add a primary or unique constraint based on an index, you can't specify columns (as they are already defined in the index):
ALTER TABLE emp ADD
CONSTRAINT pk_emp PRIMARY KEY
USING INDEX idx_emp_pk;

T-SQL: foreign key that's not referencing a primary key

I have the following database:
CREATE TABLE ContentNodes
(
Id UNIQUEIDENTIFIER NOT NULL,
Revision INT IDENTITY(1,1) NOT NULL,
ParentId UNIQUEIDENTIFIER NULL
PRIMARY KEY (Id, Revision)
)
How do I limit ParentId to only contain values from the Id column. Trying to make ParentId a foreign key gives me:
PRINT 'FK_ContentNodes_ParentId_ContentNodes';
ALTER TABLE ContentNodes
ADD CONSTRAINT FK_ContentNodes_ParentId_ContentNodes FOREIGN KEY (ParentId) REFERENCES ContentNodes(Id);
GO
Error:
There are no primary or candidate keys in the referenced table
'ContentNodes' that match the
referencing column list in the foreign
key
'FK_ContentNodes_ParentId_ContentNodes'.
Since you have a compound primary key (Id, Revision) on your ContentNodes, you have to use both columns in a foreign key relation.
You cannot reference only parts of a primary key - simply cannot be done.
You have to either introduce a surrogate primary key into your table which is just a simple INT IDENTITY and then you can self-reference that single PK column, or you can (if it's possible in your data model) put a UNIQUE INDEX on that one column you want to reference:
CREATE UNIQUE NONCLUSTERED INDEX UIX_ID
ON ContentNodes(Id)
Once you have a UNIQUE INDEX on that column, then you can use it as a FK reference.