Get AutoIncrement ID and insert into Foreign Key Table - sql

I have 3 tables User, Profile and ProfilePicture. Profile and ProfilePicture have a foreign key relation with User table. What I want to do here is whenever I insert data into the User table through web application their AutoGeneratedID get and inserted into Profile and ProfilePicture tables.
CREATE TABLE User
(
UserId INT(11) NOT NULL AUTO_INCREMENT,
Username VARCHAR(45) NOT NULL,
Password VARCHAR(50) NOT NULL,
PRIMARY KEY (`UserId`),
UNIQUE INDEX `UserIdId_UNIQUE` (`UserId` ASC)
);
CREATE TABLE Profile
(
UserId INT(11) NOT NULL,
Firstname VARCHAR(50) NULL,
Lastname VARCHAR(50) NULL,
FOREIGN KEY (UserId) REFERENCES User (UserId)
)
CREATE TABLE ProfilePicture
(
UserId INT(11) NOT NULL,
Picture image NULL,
insertdate date NULL,
FOREIGN KEY (UserId) REFERENCES User (UserId)
)
I know I have to use a trigger but I don't understand how to do this.

I am supposing that you are doing this using stored procedure or raw queries. This thing can be achieved by using OUTPUT clause.
Define a local table with column Id
DECLARE #OutputTbl TABLE (ID INT)
Now when you save the User then insert the new gnerated id into #OutputTbl
INSERT INTO User (Username, Password)
OUTPUT INSERTED.UserId INTO #OutputTbl(ID)
VALUES ('name', 'password')
Now when you need this id in Profile/ProfilePicture, get this id from local table
insert into Profile (
UserId ,
Firstname,
Lastname) Values ((Select ID from #OutputTbl),'fName','lName')

You can try something as below :
CREATE TABLE #tempUser(
UserId INT,
ShopRef INT
)
INSERT INTO [User] (UserPassword,Name,MobileNo,Gender,Dob,Country,State,City,StreetAddress
,ZipCode,IsActive
,CreatedDate,ModifiedBy,CreatedBy,IsAdmin,EmailOtp,UserImage,Rating
,ContactNo)
OUTPUT inserted.UserId, inserted.EmailOtp INTO #tempUser
SELECT 'NA', [Name], [MobileNo], '-','1900-01-01',[Country],[State],[City],[StreetAddress],
[ZipCode], 1
,#Date,#UserId,#UserId,0,ID,'NA',0
,'NA'
FROM #temp WHERE Status ='SUCCESS'
If you are executing these inserts in the same SP then you can use, make sure UserId is an Identity Column :
SET #UserId = SCOPE_IDENTITY()

you can after insert into table, call SCOPE_IDENTITY() function, to get the latest
identity inserted
for more informatin see:
https://msdn.microsoft.com/en-us/library/ms190315.aspx
http://www.codeproject.com/Articles/103610/Difference-between-IDENTITY-SCOPE-IDENTITY-IDENT-C

Related

How to save auto generated primary key Id in foreign key column in same table

Following is the table structure:
CREATE TABLE [User] (
[Id] bigint identity(1,1) not null,
[FirstName] nvarchar(100) not null,
[LastName] nvarchar(100) not null,
[Title] nvarchar(5) null,
[UserName] nvarchar(100) not null,
[Password] nvarchar(100) not null,
[Inactive] bit null,
[Created] Datetime not null,
[Creator] bigint not null,
[Modified] DateTime null,
[Modifier] bigint null
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
(
[Id] Asc
)
);
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[FK_User_Creator]') AND parent_object_id = OBJECT_ID(N'[User]'))
ALTER TABLE [User] ADD CONSTRAINT [FK_User_Creator] FOREIGN KEY([Creator]) REFERENCES [User]([Id])
GO
INSERT INTO [User] (Creator) Values ([Id] ?)
This is a case when table is empty and first user is going to add in table. Otherwise I don't have issue.
How can I insert Id in creator column with insert statement at the same time?
One way could be using Sequence instead of identity column. The below script might serve the same purpose:
CREATE SEQUENCE dbo.useridsequence
AS int
START WITH 1
INCREMENT BY 1 ;
GO
CREATE TABLE [User] (
[Id] bigint DEFAULT (NEXT VALUE FOR dbo.useridsequence) ,
[FirstName] nvarchar(100) not null,
[LastName] nvarchar(100) not null,
[Title] nvarchar(5) null,
[UserName] nvarchar(100) not null,
[Password] nvarchar(100) not null,
[Inactive] bit null,
[Created] Datetime not null,
[Creator] bigint DEFAULT NEXT VALUE FOR dbo.useridsequence ,
[Modified] DateTime null,
[Modifier] bigint null
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
(
[Id] Asc
)
);
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[FK_User_Creator]') AND parent_object_id = OBJECT_ID(N'[User]'))
ALTER TABLE [User] ADD CONSTRAINT [FK_User_Creator] FOREIGN KEY([Creator]) REFERENCES [User]([Id])
GO
INSERT INTO [User]
(
-- Id -- this column value is auto-generated
FirstName,
LastName,
Title,
UserName,
[Password],
Inactive,
Created,
Creator,
Modified,
Modifier
)
VALUES
(
'Foo',
'Bar',
'Title',
'UserName ',
'Password',
0,
GETDATE(),
DEFAULT,
GETDATE(),
1
)
SELECT * FROM [User] AS u
Result :
The short answer is that you can't do this. And I suggest your model is logically flawed in the first place. Do you intend to define all actual database users (e.g., create user ... for login ...) as rows in [Users]? You need to think about that - but the typical answer is no. If the answer is yes, then you don't need the creator column at all because it is redundant. All you need is the created date - for which you probably should have defined a default.
But if you want to do this, you will need to do it in two steps (and you will need to make the column nullable). You insert a row (or rows) with values for the "real" data columns. Then update those same rows with the identity values generated for id. An example showing different ways to do this
use tempdb;
set nocount on;
CREATE TABLE dbo.[user] (
[user_id] smallint identity(3,10) not null primary key,
[name] nvarchar(20) not null,
[active] bit not null default (1),
[created] Datetime not null default (current_timestamp),
[creator] smallint null
);
ALTER TABLE dbo.[user] ADD CONSTRAINT [fk_user] FOREIGN KEY(creator) REFERENCES dbo.[user](user_id);
GO
-- add first row
insert dbo.[user] (name) values ('test');
update dbo.[user] set creator = SCOPE_IDENTITY() where user_id = SCOPE_IDENTITY()
-- add two more rows
declare #ids table (user_id smallint not null);
insert dbo.[user] (name) output inserted.user_id into #ids
values ('nerk'), ('pom');
update t1 set creator = t1.user_id
from #ids as newrows inner join dbo.[user] as t1 on newrows.user_id = t1.user_id;
select * from dbo.[user] order by user_id;
-- mess things up a bit
delete dbo.[user] where name = 'pom';
-- create an error, consume an identity value
insert dbo.[user](name) values (null);
-- add 2 morerows
delete #ids;
insert dbo.[user] (name) output inserted.user_id into #ids
values ('nerk'), ('pom');
update t1 set creator = t1.user_id
from #ids as newrows inner join dbo.[user] as t1 on newrows.user_id = t1.user_id;
select * from dbo.[user] order by user_id;
drop table dbo.[user];
And I changed the identity specification to demonstrate something few developers realize. It isn't always defined as (1,1) and the next inserted value can jump for many reasons - errors and caching/restarts for example. Lastly, I think you will regret naming a table with a reserved word since references to it will require the use of delimiters. Reduce the pain.

How to properly configure database schema & inserts

So I have the following schema.
CREATE TABLE user_group (
id BIGINT PRIMARY KEY NOT NULL,
user_id BIGINT NOT NULL,
group_table_id BIGINT NOT NULL,
role VARCHAR(255),
CONSTRAINT user_group_user_id_fk FOREIGN KEY (user_id) REFERENCES user(id),
CONSTRAINT user_group_group_table_id_fk FOREIGN KEY (group_table_id) REFERENCES group_table(id)
);
CREATE TABLE group_table
(
id BIGINT PRIMARY KEY NOT NULL,
group_name VARCHAR(255),
group_picture_url VARCHAR(255),
tags VARCHAR(255),
description VARCHAR(255),
event_id BIGINT,
user_group_id BIGINT,
CONSTRAINT group_table_user_group_id_fk FOREIGN KEY (user_group_id) REFERENCES user_group(id)
);
CREATE TABLE user (
id BIGINT PRIMARY KEY NOT NULL,
display_name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
description TEXT NOT NULL,
picture_url VARCHAR(255),
user_group_id BIGINT,
event_response_id BIGINT,
CONSTRAINT user_user_group_id_fk FOREIGN KEY (user_group_id) REFERENCES user_group(id),
);
How can I make it so that this is a valid statement? In the sense that I should be able to create a user_group table, group_table table, or user table without needing the others.
The other question that I have is. Say this statement is valid and the tables exist. How would I insert data into user_group?
INSERT INTO user_group VALUES (1, 2, 3, 'role')
Would require that both a group_table and a user with id's of 2 and 3 respectively already exist upon insert of the value.
How can I make it so that this is a valid statement? In the sense that I should be able to create a user_group table, group_table table, or user table without needing the others.
You can create the tables first, and create the foreign key constraints after. If you try to do both at the same time (like you currently have), you run into a chicken and egg situation.
Here is an example of how you could do it:
CREATE TABLE user_group (
id BIGINT PRIMARY KEY NOT NULL,
user_id BIGINT NOT NULL,
group_table_id BIGINT NOT NULL,
role VARCHAR(255)
);
CREATE TABLE group_table
(
id BIGINT PRIMARY KEY NOT NULL,
group_name VARCHAR(255),
group_picture_url VARCHAR(255),
tags VARCHAR(255),
description VARCHAR(255),
event_id BIGINT,
user_group_id BIGINT
);
CREATE TABLE user (
id BIGINT PRIMARY KEY NOT NULL,
display_name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
description TEXT NOT NULL,
picture_url VARCHAR(255),
user_group_id BIGINT,
event_response_id BIGINT
);
alter table user_group
add constraint user_group_user_id_fk
foreign key (user_id)
references user(id);
alter table user_group
add constraint user_group_group_table_id_fk
foreign key (group_table_id)
REFERENCES group_table(id);
alter table group_table
add constraint group_table_user_group_id_fk
FOREIGN KEY (user_group_id)
REFERENCES user_group(id);
alter table user
add constraint user_user_group_id_fk
FOREIGN KEY (user_group_id)
REFERENCES user_group(id);
The other question that I have is. Say this statement is valid and the tables exist. How would I insert data into user_group?
INSERT INTO user_group VALUES (1, 2, 3, 'role')
Would require that both a group_table and a user with id's of 2 and 3 respectively already exist upon insert of the value.
Yes, the corresponding rows in user (id = 2) and group (id = 3) would have to be inserted prior to attempting the insert into user_group.

Locking Order of table with foreign key constraint?

If I create a schema such as the following:
create table org
(
org_id bigint not null auto_increment,
name varchar(255) not null,
primary key(org_id)
);
create table user
(
user_id bigint not null auto_increment,
name varchar(255) not null,
org_id bigint not null,
primary key(user_id),
foreign key(org_id) references org (org_id)
);
Where the org table has one entry:
insert into org (name) values ('org 1');
If I run the following sql statement:
insert into user (name, org_id) values ('user 1', 1);
In what order will the tables be locked? Is it deterministic? What if there were a second foreign key constraint to another table?

Foreign Key Not Populating with Primary Key Values

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)

