Foreign Key Not Populating with Primary Key Values - sql

I have searched for an answer but am not finding it. I have 2 tables. Both have an auto-generated PK. The PK from table 2 is an FK in table 1. Since they are both auto-generated I assumed the FK in table 1 would populate with the value that is auto-generated from table 2 but it is not working. The FK in table 1 ends up null. Here is my SQL code for creating table 1:
CREATE TABLE Employee_tbl (
EmployeeID int PRIMARY KEY IDENTITY,
LastName varchar(20) not null,
FirstName varchar(20) not null,
Age varchar(3) not null,
JobID int FOREIGN KEY REFERENCES JobTitle_tbl(JobID),
)
and here is table 2:
create table JobTitle_tbl(
JobID int PRIMARY KEY IDENTITY,
EEO1Classification varchar(50) not null,
Exempt_nonexempt_status varchar(20) not null,
)
I also have some insert statements:
INSERT INTO Employee_tbl
(LastName, FirstName, Age)
Values
('Smith', 'John', '50'),
...
and:
INSERT into JobTitle_tbl (EEO1Classification, Job_title, )
VALUES ('Office/Clerical', 'Accounting Clerk', ),
Why is the FK value showing null when I query table 1?

The foreign keys will not auto-populate, as it doesn't know what foreign key to use. You need to either insert the rows into the JobTitle_tbl table, then select the IDs back out (or use ##identity if using sql server)
select id from JobTitle_tbl where Job_title = ''
Another option would be to update your insert statements to include the primary key, although you'll have to allow identity inserts first.
SET IDENTITY_INSERT JobTitle_tbl ON
into the JobTitle_tbl (id, title) values (1, 'Manager')
SET IDENTITY_INSERT JobTitle_tbl OFF
In either case, you'll need to then update your first insert statements with the ID that you have.
insert into Employee_tbl (LastName, FirstName, JobID) values ('Smith', 'John', 1)

Related

How to insert data into another table when the condition is met with trigger

