Why am I getting an Integrity Constraint (parent key not found) when the parent key exists - sql

I have a parent record in my people table, but when trying to insert a matching record in my employee table, I get a integrity constraint error. Can anyone explain what is wrong?

Ah! Based on your comment:
I've added a pic of the foreign keys, personID is present is both the employee table and customer table and references the people table
it seems that you're mistaken.
Oracle doesn't check whether constraints exist, but whether data (that support those constraints) exist. In other words, first you have to insert a row into a parent table, and then into its child table (whose values "reference" primary key values in the parent table).
The way you posted it, you're inserting into child with no parent.

From the provided images, I can only guess that you are trying to insert a record into "Employee" table with "PersonId" that does not exist in the parent table "People"
If that is not the case, are you able to show us the whole table design including foreign keys?

Related

Bypass database constraints during record deletion

I have around 20 mapping tables which refer to a single table.
The single table being referenced is,
field (
id integer,
value char
)
The mapping tables are as,
employee_field_map (
employee_id integer references employee(id),
field_id references field(id)
)
dept_field_map (
dept_id integer references dept(id),
field_id references field(id)
)
and similar additional 18 mapping tables.
Now if I want to delete number of records from the field table where field.id = employee_field_map.field_id it takes very long amount of time because there are 20 mapping tables which refer to the field table; And for each of that mapping table a constraint violation check is performed before deleting a record from the field table.
A field table rcord will always be referenced by only one of the mapping table at a time.
In above scenario before deleting a record from field table of course the corresponding record in employee_field_map table is deleted first. So I know for sure that none of the mapping table contains a reference to the field table record being deleted. So is there a way to tell the database engine not to perform those constraint checks when the delete on field table is being performed?
Disabling the constraints is not an option unfortunately. Please advise.
Assuming each of the mapping tables has an index on field_id, then the lookups should not be expensive.
I am wondering why you are not declaring them using cascading delete foreign key references:
employee_field_map (
employee_id integer references employee(id),
field_id references field(id) on delete cascade
);
Nothing in your data model is saying that the field is in only one mapping table. In fact, I don't see why things are broken out the way they are. Presumably there is a reason for breaking the fields apart like this instead of just having a "type" column in the fields table.

Query regarding SQLite and Cascading foreign keys

