Inserting one table's primary key into another table - sql

I have two tables in SQL Server, Appointment and AppointmentDetails.
Appointment table has two columns AppId and CusId.
AppointmentDetail table has AppId, ApDay, Intime, OutTime, EmpId.
Appointment table has AppId as its primary key, and it is set to auto increment.
AppointmentDetails table has primary key on (AppId, ApDay).
My problem how get and insert the primary key of the Appointment table to AppointmentDetails table when I am inserting data into Appointment table???

Here's one method of doing it (with corrected spellings for table names though I accept these are sometimes beyond your control):
DECLARE #insertedId INT;
BEGIN TRANSACTION
INSERT INTO Appointment(CusId) VALUES(#cusId);
SET #insertedId = SCOPE_IDENTITY();
COMMIT
BEGIN TRANSACTION
INSERT INTO
AppointmentDetails
SELECT
AppId = #insertedId
,ApDay = #apDay
,Intime = #inTime
,OutTime = #outTime
,EmpId = #empId
FROM
Appointment
COMMIT
Alternatively you could use a trigger, but they're just evil!

I think they asking how can they return the new key that was generated to then insert it into the details table.
Check this post out if using JDBC but the idea is the same for all languages: How to get the insert ID in JDBC?

Related

SQL Server : primary key violation on occasion despite prior deletion

I have a procedure that is supposed to replace an entry in my table by first deleting it based on an id and then inserting it with new values.
It looks like this, plus additional values used for the insert statement that I have left out.
ALTER PROCEDURE [dbo].[DemoProc]
#id BIGINT,
...
AS
IF EXISTS (SELECT id FROM demoTable WHERE id = #id)
DELETE demoTable
WHERE id = #id
INSERT INTO demoTable (id, ...)
VALUES (#id, ...)
RETURN 0
Now every now and again, I'm getting an error log that alerts me of a primary key violation that originates from this procedure. I also end up with the entry not being inserted at all. Any ideas?

How to get ID of an identity column?

I have a many-to-many relationship between two tables, Users and Projects.
The table that connects those two together is named ProjectsUsers.
Here is the description of the tables and their relationships:
CREATE TABLE "Users"
(
Email VARCHAR(320) COLLATE SQL_Latin1_General_CP1_CI_AS PRIMARY KEY CHECK(LEN(Email) >= 3),
--More....
);
CREATE TABLE "Projects"
(
ProjectID INT PRIMARY KEY IDENTITY,
--More....
);
CREATE TABLE "ProjectsUsers"
(
UsersEmail VARCHAR(320) COLLATE SQL_Latin1_General_CP1_CI_AS CHECK(LEN(UsersEmail) >= 3) NOT NULL,
ProjectsID INT NOT NULL,
CONSTRAINT ProjectsUsers_PK PRIMARY KEY (UsersEmail, ProjectsID),
CONSTRAINT ProjectsID_FK FOREIGN KEY (ProjectsID) REFERENCES Projects (ProjectID)
ON DELETE CASCADE ON UPDATE CASCADE ,
CONSTRAINT UsersEmail_FK FOREIGN KEY (UsersEmail) REFERENCES Users(Email)
ON DELETE CASCADE ON UPDATE CASCADE
);
I am now trying to create a stored procedure that will insert a new project to the Projects table. After I add the project I want to create a reference to it in the ProjectsUsers table. The problem is, there is no possible way for me to know what the id of the project I just created - thus, I am unable to know what ID should I insert into the ProjectsUsers.
So if my stored procedure was something like this:
INSERT INTO Projects (Project, CreationDate, ProjectName)
VALUES (#project, GETDATE(), #email);
INSERT INTO ProjectsUsers VALUES (#email, ???)
How can I get the ID?
Just use SCOPE_IDENTITY like this:
INSERT INTO Projects (Project, CreationDate, ProjectName)
VALUES (#project, SYSDATETIME(), #email);
DECLARE #ProjectID INT = SCOPE_IDENTITY();
INSERT INTO ProjectsUsers
VALUES (#email, #ProjectID)
More all the relevant details about SCOPE_IDENTITY on the official Microsoft Documentation site.
As Sean Lange mentions, you can use SCOPE_IDENTITY to get last id inserted from within your proc
You can also use the OUTPUT clause and get possibly many ids. You can output in the screen or in a table, but it wont work if you are selecting from a table that has triggers.
Use the OUTPUT clause! Do not use the various identity functions or variables. This directly solves your problem:
DECLARE #ids TABLE (ProjectId int);
INSERT INTO Projects (Project, CreationDate, ProjectName)
OUTPUT inserted.ProjectId INTO #ids;
VALUES (#project, GETDATE(), #email);
INSERT INTO ProjectsUsers (UsersEmail, ProjectId)
SELECT #email, ProjectId
FROM #ids;
All the other methods of returning the identity have peculiarities:
Perhaps they don't work when the insert has multiple statements.
Perhaps concurrent inserts mess up the value.
Perhaps they don't work well with triggers.

Having troubles with Identity field of SQL-SERVER

I'm doing a school project about a school theme where I need to create some tables for Students, Classes, Programmes...
I want to add a Group to determined classes with an auto increment in group_id however I wanted the group_id variable to reset if I change any of those attributes(Classes_id,courses_acronym,year_Semesters) how can I reset it every time any of those change??
Here is my table:
CREATE TABLE Classes_Groups(
Classes_id varchar(2),
Group_id INT IDENTITY(1,1),
courses_acronym varchar(4),
year_Semesters varchar(5),
FOREIGN KEY (Classes_id, year_Semesters,courses_acronym) REFERENCES Classes(id,year_Semesters, courses_acronym),
PRIMARY KEY(Classes_id,courses_acronym,year_Semesters,Group_id)
);
Normally, you do not (need to) reset the identity column of a table. An identity column is used to create unique values for every single record in a table.
So you want to generate entries in your groups table based on new entries in your classes table. You might create a trigger on your classes table for that purpose.
Since Group_id is already unique by itself (because of its IDENTITY), you do not need other fields in the primary key at all. Instead, you may create a separate UNIQUE constraint for the combination (Classes_id, courses_acronym, year_Semesters) if you need it.
And if the id field of your classes table is an IDENTITY column too, you could define a primary key in your classes table solely on that id field. And then your foreign key constraint in your new groups table can only include that Classes_id field.)
So much for now. I guess that your database design needs some more additional tuning and tweaking. ;)
where are you setting the values from?, you can have a stored proc and in your query have the columns have an initial value set when stored proc is hit assuming there are values at the beginning
.Then use an IF statement.
declare #initial_Classes_id varchar(2) = --initial value inserted
declare #initial_courses_acronym varchar(4) = --initial value inserted
declare #initial_year_Semesters varchar(5) = --initial value inserted
declare #compare_Classes_id varchar(2) = (select top 1 Classes_id from Classes_Groups order by --PK column desc for last insert); l would add Dateadded and then order with last insert date
declare #compare_courses_acronym varchar(2) = (select top 1 Classes_id from Classes_Groups where Classes_id = #compare_Classes_id);
declare #compare_year_Semesters varchar(2) = (select top 1 Classes_id from Classes_Groups where Classes_id = #compare_Classes_id);
IF (#initial_Classes_id != #compare_Classes_id OR #initial_courses_acronym != #compare_courses_acronym OR #initial_year_Semesters != #compare_year_Semesters)
BEGIN
DBCC CHECKIDENT ('Group_id', RESEED, 1)
Insert into Classes_Groups (courses_acronym,year_Semesters)
values (
courses_acronym,
year_Semesters
)
END
ELSE
BEGIN
Insert into Classes_Groups (courses_acronym,year_Semesters)
values (
courses_acronym,
year_Semesters
)
END
NB: would advice to use int on the primary key. Unless you have a specific purpose of doing so.

How to insert primary key from one table as a foreign key into secondary table

I am creating a sample database with two tables submissions and submittedItems. I am populating this table with sample data and I wanted to know how to populate the second table with the primary key from the first table.
The script I have works fine for what I am testing however I am currently inserting the foreign key by simply mirroring the count. Since this is a new table it works fine as both start with the same number. Where my question is what if the table already had data within it, How would I go about retrieving the PK of the last record entered into the submissions table? I know when using Identity I could use SELECT SCOPE_IDENTITY() to get the last identity entered but not sure of the proper select statement to use for anything else. OR am I misunderstanding the use of Scope_Identity() and it does retrieve whatever the last PK/Identity that was entered? As you can see I am no expert at sql so if there is a better approach I would welcome any suggestions.
Thanks in advance,
use SampleRecords
GO
--create two test tables
CREATE TABLE submissions
(submission_id int Identity(1,1) primary key not null,
submissionName varchar(150),
dateSubmitted datetime)
CREATE TABLE submissionItems
(submissionitems_id int identity(1,1) primary key,
fk_submission_id int not null,
item varchar(150),
CONSTRAINT fk_submission_id foreign key (fk_submission_id) references submissions (submission_id))
--populate tables with sample data
DECLARE #totalRecords int
SET #totalRecords = 0
DECLARE #currentKey int
WHILE #totalRecords < 500
BEGIN
SET #totalRecords = #totalRecords + 1
INSERT INTO dbo.submissions (submissionName, dateSubmitted)
VALUES
('submission record ' + cast(#totalRecords AS varchar(3)), SYSDATETIME())
INSERT INTO dbo.submissionItems (fk_submission_id, item)
VALUES
(#totalRecords, 'a new record item for submission '+ cast(#totalRecords AS varchar(3)))
-- I tried using scope_identity as follows but could not get the syntax correct
-- ('submission record ' + cast(Select Scope_Identity() AS varchar(3)), SYSDATETIME())
END
Yes, just use the ScopeIdentity...
--populate tables with sample data
DECLARE #totalRecords int
SET #totalRecords = 0
DECLARE #currentKey int
WHILE #totalRecords < 500
BEGIN
SET #totalRecords = #totalRecords + 1
INSERT INTO dbo.submissions (submissionName, dateSubmitted)
VALUES ('submission record ' + cast(#totalRecords AS varchar(3)), SYSDATETIME())
Set #currentKey = Scope_Identity()
INSERT INTO dbo.submissionItems (fk_submission_id, item)
VALUES (#currentKey, 'a new record item for submission '+ cast(#totalRecords AS varchar(3)))
END

Select from another table within an Insert Trigger

I am maintaining an audit table, where in I have a parent table and it's child table.I want to insert the primary key of the parent audit table into it's child audit table.
Should I be declaring a "before insert" instead of a "for insert" trigger. Here's my code:
CREATE trigger [trgAudtblChild] On [tblChild]
for Insert
as
BEGIN
declare #serNo bigint
declare #expSerNo int
declare #postPercent numeric (12, 2)
declare #prdSAPid varchar (50)
declare #lastUpdatedBy int
declare #lastUpdatedOn smalldatetime
SELECT
--#serno = serno,
#expSerNo = expSerNo ,
#postPercent = postPercent ,
#prdSAPid = prdSAPid ,
#lastUpdatedBy = lastUpdatedBy ,
#lastUpdatedOn = lastUpdatedOn
FROM INSERTED
select #serno = max(at_serno) from AT_tblParent
insert into AT_tblChild(serNo, expSerNo, postPercent
, prdSAPid, lastUpdatedBy, lastUpdatedOn
, change_column_index) values(
#serNo, #expSerNo, #postPercent
, #prdSAPid, #lastUpdatedBy, #lastUpdatedOn
, 'INSERTED')
End
Return
The above code, does not work and puts the table into transaction.
Before Trigger - When you want to Intercept the data before it actually gets Inserted in Table.
For Trigger - Your record is Inserted but can still modify it.
The only difference is that about record is actually Inserted or not.
Back to the original Query
In you above mentioned situation, you should not use Before Trigger. Consider a case, when your Parent Table record Insertion in under some Transaction and same Transaction gets Rollbacked. In that case, It will crash for the Foreign key constraint. Because you will try to Reference a Foreign key Record of Parent Table into Child Table during Insertion which does not exist in Parent Table.