I have these 4 tables:
CREATE TABLE dbo.person
(
personId INT IDENTITY(1,1) NOT NULL,
firstName NVARCHAR(30) NOT NULL,
lastName NVARCHAR(30) NOT NULL,
CONSTRAINT pkPerson PRIMARY KEY (personId),
);
CREATE TABLE dbo.personRegistration
(
person_registrationId INT IDENTITY(1,1) NOT NULL,
personId INT,
firstName NVARCHAR(30) NOT NULL,
lastName NVARCHAR(30) NOT NULL,
confirmed NCHAR(1) DEFAULT 'N' NOT NULL,
CONSTRAINT pkpersonRegistration PRIMARY KEY (person_registrationId),
CONSTRAINT fkpersonRegistration FOREIGN KEY (personId) REFERENCES dbo.person (personId)
CONSTRAINT personConfirmed CHECK (confirmed IN ('Y', 'N'))
);
CREATE TABLE dbo.person_organizationalUnit
(
personId INT NOT NULL,
organizationalUnitId INT NOT NULL,
CONSTRAINT pkorganizationalUnit PRIMARY KEY (personId, organizationalUnitId),
CONSTRAINT fkperson FOREIGN KEY (personId) REFERENCES dbo.person (personId),
CONSTRAINT fkorganizationalUnit FOREIGN KEY (organizationalUnitId) REFERENCES dbo.organizatinalUnit(unicOrgUnitId),
);
CREATE TABLE dbo.organizatinalUnit
(
organizationalUnitId INT IDENTITY(1,1) NOT NULL,
organizationalUnitName NVARCHAR(130) NOT NULL,
CONSTRAINT pkorganizationalUnit PRIMARY KEY (organizationalUnitId)
);
I need to create a trigger which will do that when I add new person in table personRegistration (his personId is set to NULL, and initial value for confirmed is 'N') and when I update personRegistration and set confirmed to 'Y', that person is going to be inserted into table person (value for personId is generated because the personId is an identity column) and the confirmed is going to change it's value to 'Y' and is going to be inserted in table person_organizationalUnit. I have written the trigger but the problem is when I update the personRegistration for more than one person my data double with each update.
CREATE TRIGGER personConfirmed
ON dbo.personRegistration
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON
INSERT INTO dbo.person (firstName, lastName)
SELECT
firstName, lastName
FROM
dbo.personRegistration
SET NOCOUNT ON
DECLARE #idPerson int
SELECT #idPerson = personId
FROM dbo.person
INSERT INTO dbo.person_organizationalUnit (personId, organizationalUnitId)
SELECT #idPerson, I.organizationalUnitId
FROM Inserted AS I
JOIN dbo.person p ON p.personId = #idPerson
WHERE confirmed = 'Y';
END
Data for insert:
INSERT INTO dbo.personRegistration (personId, firstName, lastName, confirmed)
VALUES (NULL, 'John', 'Smith', 'N');
Data for update:
UPDATE dbo.personRegistration
SET confirmed = 'Y'
WHERE personRegistrationId = 1;
SQL Server triggers works with sets not single register i did some small changes in your trigger
create TRIGGER dbo.usp_PersonConfirmed ON dbo.personRegistration
AFTER UPDATE
AS
BEGIN
-- create person if not exists
INSERT INTO dbo.person (firstName, lastName)
SELECT firstName, lastName
FROM dbo.personRegistration p
where not exists(select * from dbo.Person where firstName = p.firstName
and lastName = p.lastName)
-- create orgonization unit if person dont exist and confirmed is Y
INSERT INTO dbo.person_organizationalUnit (personId, organizationalUnitId)
SELECT i.personId, I.organizationalUnitId
FROM Inserted AS I
where not exists(select * from dbo.person_organizationalUnit where
personId = i.personId)
and confirmed = 'Y';
-- update orgonization unit if person exist and confirmed is Y
update pou set organizationalUnitId = I.organizationalUnitId
from dbo.person_organizationalUnit pou
inner join Inserted AS I on i.personID = pou.personId
where i.confirmed = 'Y';
END
Your trigger has a fatal flaw: it does not deeal properly with multiple rows. It is also not using the inserted table in the first INSERT, and instead selecting from the whole original table.
So you need to OUTPUT the identity column from the first insert in order to use it in the second.
Because you don't have the identity column yet, you need to join onto firstName and lastName, which I need not say isn't a very good primary key
CREATE OR ALTER TRIGGER personConfirmed
ON dbo.personRegistration
AFTER UPDATE
AS
SET NOCOUNT ON
IF NOT UPDATE(confirmed) OR NOT EXISTS (SELECT 1 FROM inserted)
RETURN; --early bailout
DECLARE #ids TABLE (personId int PRIMARY KEY, firstName nvarchar(100), lastName nvarchar(100));
INSERT INTO dbo.person (firstName, lastName)
OUTPUT inserted.personId, inserted.firstName, inserted.lastName
SELECT
i.firstName,
i.lastName
FROM
inserted i
WHERE i.confirmed = 'Y';
INSERT INTO dbo.person_organizationalUnit (personId, organizationalUnitId)
SELECT ids.personId, i.organizationalUnitId
FROM inserted AS i
JOIN #ids ids ON i.firstName = ids.firstName AND i.lastName = ids.lastName;
Ideally, you have some kind of unique primary key on personRegistration. then your trigger would look like this:
CREATE OR ALTER TRIGGER personConfirmed
ON dbo.personRegistration
AFTER UPDATE
AS
SET NOCOUNT ON
IF NOT UPDATE(confirmed) OR NOT EXISTS (SELECT 1 FROM inserted)
RETURN; --early bailout
DECLARE #ids TABLE (personId int PRIMARY KEY, registrationId int);
MERGE dbo.person p
USING (
SELECT *
FROM inserted i
WHERE i.confirmed = 'Y'
) i
ON 1 = 0 -- never match
WHEN NOT MATCHED THEN
INSERT (firstName, lastName)
VALUES (i.firstName, i.lastName)
OUTPUT inserted.personId, i.organizationalUnitId
INTO #ids (personId, organizationalUnitId)
;
INSERT INTO dbo.person_organizationalUnit (personId, organizationalUnitId)
SELECT ids.personId, i.organizationalUnitId
FROM #ids ids;
We need that funny MERGE because we want to OUTPUT columns that we are not inserting. You can only do this using MERGE.