I am currently writing a application in C# that uses a SQLite database to store information the user will input. The application is basically a Management system for users who are called "Students" in the application. This is the most important table in my database and every other table is linked off this table. What I want to do is when a student is removed - they leave the institute/get kicked out etc. - is to remove their data from all the other tables so that data is no longer there as it isn't needed. An example of some of the Create table statements I have written is:
CREATE TABLE student(studentID int(5) PRIMARY KEY NOT NULL, name string(16),...,DOB string(8) );
CREATE TABLE emergencyContact(emergencyID int(5) PRIMARY KEY NOT NULL, name string(16),..., contactNumber int(16));
CREATE TABLE emergencyContactOf(studentID int(5) FOREIGN KEY REFERENCES student('studentID'), emergencyID int(5) FOREIGN KEY REFERENCES emergencyContact('emergencyID');
I have read up on this and my understanding is the data will be deleted in the EmergencyContactOf table if I include a 'ON DELETE CASCADE' statement as the StudentID key will no longer be present in the Parent table.
However, my understanding is the data in the EmergencyContact table that is for that specific student will not be deleted as there is no reference to the StudentID.
My question is, is there a way to remove the data from this table also that is relevant to that Student? For example, if I was to include a column in the EmergencyContact table which would reference the StudentID as a Foreign Key and then remove that row if the StudentID is ever deleted from the parent table? Is this a good solution to this particular problem?
All other tables I have are also designed in this way, where the data is in different tables and then linked back to the Student table with relationship tables so this will also apply to all the other tables I have.
Thanks.
My question is, is there a way to remove the data from this table also that is relevant to that Student? For example, if I was to include a column in the EmergencyContact table which would reference the StudentID as a Foreign Key and then remove that row if the StudentID is ever deleted from the parent table? Is this a good solution to this particular problem?
What happens if multiple students have the same emergency contact? You don't want to duplicate data if you don't have to - that's the whole point of the emergencyContactOf table, to efficiently set up a many to many relation between students and emergency contacts. So you don't want to do something like you describe.
You could periodically (Monthly, yearly, after purging student rosters, whatever) run a delete that removes rows from emergencyContact if they don't appear in emergencyContactOf:
DELETE FROM emergencyContact
WHERE emergencyID NOT IN (SELECT emergencyID FROM emergencyContactOf)
or the like.
Hmm, I see two scenarios here. What if two students have the same emergency contact, say two bothers having their father as emergency contact?
If in such a case you store only one record (the father) in the emergency contact table, you don't want to delete the emergency contact if only one of them leaves. You'd delete the emergency contact for the other one. So you'd need additional logic, when to delete an emergency contact. You could put that in a trigger.
You use a less sophisticated approach and multiple rows from the emergency contact table can map to one person in real life. In that case you can pull the reference to the student directly into the emergency contact table and use ON DELETE CASCADE there.
CREATE TABLE student
(studentid int(5),
name string(16),
...
PRIMARY KEY (studentid),
...);
...
CREATE TABLE emergencycontact
(emergencycontactid int(5),
studentid int(5),
name string(16),
...
PRIMARY KEY (emergencycontactid),
FOREIGN KEY (studentid)
REFERENCES student
(studentid),
...);
The second might be tempting but the "clean way" is the first one, as the second allows contradicting data. From what you posted you're already on the "clean way". But a mentioned that required triggers.

Insert into tables with primary and foreign key at same time

Very new to SQL and have spent a day on this already.
Here are my two tables:
Centre(cid, name, location, nurse_supervisor)
Nurse(nid, name, centre_id, certificate)
I have a big problem. The (nurse_supervisor) in Centre is a foreign key to Nurse (nid).
The (centre_id) in Nurse is a foreign key to (Centre cid).
I can't figure out how to populate these tables. I have tried:
INSERT ALL, which produces "A foreign key value has no matching primary key value"
I have tried removing the foreign key constraints and adding them after populating the tables but when I do that it says I can't add a constraint to tables with preexisting data.
I tried removing NOT NULL - but realized that was silly as the constraints will be enforced anyways.
Everything I look through says populate the parent table first and then the child, but these tables are linked to each other.
I am using SQL developer.
This is a poor schema design, but one way to get around it would be to:
Make both centre_id and nurse_supervisor columns NULL in the two table definitions
Insert all rows into both tables, but with NULL for those two columns
Update centre_id to the correct value for each row in the Nurse table
Update nurse_supervisor to the correct value for each row in the Centre table

How to delete a row ONLY in parent table, which is referenced by a Foregin Key from the child table

I want to delete a row/tuple from a parent table, but it is throwing an error message because it has a FOREIGN KEY reference in its child table.
However, in my case I want to delete the record only from the parent table and maintain the data in the child table.
Is it possible to achieve this?
I know the usage of ON DELETE CASCADE, but I want to know if there is a solution for the secenario I described?
It is possible with some agreements in your data. To maintain child table data you'll have to do ON DELETE SET NULL. This will leave data, but set FK to NULL value (in child table). And that is because of data-integrity: while you can keep your data, your FK can not refer to non-existent row of parent table in terms of enforcing FK constraint. Thus, it will be set to NULL by this.
If you want to "save" value of FK - then you definitely should not use FK at all because such behavior violates what FK is. So then just don't use that constraint, but be aware of possible integrity fails.
The point of a foreign key constraint is to prevent orphan records in the child table. So, no, it's not possible to do that, unless you drop the foreign key relationship.
If you rely on 'ON DELETE CASCADE', then deleting the parent record will result in all the corresponding children to be deleted.
If you want to delete the parent, but keep the children, you need to drop the foreign key constraint, or set the constraint to be 'ON DELETE SET NULL'. If you set 'ON DELETE SET NULL', then when you delete the parent record, the child records will remain, but the foreign key column value will be set to NULL.
delete a row ONLY in parent table, which is referenced by a Foregin Key from the child table
If Multiple table has been mapped in one table in that case all foreign key i.e :-
$table->integer('customer_id')->unsigned()->nullable();
$table->foreign('customer_id')->references('id')
->on('customers')->onDelete(`SET NULL`);

Database table id-key Null value and referential integrity

I'm learning databases, using SQLce. Got some problems, with this error:
A foreign key value cannot be inserted because a corresponding primary key value does not exist.
How does the integrity and acceptance of data work when attempting to save a data row that does not have specified one foreign key. Isn't it possible to set it to NULL in some way, meaning it will not reference the other table? In case, how would I do that? (For an integer key field)
Also, what if you save a row with a valid foreign key that corresponds to an existing primary key in other table. But then decide to delete that entry in this other table. So the foreign key will no longer be valid. Will I be allowed to delete? How does it work? I would think it should then be simply reset to a null value.. But maybe it's not that simple?
What you need to do is insert your data starting from the parent down.
So if you have an orders table and an items table that refers to orders, you have to create the new order first before adding all the children to the list.
Many of the data access libraries that you can get (in C# there is Linq to SQL) which will try and abstract this problem.
If you need to delete data you actually have to go the other way, delete the items before you delete the parent order record.
Of course, this assumes you are enforcing the foreign key, it is possible to not enforce the key, which might be useful during a bulk delete.
This is because of "bad data" you have in the tables. Check if you have all corresponding values in the primary table.
DBMS checks the referential integrity for ensuring the "correctness" of data within database.
For example, if you have a column called some_id in TableA with values 1 through 10 and a column called some_id in TableB with values 1 through 11 then TableA has no corresponding value (11) for that which you have already in TableB.
You can make a foreign key nullable but I don't recommend it. There are too many problems and inconsistencies that can arise. Redesign your tables so that you don't need to populate the foreign key for values that don't exist. Usually you can do that by moving the column to a new table for example.