Table record update stopped by Foreign key constraint - sql

I have a problem in updating records to a derby db table with foreign key. Consider the two tables QUESTIONCHOICE and QUESTIONANSWER below. The records in table QUESTIONANSWER is a subset of QUESTIONCHOICE and has a foreign key constraint to make sure QUESTIONANSWER table is always subset of QUESTIONCHOICE table.
Now i am trying to update a record in QUESTIONCHOICE table using the query below and the update is stopped by foreign key constraint.
update "USER"."QUESTIONCHOICE" set "CHOICE"='GET1' where "QID"=10001 and "CHOICE"='GET';
UPDATE on table 'QUESTIONCHOICE' caused a violation of foreign key constraint 'QUESTIONANSWER_FK' for key (10001,GET). The statement has been rolled back.
How am i supposed to update the records in the table QUESTIONCHOICE?
i can delete the record in QUESTIONANSWER table update my record in QUESTIONCHOICE table and then insert the record in QUESTIONANSWER. but it doesnt sounds good to me.
Also can i create QUESTIONANSWER as a VIEW instead a TABLE, If so how will i make a subset of QUESTIONCHOICE table?
please suggest.
Thanks,
-Vijay Selvaraj
----------
CREATE TABLE USER.QUESTIONCHOICE(
QID INT NOT NULL,
Choice VARCHAR(100) NOT NULL,
CONSTRAINT QUESTIONCHOICE_PK PRIMARY KEY (QID, Choice),
CONSTRAINT QUESTIONCHOICE_FK FOREIGN KEY (QID)
REFERENCES user.questionbank (QuestionID)
);
----------
create table USER.QUESTIONANSWER(
QID INT NOT NULL,
Answer VARCHAR(100) NOT NULL,
CONSTRAINT QUESTIONANSWER_PK PRIMARY KEY (QID, Answer),
CONSTRAINT QUESTIONANSWER_FK FOREIGN KEY (QID, Answer)
REFERENCES USER.QUESTIONCHOICE (QID, Choice)
);

Why dont you add a additional column to the QUESTIONCHOICE table to mark a row as the answer row, this way, the view also can be created by applying a constraint on the answer column.

Related

Do foreign keys gets inserted when primary key is inserted?

A very basic question I'm confused about, similar to UPDATE and DELETE CASCADE, do foreign keys gets inserted automatically when a referenced table's primary key is inserted?
Or are they simply a constraint that tells to check the primray key that is being reference and if present add, else error.
As a example, I'm asking about something like this:
...
CONSTRAINT idFK
FOREIGN KEY(id)
REFERENCES Users(id)
ON DELETE CASCADE
ON UPDATE CASCADE
...
Here, will id in this table automatically get inserted when an id is inserted in Users table?
when you insert a record in "Users" table , nothing inserted in any other tables.
when you insert a record in a table with foreign key, the value of foreign key field just will check with the primary key value in parent(Here "Users") table.

How to add a foreign key referring to itself in SQL Server 2008?

I have not seen any clear, concise examples of this anywhere online.
With an existing table, how do I add a foreign key which references this table? For example:
CREATE TABLE dbo.Projects(
ProjectsID INT IDENTITY(1,1) PRIMARY KEY,
Name varchar(50)
);
How would I write a command to add a foreign key which references the same table? Can I do this in a single SQL command?
I'll show you several equivalent ways of declaring such a foreign key constraint. (This answer is intentionally repetitive to help you recognise the simple patterns for declaring constraints.)
Example: This is what we would like to end up with:
Case 1: The column holding the foreign keys already exists, but the foreign key relationship has not been declared / is not enforced yet:
In that case, run this statement:
ALTER TABLE Employee
ADD FOREIGN KEY (ManagerId) REFERENCES Employee (Id);
Case 2: The table exists, but it does not yet have the foreign key column:
ALTER TABLE Employee
ADD ManagerId INT, -- add the column; everything else is the same as with case 1
FOREIGN KEY (ManagerId) REFERENCES Employee (Id);
or more succinctly:
ALTER TABLE Employee
ADD ManagerId INT REFERENCES Employee (Id);
Case 3: The table does not exist yet.
CREATE TABLE Employee -- create the table; everything else is the same as with case 1
(
Id INT NOT NULL PRIMARY KEY,
ManagerId INT
);
ALTER TABLE Employee
ADD FOREIGN KEY (ManagerId) REFERENCES Employee (Id);
or, declare the constraint inline, as part of the table creation:
CREATE TABLE Employee
(
Id INT NOT NULL PRIMARY KEY,
ManagerId INT,
FOREIGN KEY (ManagerId) REFERENCES Employee (Id)
);
or even more succinctly:
CREATE TABLE Employee
(
Id INT NOT NULL PRIMARY KEY,
ManagerId INT REFERENCES Employee (Id)
);
P.S. regarding constraint naming: Up until the previous revision of this answer, the more verbose SQL examples contained CONSTRAINT <ConstraintName> clauses for giving unique names to the foreign key constraints. After a comment by #ypercube I've decided to drop these clauses from the examples, for two reasons: Naming a constraint is an orthogonal issue to (i.e. independent from) putting the constraint in place. And having the naming out of the way allows us to focus on the the actual adding of the constraints.
In short, in order to name a constraint, precede any mention of e.g. PRIMARY KEY, REFERENCES, or FOREIGN KEY with CONSTRAINT <ConstraintName>. The way I name foreign key constraints is <TableName>_FK_<ColumnName>. I name primary key constraints in the same way, only with PK instead of FK. (Natural and other alternate keys would get the name prefix AK.)
You can add the column and constraint in one operation
ALTER TABLE dbo.Projects ADD
parentId INT NULL,
CONSTRAINT FK FOREIGN KEY(parentid) REFERENCES dbo.Projects
Optionally you could specify the PK column in brackets after the referenced table name but it is not needed here.
If the table already exists: Assuming you don't already have a column to store this data. If you do then skip this step.
ALTER TABLE [dbo].[project]
ADD [fkProjectsId] INT;
GO
ALTER TABLE [dbo].[projects]
ADD CONSTRAINT [FK_Projects_ProjectsId] FOREIGN KEY ([fkProjectsId]) REFERENCES [dbo].[Projects] ([ProjectsID])
GO