Why does the DBMS say that the primary key is not present in the table

I am a CS student that is taking his first course in databases so here I am using Postgresql to create a database with the following tables: employee, project, and worksOn.
So if you run the program you can see that both the employee and project table are created.
However, worksOn is not because it gives me the following error:
SQL Error [23503]: ERROR: insert or update on table "workson" violates foreign key constraint "fk_employee"
Detail: Key (essn)=(222443333) is not present in table "employee"."
I know people won't like it but if you could help that would be highly appreciated. Also, take in consideration that I never dealt with databases and I spent like a week on this.
DROP TABLE IF EXISTS employee;
DROP TABLE IF EXISTS project;
DROP TABLE IF EXISTS worksOn;
create table employee(
Ssn bigint generated always as identity,
Fname varchar(45) not null,
Lname varchar(45) not null,
primary key(Ssn)
);
create table project(
Pname varchar(45) not null,
Plocation varchar(45) not null,
Dnum int not null,
Pnumber int generated always as identity,
primary key(Pnumber)
);
create table if not exists worksOn(
Hours int not null,
Essn bigint,
Pno int,
-- index fk_emplyee,
constraint fk_employee
foreign key(Essn)
references employee(Ssn)
-- constraint fk_project
-- foreign key(Pno)
-- references project(Pnumber)
-- on delete set null
);
insert into employee (Fname, Lname)
values('Jim', 'Brown');
--insert into project (Pname, Plocation, Dnum)
--values('ProjA', 'Boston', 3);
insert into worksOn (Essn, Pno, Hours)
values(222443333, 1, 20);
Your ssn column is defined as a identity column which means it's generated automatically whenever you do not specify a value for it during insert. Given your SQL script the SSN value for Jim Brown will be 1, not 222443333 as you expected.
You need to remove the identity attribute from the column, then provide it during insert into the employee table:
create table employee(
ssn bigint, --<< no identity!
fname varchar(45) not null,
lname varchar(45) not null,
primary key(ssn)
);
....
....
insert into employee (ssn, fname, lname)
values(222443333, 'Jim', 'Brown');
However, if you do want the SSN to be auto generated, you need to access the latest value when you insert into the workson table:
Assuming employee.ssn is still an identity column, you can use this:
insert into employee (fname, lname)
values('Jim', 'Brown');
insert into project (pname, plocation, dnum)
values('ProjA', 'Boston', 3);
insert into workson (essn, pno, hours)
values(
currval(pg_get_serial_sequence('employee', 'ssn')),
currval(pg_get_serial_sequence('project', 'number')), 20
);

Violation of PRIMARY KEY constraint 'PK__Transact__'. Cannot insert duplicate key in object 'dbo.Transactions_ID'. The duplicate key value is (1001)

