How to get the auto-generated primary key after insertion in stored procedure? - sql

My SQL Server table:
[dbo].[Rep] (
[rep_ID] INT IDENTITY (300, 1) NOT NULL,
[Restaurant_ID] INT NULL,
[Fname] VARCHAR (50) NOT NULL,
[Lname] VARCHAR (50) NOT NULL,
CONSTRAINT [PK_Rep_ID] PRIMARY KEY CLUSTERED ([rep_ID] ASC),
CONSTRAINT [FK_Restaurant_ID] FOREIGN KEY ([Restaurant_ID]) REFERENCES [dbo].[Restaurants] ([ID])
);
I want to create a stored procedure that return the auto generated key for the inserted record.
My current stored procedure:
CREATE PROCEDURE [dbo].[createRepAcc]
#first varchar(50),
#last varchar(50)
AS
INSERT INTO Rep([Fname], [Lname])
OUTPUT inserted.rep_ID
VALUES (#first, #last);
It's able to insert into the table but only return 1 instead of the primary key generated.
What am I doing wrong?

You can use scope_identity() to get the last generated id. For your case here is a detailed worksheet
/* creating a simple table with identity column */
CREATE TABLE dbo.a(identity_column INT IDENTITY(300,1), x CHAR(1));
/* Procedure that inserts values and returns generated output*/
CREATE PROCEDURE [dbo].[ap]
#x char(1),
#id int output
AS
INSERT INTO a(x) VALUES (#x);
select #id = SCOPE_IDENTITY();
/* This is how the procedure could be called */
declare #ident int -- declare a variable to receive output
execute dbo.ap #x='b', #id=#ident output -- execute or call the procedure
select #ident -- select or print the genereated id

Related

SQL Trigger on Insert to call a Function and Manipulate Values

I am having a problem knowing set up a trigger on insert to call a function and passing an identifier SiteID to that function which then operates on variables from another table.
I have the table, where values are inserted:
CREATE TABLE [dbo].[Tests] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[SiteID] NVARCHAR (128) NOT NULL,
[Date] NVARCHAR (MAX) NULL,
[Time] NVARCHAR (MAX) NULL,
[Tub] NVARCHAR (MAX) NULL,
[FCl] FLOAT (53) NOT NULL
PRIMARY KEY CLUSTERED ([Id] ASC)
);
Every time a value is inserted in to the Tests table I would like a function to be called which uses the table Review to perform a simple calculation (see the trigger down the post below):
CREATE TABLE [dbo].[Review] (
[SiteID] NVARCHAR (128) NOT NULL,
[TubNum] INT NOT NULL,
[Supplied] INT NULL,
[Performed] INT NULL,
[Remaining] INT NULL
PRIMARY KEY CLUSTERED ([SiteID] ASC)
);
This is my sqlfiddle so far, however, I am unable to save it with the functions I am working on, which are here:
The trigger - not sure how to pass the SiteID for the insert or call the function:
CREATE TRIGGER [dbo].[TRIG_MyTable]
ON [dbo].[Tests]
AFTER INSERT
AS
CALL CalcRemaining() //how to pass it SiteID?
and the the function itself:
CREATE FUNCTION [dbo].[CalcRemaining](#ID NVARCHAR (128))
RETURNS NULL
AS
BEGIN
SELECT (Supplied, Performed FROM Review WHERE SiteID = ID);
Performed = Performed + 1;
INSERT INTO Review (Performed, Remaining) VALUES (Performed, (Supplied-Performed))
RETURN;
END
The idea is that the SiteID from the inserted line is passed to the function when called, the function then selects the values Supplied and Performed for that matching SiteID from the Review table. The Performed value is incremented by 1 and that new value along with the retrieved Supplied value are subtracted and written to the Remaining field in the Review table.
If the assumptions I've asked about in the comments are valid (that Remaining and Performed can always be calculated), here's how I'd implement your database structure, with no trigger nor function:
Base tables:
CREATE TABLE dbo.Tests (
[Id] INT IDENTITY (1, 1) NOT NULL,
[SiteID] NVARCHAR (128) NOT NULL,
[Date] NVARCHAR (MAX) NULL,
[Time] NVARCHAR (MAX) NULL,
[Tub] NVARCHAR (MAX) NULL,
[FCl] FLOAT (53) NOT NULL
PRIMARY KEY CLUSTERED ([Id] ASC)
);
GO
CREATE TABLE dbo._Review (
[SiteID] NVARCHAR (128) NOT NULL,
[TubNum] INT NOT NULL,
[Supplied] INT NULL,
PRIMARY KEY CLUSTERED ([SiteID] ASC)
);
Then a view that calculates Performed:
CREATE VIEW dbo._Tests_Count
WITH SCHEMABINDING
AS
SELECT
SiteID,
COUNT_BIG(*) as Performed
FROM
dbo.Tests t
GROUP BY SiteID
GO
CREATE UNIQUE CLUSTERED INDEX IX_Tests_Count ON dbo._Tests_Count (SiteID)
And finally a view that re-creates the original Review table:
CREATE VIEW dbo.Review
WITH SCHEMABINDING
AS
SELECT
r.SiteID,
r.TubNum,
r.Supplied,
COALESCE(tc.Performed,0) as Performed,
r.Supplied - COALESCE(tc.Performed,0) as Remaining
FROM
dbo._Review r
left join
dbo._Tests_Count tc WITH (NOEXPAND)
on
r.SiteID = tc.SiteID
GO
If needed, at this point a trigger could be created on this Review view to allow any INSERTs, DELETEs and UPDATEs to be performed against it rather than _Review, if you cannot change some calling code.
You have to be completely sure you're manipulating ONLY one row at a time!
CREATE TRIGGER [dbo].[TRIG_MyTable]
ON [dbo].[Tests]
AFTER INSERT
AS
DECLARE #SiteID NVARCHAR (128)
SELECT #SiteID = ID FROM inserted
CALL CalcRemaining(#SiteID)

Insert into two tables at the same time insert new record

I have two SQL Server tables to work with in my database.
Here is my table VMA_VehicleDetails_TB:
CREATE TABLE [dbo].[VMA_VehicleDetails_TB]
(
[VehRegID] INT IDENTITY (1000, 2) NOT NULL,
[TraPNumber] NVARCHAR (60) NOT NULL,
[VehOwner] NVARCHAR (60) NOT NULL,
[RegExpDate] DATE NOT NULL,
[InsExpDate] DATE NOT NULL,
[VehModel] NVARCHAR (120) NOT NULL,
[VehOrigin] NVARCHAR (120) NOT NULL,
[VehType] NVARCHAR (80) NOT NULL,
PRIMARY KEY CLUSTERED ([VehRegID] ASC)
);
Here is my table VMA_VehDrvAssigned_TB:
CREATE TABLE [dbo].[VMA_VehDrvAssigned_TB]
(
[VehRegID] INT DEFAULT ((0)) NOT NULL,
[DrvRegID] INT DEFAULT ((0)) NOT NULL,
[IsAssigned] BIT DEFAULT ((0)) NOT NULL,
CONSTRAINT [PK_VMA_VehDrvAssigned_TB] PRIMARY KEY CLUSTERED ([VehRegID] ASC)
);
I have use this stored procedure to add new registered vehicle id to the VMA_VehDrvAssigned_TBtable. It is working fine.
ALTER PROCEDURE [dbo].[addNewVehicleDetail_SP]
#TraPNumber NVARCHAR (60)
,#VehOwner NVARCHAR (60)
,#RegExpDate DATE
,#InsExpDate DATE
,#VehModel NVARCHAR (120)
,#VehOrigin NVARCHAR (120)
,#VehType NVARCHAR (80)
,#IsAssigned BIT
,#DrvRegID VARCHAR(60)
AS
BEGIN
SET NOCOUNT ON;
-- Insert statements for procedure here
INSERT INTO [VMA_VehicleDetails_TB] (TraPNumber, VehOwner, RegExpDate, InsExpDate, VehModel, VehOrigin, VehType)
VALUES (#TraPNumber, #VehOwner, #RegExpDate, #InsExpDate, #VehModel, #VehOrigin, #VehType)
INSERT INTO VMA_VehDrvAssigned_TB (VehRegID)
SELECT
VehRegID = scope_identity();
END
Now, I want to add #IsAssigned and #DrvRegID to the same table while insert new record. But, I only know to add single column to the table. Did I something wrong??
Just modify last INSERT.
ALTER PROCEDURE [dbo].[addNewVehicleDetail_SP]
-- Add the parameters for the stored procedure here
#TraPNumber NVARCHAR (60)
,#VehOwner NVARCHAR (60)
,#RegExpDate DATE
,#InsExpDate DATE
,#VehModel NVARCHAR (120)
,#VehOrigin NVARCHAR (120)
,#VehType NVARCHAR (80)
,#IsAssigned BIT
,#DrvRegID VARCHAR(60)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
INSERT INTO [VMA_VehicleDetails_TB] (TraPNumber,VehOwner,RegExpDate,InsExpDate,VehModel,VehOrigin,VehType)
VALUES (#TraPNumber,#VehOwner,#RegExpDate,#InsExpDate,#VehModel,#VehOrigin,#VehType)
INSERT INTO VMA_VehDrvAssigned_TB (VehRegID, DrvRegID, IsAssigned )
SELECT scope_identity(), #DrvRegID, #IsAssigned ;
END

Why isn't my Auto Increment working in SQL Server 2008?

This is my table creation:
create table Movie
(
MovieID int NOT NULL IDENTITY (1,1) PRIMARY KEY,
MovieName varchar(40) NOT NULL UNIQUE,
CurrentStock int NOT NULL,
GenreID int NOT NULL,
RatingID int NOT NULL,
Max_Inventory int NOT NULL,
Platforms char(5) NOT NULL,
Discontinued bit,
DiscontinuedDate Date
);
create table Inventory
(
InventoryID int NOT NULL IDENTITY (1,1) PRIMARY KEY,
MovieID int Not NULL,
CurrentStock int NOT NULL,
Max_Inventory int NOT NULL
);
Stored procedures:
ALTER PROCEDURE [dbo].[InsInventory]
(#CurrentStock int,
#ChangeStock int)
as
begin
insert into Inventory(Max_Inventory, CurrentStock)
Values (#ChangeStock, #CurrentStock)
select SCOPE_IDENTITY();
END
ALTER PROCEDURE [dbo].[InsMovie]
(#GenreID int,
#RatingID int,
#Platform varchar(5),
#MovieName varchar(40)
)
AS
BEGIN
Insert into Movie (RatingID, MovieName, Platforms, GenreID)
Values (#RatingID, #MovieName, #Platform, #GenreID)
select SCOPE_IDENTITY();
SET NOCOUNT ON;
END
Foreign key:
ALTER Table Inventory
ADD CONSTRAINT fk_Inventory_Movie
FOREIGN KEY (MovieID) REFERENCES Movie(MovieID)
ALTER TABLE Movie
ADD CONSTRAINT fk_Movie_RatingLookUp
FOREIGN KEY (RatingID) REFERENCES RatingLookUp(RatingID)
ALTER TABLE Movie
ADD CONSTRAINT fk_Movie_GenreLookUp
FOREIGN KEY (GenreID) REFERENCES GenreLookUp (GenreID)
When I run my code I keep getting the error in Visual Studio
MovieID cannot be null
but it should be when I insert a row. I also made sure to manually check to see if SQL Server had the IsIdentity set, which it is. So please help a confused programmer out.
You shouldn't insert NULL as a primary key to make it generate a value, you should just don't insert that value at all by not listing it among the fields to insert. As a sample;
INSERT INTO Movie (moviename, currentstock, genreid, ratingid, max_inventory, platforms)
VALUES ('name1', 1, 1, 1, 1, '1');
A simple working sample with your exact table creation.
Below statement is your problem. your table def shows MovieID not null. but in below statement you didn't provide that.
insert into Inventory(Max_Inventory, CurrentStock)
Values (#ChangeStock, #CurrentStock)
here is what you need to do.. first you need to retrieve Movie id which will be return from executing InsMovie sproc. than you need to use that Movie Id as a prameter to InsInvetory sproc call.
according to your table def movie id is required. also for Movie table you missed two column values that i have added which are required as well.
Please see blow updated stored procedures.
ALTER PROCEDURE [dbo].[InsInventory]
(
#CurrentStock int,
#ChangeStock int,
#MovieID int
)
as
begin
insert into Inventory(MovieID, Max_Inventory,CurrentStock)
Values (#MovieID, #ChangeStock, #CurrentStock)
select SCOPE_IDENTITY();
END
ALTER PROCEDURE [dbo].[InsMovie]
(
#GenreID int,
#RatingID int,
#Platform varchar(5),
#MovieName varchar(40),
#CurrentStock int,
#max_inventory int
)
AS
BEGIN
Insert into Movie (CurrentStock, max_inventory, RatingID, MovieName, Platforms,GenreID)
Values(#CurrentStock, #max_inventory, #RatingID,#MovieName, #Platform, #GenreID)
select SCOPE_IDENTITY();
SET NOCOUNT ON;
END

How i can change and run sql file into mssql

I have my database in sqlite .I exported sql file from sqlite manager. Now on executing that file into Microsoft SQL Server 2012 it is giving error on following lines.
DROP TABLE
IF EXISTS "Admin";
CREATE TABLE "AdvancePayments" (
"Id" INT PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE,
"date" VARCHAR,
"Name" VARCHAR,
"Amount" INT,
"Remarks" VARCHAR);
INSERT INTO "AdvancePayments"
VALUES (
1,
'11/22/2013',
'wqqw',
21,
'fgdsr');
CREATE TABLE "DVouchers" (
"DVid" INT PRIMARY KEY NOT NULL,
"vdate" VARCHAR DEFAULT(NULL),
"Vehiclenum" VARCHAR,
"Coupen" BOOL,
"Saleperson" VARCHAR,
"DVnumber" INT,
"Ares" VARCHAR,
"Ctitle" VARCHAR,
"remarks" VARCHAR,
"mEntry" BOOL,
"Cust_Id" INT,
FOREIGN KEY (Cust_Id) REFERENCES Customer_New(Cust_Id));
What is correct syntax for mssql?
You should write it as:
--DROP TABLE IF EXISTS Admin;
--query to drop a table
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[TableName]') AND type in (N'U'))
DROP TABLE [dbo].[TableName]
GO
CREATE TABLE [AdvancePayments]
(
[Id] INT IDENTITY(1,1) PRIMARY KEY NOT NULL ,--The MS SQL Server uses the IDENTITY keyword to perform an auto-increment feature
[date] VARCHAR(10),-- best practice is to use datetime datatype to store date feilds.
[Name] VARCHAR(100),
[Amount] INT,
[Remarks] VARCHAR(1000)
);
INSERT INTO AdvancePayments
VALUES (
--1,-- you cannot give an explicit value to identity column untill IDENTITY_INSERT is ON. So comment this.
'11/22/2013',
'wqqw',
21,
'fgdsr');
CREATE TABLE [DVouchers] (
[DVid] INT PRIMARY KEY NOT NULL,
[vdate] VARCHAR(20) DEFAULT(NULL),
[Vehiclenum] VARCHAR(100),
[Coupen] BIT,-- Bit is the datatype used for Boolean values.
[Saleperson] VARCHAR(100),
[DVnumber] INT,
[Ares] VARCHAR(100),
[Ctitle] VARCHAR(100),
[remarks] VARCHAR(100),
[mEntry] BIT,
[Cust_Id] INT,
FOREIGN KEY (Cust_Id) REFERENCES Customer_New(Cust_Id)
);
Note: In MS SQL default length of varchar datatype is 1. so you will have to specify length to each
varchar variable.
TSQL:
IF NOT OBJECT_ID('dbo.TableToDrop') IS NULL
BEGIN
DROP TABLE dbo.TableToDrop
END;
// change dbo. to your schema if necessary

Multilingual database design

I'm trying to design a database schema for a multilingual application. I have so far found a sample from this address. http://fczaja.blogspot.com/2010/08/multilanguage-database-design.html
But I haven't understood this sample. Should I insert Id value on app_product first? How can I know that these values are true for ProductId on app_product_translation?
CREATE TABLE ref_language (
Code Char(2)NOT NULL,
Name Varchar(20) NOT NULL,
PRIMARY KEY (Code)
);
CREATE TABLE app_product (
Id Int IDENTITY NOT NULL,
PRIMARY KEY (Id)
);
CREATE TABLE app_product_translation (
ProductId Int NOT NULL,
LanguageCode Char(2) NOT NULL,
Description Text NOT NULL,
FOREIGN KEY (ProductId) REFERENCES app_product(Id),
FOREIGN KEY (LanguageCode) REFERENCES ref_language(Code)
);
It looks like SQLServer code, proceeding on that assumption.
Yes you must insert the app_product first. But you cannot insert the id column's value. It is assigned automatically, because it is an identity column.
Two things you can check out...to find the identity column's value after inserting.
The OUTPUT clause of the INSERT statement. It can return any values that are inserted, not just the identity column.
The ##Identity variable. (by far more traditional and popular)
declare #lastid int
insert into x values (1,2,3)
set #lastid = ##identity
insert into y values (#lastid, a, b, c)