two columns referencing a single column in another table

A similar question is asked here multiple foreign keys referencing single column in other table
but the syntax is not shown in the answer. I would like to know how this can be accomplished in SQL server. The following syntax gives error
ALTER TABLE ItemIssue ADD CONSTRAINT FK_ItemIssue_Person
FOREIGN KEY (PersonID, AdvisorID) REFERENCES Person (PersonID)
;
ERROR: Number of referencing columns in foreign key differs from number of referenced columns, table 'ItemIssue'.
-- Create Tables
CREATE TABLE ItemIssue (
ItemIssueID int identity(1,1) NOT NULL,
PersonID int,
AdvisorID int,
)
;
CREATE TABLE Person (
PersonID int NOT NULL,
Name nvarchar(500),
)
;
You need to define two foreign keys, one for each column:
ALTER TABLE ItemIssue ADD CONSTRAINT FK_ItemIssue_Person
FOREIGN KEY (PersonID) REFERENCES Person (PersonID)
;
ALTER TABLE ItemIssue ADD CONSTRAINT FK_ItemAdvisor_Person
FOREIGN KEY (AdvisorID) REFERENCES Person (PersonID)
;
It is impossible to create one foreign key for two columns referencing one column. Create them seperate:
ALTER TABLE ItemIssue
ADD CONSTRAINT FK_ItemIssue_Person_Person FOREIGN KEY (PersonID) REFERENCES Person (PersonID),
ADD CONSTRAINT FK_ItemIssue_Advisor_Person FOREIGN KEY (AdvisorID) REFERENCES Person (PersonID);
To define two foreign keys, one for each column-
Table
Contract - HospidPharmacyId Column
Hospice- HospiceID PK
Pharmacy PharmacyId Pk
Using Following Query we can apply 2 Foreign Key for 1 column.
Alter Table Contract
Add Constraint fk_pharmacyID Foreign Key ([HospIDPharmID]) references Pharmacy([PharmacyID])
Alter TAble contract
Add Constraint Fk_hospId Foreign key ([HospIDPharmID]) references Hospice(HospiceID)
In the Contract Table for column-HospidPharmacyId we can insert common value in both the
tables. those which are present in hospice & not in Pharmacy then we cant insert that value in
contract table & vice versa.

Check if data exists in another table on insert?