When I am trying to insert execute the table and I am getting that error. And when I try to insert more rows into Employee_in I get an error
The number of columns for each row in a table value constructor must be the same
CREATE DATABASE EmployeeDatabase
USE EmployeeDatabase
CREATE TABLE Employee_In
(
EmployeeID INT NOT NULL PRIMARY KEY,
EmployeeName CHAR(30) NOT NULL,
EmployeeCountry CHAR(30)NOT NULL,
EmployeeSalary INT NOT NULL
)
USE EmployeeDatabase
GO
INSERT INTO Employee_In (EmployeeID, EmployeeName, EmployeeCountry, EmployeeSalary)
VALUES (1001, 'Sundar', 'USA', 125000),
(1002, 'Satya', 'CANADA', 120000);
SELECT * FROM Employee_In
CREATE TABLE Transactions_ID
(
TransactionID INT NOT NULL PRIMARY KEY,
EmployeeID INT FOREIGN KEY REFERENCES Employee_In(EmployeeID),
PostalDate VARCHAR(20) NOT NULL,
Amount VARCHAR(40) NOT NULL,
Description CHAR(25),
);
USE EmployeeDatabase
GO
INSERT INTO Transactions_ID (TransactionID, EmployeeID, PostalDate, Amount)
VALUES ('1001','1001','2020-04-07','20000')
Violation of PRIMARY KEY constraint 'PK__Transact__'. Cannot insert duplicate key in object 'dbo.Transactions_ID'. The duplicate key value is (1001)
This means you already have a value 1001 for the PK TransactionID in your table, most likely from and earlier insert.
INSERT INTO Transactions_ID (TransactionID, EmployeeID, PostalDate, Amount)
VALUES ('1001', '1001', '2020-04-07', '20000')
Here you are trying to insert string in columns with a datatype int... this should be:
INSERT INTO Transactions_ID (TransactionID, EmployeeID, PostalDate, Amount)
VALUES (1001, 1001, '2020-04-07', '20000')
Good luck!

How to prevent the auto increment values if the conflict error is occured?

I had created two tables
Create Table Tbl_Class
(
Id int Identity,
ClassId int Primary Key,
Class Varhar(20)
)
Create Table Tbl_Subjects
(
Id Int Identity,
SubjectId int Primary Key,
Subject Varchar(20),
ClassId int Foreign key (ClassId) REFERENCE Tbl_Class(ClassId)
)
Insert into Tbl_Class values (7,'Seventh');
Insert into Tbl_Class values (8,'Eight');
Insert Into Tbl_Subject values(1,'Science',7);
If I run the above insert statement then it will insert into the table because I had passed the date which exists in the primary table and the identity column value is 1 now but if I fire this query
Insert Into Tbl_Subject values(2,'Science',9);
It gives the conflicted error but here the identity column value increased to 2
I need to prevent auto increment of column value if values not inserted into the database

The INSERT statement conflicted with the FOREIGN KEY SAME TABLE constraint

I have created table Employee
Create table Employee
(
FName varchar(20) Not Null,
LName varchar(20) Not Null,
SSN int Not Null,
BDate Datetime,
Address varchar(50),
Sex char(1),
Salary money,
Super_SSN int,
Primary Key(SSN),
Foreign Key(Super_SSN) references Employee(SSN)
)
When i try to insert first row to ,
insert into Employee(FName,LName,SSN,BDate,Address,Sex,Salary,Super_SSN)
values('John','Smith',12345,'1965-01-09','Houston,TX','M',30000,33344)
I am getting the error like..
Error:
The INSERT statement conflicted with the FOREIGN KEY SAME TABLE constraint "FK_Employee_Employee". The conflict occurred in database "Company", table "dbo.Employee", column 'SSN'.
You need to first INSERT record for SSN '33344' with Super_SSN value as NULL.
INSERT INTO Employee(FName,LName,SSN,BDate,Address,Sex,Salary,Super_SSN)
VALUES (<FName>,<LName>,'33344',<BDate>,<Address>,<Sex>,<Salary>,NULL)
After that insert
INSERT INTO Employee (FName,LName,SSN,BDate,Address,Sex,Salary,Super_SSN)
VALUES ('John','Smith',12345,'1965-01-09','Houston,TX','M',30000,33344)
If SSN '33344' have any Super_SSN, update the SSN value (this record should be available in table).
The error is likely thrown because there is a foreign key from Super_SSN to SSN column. You cannot insert a value of 33344 into Super_SSN unless that value already exists in SSN. Try inserting null into Super_SSN or inserting user 33344 first.