autoincrement in access sql is not working

How can I create a table with autoincrement in access. Here is what I have been doing but not working.
CREATE TABLE People_User_Master(
Id INTEGER primary key AUTOINCREMENT,
Name varchar(50),
LastName varchar(50),
Userid varchar(50) unique,
Email varchar(50),
Phone varchar(50),
Pw varchar(50),
fk_Group int,
Address varchar(150)
)
Remove INTEGER (it conflicts with AUTOINCREMENT)
CREATE TABLE People_User_Master(
Id AUTOINCREMENT primary key ,
Name varchar(50),
LastName varchar(50),
Userid varchar(50) unique,
Email varchar(50),
Phone varchar(50),
Pw varchar(50),
fk_Group int,
Address varchar(150)
)
Try adding the constraint at the end
CREATE TABLE People_User_Master(
Id AUTOINCREMENT
, Name varchar(50)
, LastName varchar(50)
, Userid varchar(50) unique
, Email varchar(50)
, Phone varchar(50)
, Pw varchar(50)
, fk_Group int
, Address varchar(150)
, CONSTRAINT id_pk PRIMARY KEY(Id)
)
Updated to fit the actual answer (the definition of INTEGER on the AUTOINCREMENT column was not allowed). Leaving PRIMARY KEY at the same line as Id AUTOINCREMENT does work.
You can do it using IDENTITY (supported by Jet4+)
CREATE TABLE People_User_Master
(
ID IDENTITY (1, 1),
Name ..
Failing that;
ID AUTOINCREMENT,
Should work (note you don't specify a type)
It may be working, but appears to fail if attempting an INSERT INTO with ID in the Column clause. This seems to override MS Access AUTOINCREMENT.
This attempts to insert a record with ID=1 bypassing AUTOINCREMENT
INSERT INTO People_User_Master
(Id, Name, LastName, Userid, Email, Phone, Pw, fk_Group, Address)
VALUES (1, "John", "Smith", "JS100", "JS#MyMail.Net", 12345678, "****","","")
Omitting ID lets AUTOINCREMENT function properly.
INSERT INTO People_User_Master
(Name, LastName, Userid, Email, Phone, Pw, fk_Group, Address)
VALUES ("John", "Smith", "JS100", "JS#MyMail.Net", 12345678, "****","","")