Table A
(
Table_A_ID int
)
Table B
(
Table_B_ID int
Value int
)
Say I want to insert data into Table B, where 'Value' would be the same as a Table_A_ID.
How would I make a constraint or check that the data actually exists in the table on insertion?
You probably need to enforce data integrity not only on INSERT into Table B, but also on UPDATE and DELETE in both tables.
Anyway options are:
FOREIGN KEY CONSTRAINT on Table B
TRIGGERs on both tables
As a last resort if for some reason 1 and 2 is not an option STORED PROCEDUREs for all insert, delete update operations for both tables
The preferred way to go in most cases is FOREIGN KEY CONSTRAINT.
Yap, I agree with #peterm.
Cause, if your both Table_A_ID and Table_B_Id are primary keys for both tables, then you don't even need two tables to store the value. Since, your two tables are seems to be on 'one-to-one' relationship. It's one of the database integrity issues.
I think you didn't do proper normalisation for this database.
Just suggesting a good idea!
I found this example which demonstrates how to setup a foreign key constraint.
Create employee table
CREATE TABLE employee (
id smallint(5) unsigned NOT NULL,
firstname varchar(30),
lastname varchar(30),
birthdate date,
PRIMARY KEY (id),
KEY idx_lastname (lastname)
) ENGINE=InnoDB;
Create borrowed table
CREATE TABLE borrowed (
ref int(10) unsigned NOT NULL auto_increment,
employeeid smallint(5) unsigned NOT NULL,
book varchar(50),
PRIMARY KEY (ref)
) ENGINE=InnoDB;
Add a constraint to borrowed table
ALTER TABLE borrowed
ADD CONSTRAINT FK_borrowed
FOREIGN KEY (employeeid) REFERENCES employee(id)
ON UPDATE CASCADE
ON DELETE CASCADE;
NOTE: This tells MySQL that we want to alter the borrowed table by adding a constraint called ‘FK_borrowed’. The employeeid column will reference the id column in the employee table – in other words, an employee must exist before they can borrow a book.
The final two lines are perhaps the most interesting. They state that if an employee ID is updated or an employee is deleted, the changes should be applied to the borrowed table.
NOTE: See the above URL for more details, this is just an excerpt from that article!
Create a foreign key constraint on the column 'Value' on table B that references the 'Table_A_ID' column.
Doing this will only allow values that exist in table A to be added into the 'Value' field of table B.
To accomplish this you first need to make Table_A_ID column the primary key for table A, or it at least has to have some sort of unique constraint applied to it to be a foreign key candidate.
BEGIN TRANSACTION -- REMOVE TRANSACTION AND ROLLBACK AFTER DONE TESTING
--PUT A PRIMARY KEY ON TABLE A
CREATE TABLE A
( Table_A_ID int CONSTRAINT PK_A_Table_A_ID PRIMARY KEY)
--ON VALUE ADD A FOREIGN KEY CONSTRAINT THAT REFERENCEs TABLE A
CREATE TABLE B
( Table_B_ID int,
[Value] int CONSTRAINT FK_B_Value_A REFERENCES A(Table_A_ID)
)
-- TEST VALID INSERT
INSERT A (Table_A_ID) VALUES (1)
INSERT B (Table_B_ID, [Value]) VALUES (1,1)
--NOT ALLOW TO INSERT A VALUE THAT DOES NOT EXIST IN A
--THIS WILL THROW A FOREIGN KEY CONSTRAINT ERROR
INSERT B (Table_B_ID, [Value]) VALUES (1,2) -- 2 DNE in table A
ROLLBACK
Note: there is no magic to 'FK_B_Value_A' or 'PK_A_Table_A_ID' it simply a naming convention and be called anything. The syntax on the foreign key and primary key lines work like this:
column-definition CONSTRAINT give-the-constraint-a-name REFERENCES table-name ( table-column )
column-definition CONSTRAINT give-the-constraint-a-name PRIMARY KEY

could unique key ( not primary ) be a parent for declarative foreign key constraint

Naive question with the answer "No" , I believe, but still would like to ask.
Table_parent
pk_parent_surrogate
parent_natural_unique_key
Table_child
pk_child_surrogate
child_natural_NOT_unique
Is that true that the only possible declarative relationship among main database vendors is
pk_parent_surrogate ----------< pk_child_surrogate
and we can't have declarative constraint or foreign key in other words for pair
parent_natural_unique_key -------< child_natural_NOT_unique
My answer here is based on my MS SQL knowledge - although I believe the same answer is correct for ANSI standards as well, i'm not 100% sure...
YES - you CAN do this as long as you've got a unique constraint on the column in your parent table that you want to use as the anchor column for the key.
You can create a FOREIGN KEY constraint as part
of the table definition when you create a table.
If a table already exists, you can add a
FOREIGN KEY constraint, provided that the
FOREIGN KEY constraint is linked to an existing
PRIMARY KEY constraints or UNIQUE constraint in
another, or the same, table. A table can contain
multiple FOREIGN KEY constraints.
And as an example of this sort of key...
use tempdb
CREATE TABLE parent(
pk int identity primary key,
candidate_key int unique not null)
CREATE TABLE child(
pk int identity primary key,
join_key int references parent(candidate_key))
See here for more information.
Try code like this:
create table testunique (id int identity(1,1) primary key, otherid int)
go
create unique index ixOther on testunique(otherid)
go
create table testFK (id int identity(1,1) primary key, someid int)
go
alter table testFK add constraint fkTest foreign key (someid) references testunique(otherid)
Rob