SQL Insert With Unique Constraint using Stored Procedure - sql

This is a generic question with a specific example.
I have a table with three fields (genreID (PK IDENTITY), genre, and subGenre). The table has a unique constraint on (genre, subGenre) combination.
I am wondering how I could go about modifying the stored procedure to insert if it DOES NOT exist in the table, otherwise return the genreID of the existing genre if it DOES exist.
CREATE PROCEDURE spInsertGenre
#genreID int OUTPUT,
#genre varchar(100),
#subGenre varchar(100)= NULL
AS
BEGIN
INSERT INTO Genre
(
genre,
subGenre
)
Values (
#genre,
#subGenre
)
SELECT #genreID = SCOPE_IDENTITY()
END
GO

You can try to select the row that would be inserted by your SP before you do the insert:
CREATE PROCEDURE spInsertGenre
#genreID int OUTPUT,
#genre varchar(100),
#subGenre varchar(100)= NULL
AS
BEGIN
-- if the row to be inserted already exists, put the genreID into the #genreID output parameter
SELECT #genreID = genreID
FROM Genre
WHERE genre = #genre
AND subGenre = #subGenre
IF #genreID IS NULL -- if the genreID was not found, do an insert and select the new genreID to the #genreID output parameter
BEGIN
INSERT INTO Genre
(
genre,
subGenre
)
Values (
#genre,
#subGenre
)
SELECT #genreID = SCOPE_IDENTITY()
END
END
GO

Related

Doing a for-each record in a user defined table type in Stored Procedure

:)
I have this defined type:
CREATE TYPE dbo.MyType
AS TABLE
(
name varchar(255),
value varchar(255)
);
Having this stored procedure:
CREATE PROCEDURE MyProcedure #docName varchar(255), #docPath varchar(255), #values AS [dbo].MyType Readonly
AS
declare #ID table (ID int)
INSERT INTO MyTable output inserted.fileID into #ID values (#docName,#docPath)
-- insert loop here
GO;
And the following "one to many" table
CREATE TABLE TableN (
fileID int PRIMARY KEY,
name varchar(255),
value varchar(255)
)
How can I, where it is noted in the above code, make a loop in order to for each record in the MyType table, to insert it into TableN, together with the fileID from the insert?
Thanks!
There's no need for a loop (you need to stop thinking programmatically in SQL and think in datasets). Just do an INSERT:
INSERT INTO TableN (FileID,[name],[value])
SELECT ID.ID,
V.[Name],
V.[value]
FROM #values v
CROSS JOIN #ID ID;

Return inserted row from stored procedure

I have the following stored procedure
CREATE PROCEDURE [dbo].[spInsert]
#name nvarchar(128),
AS
insert into NameIdentifier
( Name, Identifier)
values
( #name, NEWID());
SELECT #new_identity = SCOPE_IDENTITY()
SELECT * FROM NameAge where Id = #new_identity
Is there are a more efficient way to return the last inserted record complete with id and associated data?
Use Insertedwithin output clause,
As the follwoing:
CREATE PROCEDURE [dbo].[spInsert]
#name nvarchar(128),
AS
DECLARE #MyTableVar table(
Name varchar(50),
Identifier uniqueidentifier
;
insert into NameIdentifier
( Name, Identifier)
values
( #name, NEWID());
OUTPUT INSERTED.Name, INSERTED.Identifier
INTO #MyTableVar
SELECt Name,Identifier from #MyTableVar
Refreance:
Best way to get identity of inserted row?
SCOPE_IDENTITY() is used to get the last generated Identity value in an identity column in your scope , For GUID values either you get the guid before you insert it like I have done in the code below , or you use OUTPUT clause to get the guid generated by the Insert statement.
CREATE PROCEDURE [dbo].[spInsert]
#name nvarchar(128)
AS
BEGIN
SET NOCOUNT ON;
Declare #NewID UNIQUEIDENTIFIER = NEWID();
insert into NameIdentifier ( Name, Identifier)
values( #name, #NewID);
SELECT * FROM NameAge where Id = #NewID;
END
This should give you your desired functionality.
CREATE PROCEDURE [dbo].[spInsert]
#name nvarchar(128),
#Ret int Output
AS
BEGIN
insert into NameIdentifier
( Name, Identifier)
values
( #name, NEWID());
END
SET #Ret = ##IDENTITY
EDIT: This will return the id of your newly inserted row.
You can achieve this by using the output clause of SQL Server, you can read more about this here
if exists (select 1 from sys.tables where name = 'NameIdentifier ')
drop table NameIdentifier
create table NameIdentifier
(
id BIGINT IDENTITY(1,1)
,Name VARCHAR(100)
,Identifier uniqueidentifier
)
DECLARE #id TABLE
(
ID BIGINT
)
INSERT INTO NameIdentifier (Name,Identifier)
OUTPUT INSERTED.id INTO #id
VALUES('abcd',NEWID())
SELECT * FROM NameIdentifier N, #id I where N.id = I.id

TSQL Updating record ID after insert

I have a stored procedure that takes data from a table and creates a record in another table in the following structure:
TableA = Source Data
TableB = Destination 1
First, we query all the data we need from the source table and insert it into TableB. This table has an identity called recordID.
This is done through an INSERT from a Select statement which could contain a variable amount of records.
When this is complete, I need to update a column in TableA called TableBRef with the recordID that was created from the insert in TableB.
I tried using Scope_Identity() but because its inserting multiple records, it only gets the ID of the last record.
I also tried to create a SQLFiddle but it appears the site is having issues as I am getting the error Unknown Error Occurred: XML document structures must start and end within the same entity.: on even the sample fiddle.
Any recommendations to be able to accomplish what I am needing?
Update:
Here is some example code since SQLFiddle is down:
-- This is our source data
DECLARE #source TABLE (recordID INT IDENTITY (1,1), name VARCHAR(100), phone VARCHAR(20));
INSERT INTO #source(name , phone)
VALUES (
'Bob Desk', '123-456-7899',
'Don Mouse', '123-456-5555',
'Mike Keyboard', '123-456-7899',
'Billy Power', '122-222-1134'
)
-- This is the first step in the process - Inserting the records into our table
DECLARE #data1 TABLE (recordID INT IDENTITY (1,1), name VARCHAR(100) NOT NULL, phone VARCHAR(20) NOT NULL, sourceID INT NULL)
SELECT name, phone
FROM #source;
-- Based on some condition, we take records from #data1 and insert them into #data2
DECLARE #data2 TABLE (recordID INT IDENTITY (1,1), name VARCHAR(100) NOT NULL, phone VARCHAR(20) NOT null)
INSERT INTO #data2( name, phone)
SELECT name, phone
FROM #data1
WHERE phone <> '123-456-5555'
-- I now need to update #data1 with the recordID that was created from inserting the data into #data2
UPDATE #data1 SET SOURCEID = 'blah'
Lets setup some tables:
DECLARE #source TABLE
(
recordID INT IDENTITY (1,1),
name VARCHAR(100),
phone VARCHAR(20),
sourceID INT
);
This will store all of the updates coming out of the insert statement:
DECLARE #NewRecord TABLE
(
recordID INT,
name VARCHAR(100),
phone VARCHAR(20)
);
Now we insert the records, and we output the updated record into a table variable to get the new id's:
INSERT INTO #source (name, phone)
OUTPUT inserted.recordid, inserted.name, inserted.phone INTO #NewRecord
VALUES
('Bob Desk', '123-456-7899'),
('Don Mouse', '123-456-5555'),
('Mike Keyboard', '123-456-7899'),
('Billy Power', '122-222-1134')
Here is the output:
SELECT * FROM #NewRecord
recordID name phone
1 Bob Desk 123-456-7899
2 Don Mouse 123-456-5555
3 Mike Keyboard 123-456-7899
4 Billy Power 122-222-1134
Becuase when we are inserting data into data2 with new identity column so we lost source record id so I used name and phone to find what I had inserted --this might not work properly if there are duplicate name and phone seems like there is some design flaw.
but here is some thing you can try this below
-- This is our source data
DECLARE #source TABLE (recordID INT IDENTITY (1,1), name VARCHAR(100), phone VARCHAR(20));
INSERT INTO #source(name , phone)
VALUES (
'Bob Desk', '123-456-7899'),
('Don Mouse', '123-456-5555'),
('Mike Keyboard', '123-456-7899'),
('Billy Power', '122-222-1134')
-- This is the first step in the process - Inserting the records into our table
DECLARE #data1 TABLE (recordID INT IDENTITY (1,1), name VARCHAR(100) NOT NULL, phone VARCHAR(20) NOT NULL, sourceID INT NULL)
--Capture inserts using another table
DECLARE #cdcapture1 TABLE (recordID INT , name VARCHAR(100) NOT NULL, phone VARCHAR(20) NOT null)
INSERT INTO #data1(name,phone)
OUTPUT Inserted.recordID,Inserted.name,Inserted.phone INTO #cdcapture1
SELECT name, phone
FROM #source;
--Capture inserts using another table
DECLARE #cdcapture2 TABLE (recordID INT , name VARCHAR(100) NOT NULL, phone VARCHAR(20) NOT null)
-- Based on some condition, we take records from #data1 and insert them into #data2
DECLARE #data2 TABLE (recordID INT IDENTITY(1,1), name VARCHAR(100) NOT NULL, phone VARCHAR(20) NOT null)
INSERT INTO #data2( name, phone)
OUTPUT Inserted.* INTO #cdcapture2
SELECT name, phone
FROM #cdcapture1 c1
--WHERE phone <> '123-456-5555'
-- Becuase when we are inserting data into data2 with new identity column so we lost source record id
UPDATE d1
SET d1.sourceid = c2.recordid
FROM #data1 d1 INNER JOIN #cdcapture1 c1 ON d1.recordID = c1.recordID
INNER JOIN #cdcapture2 c2 ON c2.NAME = c1.NAME AND c2.phone = c1.phone
SELECT * FROM #data1
-- This is our source data
DECLARE #source TABLE
(
recordID INT IDENTITY (1,1),
name VARCHAR(100),
phone VARCHAR(20)
);
INSERT INTO #source(name , phone)
VALUES
('Bob Desk', '123-456-7899'),
('Don Mouse', '123-456-5555'),
('Mike Keyboard', '123-456-7899'),
('Billy Power', '122-222-1134');
-- This is the first step in the process - Inserting the records into our table
DECLARE #data1 TABLE
(
recordID INT IDENTITY (1,1),
name VARCHAR(100) NOT NULL,
phone VARCHAR(20) NOT NULL,
sourceID INT NULL
)
INSERT INTO #data1 (name, phone )
SELECT name, phone
FROM #source;
-- Based on some condition, we take records from #data1 and insert them into #data2
DECLARE #data2 TABLE
(
recordID INT IDENTITY (1,1),
name VARCHAR(100) NOT NULL,
phone VARCHAR(20) NOT null,
data1recid INT
)
INSERT INTO #data2( name, phone, data1recid)
SELECT name, phone, recordID
FROM #data1
WHERE phone <> '123-456-5555'
-- I now need to update #data1 with the recordID that was created from inserting the data into #data2
UPDATE m
set m.sourceID = d.recordID
FROM #data1 m
INNER JOIN #data2 d
ON m.recordID = d.data1recid
Here is the output:
SELECT * FROM #data1
recordID name phone sourceID
1 Bob Desk 123-456-7899 1
2 Don Mouse 123-456-5555 NULL
3 Mike Keyboard 123-456-7899 2
4 Billy Power 122-222-1134 3
Is this more along the lines of what you needed?

User Defined Scalar functions in SQL

I am new to SQL and am learning User Defined Functions in SQL
I have two tables and I have given the rows I have inserted to those tables.
--Table1
create table sql_exam(
exa_examid bigint not null primary key,
exa_name varchar(100) not null,
exa_maxmark decimal(5,2) not null,
exa_minmarkreqdforpass decimal(5,2) not null,
exa_examscheduletime datetime not null
)
--Rows inserted into Table1
insert into sql_exam(exa_examid,exa_name,exa_maxmark,exa_minmarkreqdforpass,exa_examscheduletime) values (1,'Maths',100,40,'2012-10-10 10:00')
insert into sql_exam(exa_examid,exa_name,exa_maxmark,exa_minmarkreqdforpass,exa_examscheduletime) values (2,'English',75,35,'2012-10-11 10:00')
--Table2
create table sql_studentmarks(
stm_studentid int not null primary key,
stm_examid bigint foreign key references sql_exam(exa_examid),
stm_mark decimal(5,2)
)
--Rows inserted into Table2
insert into sql_studentmarks(stm_studentid,stm_examid,stm_mark) values (1,1,80)
insert into sql_studentmarks(stm_studentid,stm_examid,stm_mark) values (2,1,90)
insert into sql_studentmarks(stm_studentid,stm_examid,stm_mark) values (3,1,40)
insert into sql_studentmarks(stm_studentid,stm_examid,stm_mark) values (1,2,70)
insert into sql_studentmarks(stm_studentid,stm_examid,stm_mark) values (2,2,60)
insert into sql_studentmarks(stm_studentid,stm_examid,stm_mark) values (3,2,17)
I require a help about creating Scalar functions and I need to get
A scalar function which will return the Student ID of the student who got highest mark in 'Maths'
A tabular function which will return the student ID and marks gained by the student who got highest total mark.
Am just trying to learn SQL. I have tried - "
create function fnGetMathsHightest()
returns int
as
begin
declare #st_id int
return #st_id
end
select dbo.fnGetMathsHightest()
from sql_studentmarks
where stm_examid=1
group by stm_studentid
having stm_mark=max(stm_mark)
for the first one. It does not look good.
It looks like this what you want for 1.
CREATE FUNCTION ssfnGetStudenytId
(
-- Add the parameters for the function here
)
RETURNS int
AS
BEGIN
declare #vId as int
set #vId = Select stm_studentid from sql_studentmarks where stm_mark = (SELECT MAX( stm_mark )from sql_studentmarks )
RETURN #vId
END

Passing multiple parameters into a Table valued function

I have a table valued function as below. When I am trying to pass more than one parameter at the same time I am getting a error like "Function has too many arguments specified" .
CREATE FUNCTION [dbo].[GetCompanyUsers](#CompanyId BIGINT)
RETURNS #Users TABLE (Id BIGINT,Contact NVarchar(4000))
AS
BEGIN
INSERT INTO #Users(Id,Contact)
SELECT [Id]
,ISNULL([FirstName],'')+' ' +ISNULL([LastName],'') AS [Contact]
FROM [dbo].[CompanyAddressesContacts]
WHERE [CompanyId]=#CompanyId
ORDER BY ISNULL([FirstName],'')+' ' +ISNULL([LastName],'')
RETURN
END
What modifications I require in the above code so that it allows multiple values and I need to use the function in a "WHERE" condition in my dataset.
WHERE(Document_RFIs.CreatedBy IN
(SELECT Id FROM dbo.GetCompanyUsers(#CompanyId)))
This may help (but the fundamental problem is - passing a comma delimited string is something to be avoided unless absolutely necessary - which explains why you have received so few answers):-
--set nocount on
--create table #Document_RFIs (
-- CreatedBy varchar(50),
-- columna varchar(50),
-- columnb varchar(50),
-- columnc varchar(50)
--)
--insert into #Document_RFIs values
-- ('albert einstein','another','value',null),
-- ('marie curie','some',null,'tuna'),
-- ('isaac newton','why','not','provide'),
-- ('kepler','some','test','data'),
-- ('robert boyle','with','your','question'),
-- ('john dalton','it',null,'would'),
-- ('enrico fermi','make','helping','you'),
-- ('peter higgs','so','much','easier')
--create table #CompanyAddressesContacts (
-- companyid int,
-- firstname varchar(50),
-- lastname varchar(50)
--)
--insert into #CompanyAddressesContacts values (22,'albert','einstein')
--insert into #CompanyAddressesContacts values (23,'marie','curie')
--insert into #CompanyAddressesContacts values (23,'isaac','newton')
--insert into #CompanyAddressesContacts values (24,null,'kepler')
--insert into #CompanyAddressesContacts values (25,'robert','boyle')
--insert into #CompanyAddressesContacts values (25,'enrico','fermi')
--insert into #CompanyAddressesContacts values (26,'peter','higgs')
declare #ids varchar(1024)
set #ids='23,24,25'
create table #id (
companyid int
)
declare #pos int
while DATALENGTH(#ids)>0 begin
set #pos=charindex(',',#ids)
if #pos>0 begin
insert into #id values (left(#ids,#pos-1))
set #ids=SUBSTRING(#ids,#pos+1,DATALENGTH(#ids))
end else begin
insert into #id values (#ids)
set #ids=''
end
end
select d.*
from #Document_RFIs d
where exists(
select cac.*
from #CompanyAddressesContacts cac
join #id i on i.companyid=cac.companyid
where isnull(cac.firstname+' ','')+isnull(cac.lastname,'')=d.CreatedBy
)
--drop table #id
--drop table #Document_RFIs
--drop table #CompanyAddressesContacts
I would do something like this:
First convert your #CompanyId to rows
WITH CompanyIds AS (
SELECT Id
FROM CompanyTable -- Same as the source of the #CompanyId
WHERE Id IN (#CompanyId)
)
Then extract all users
,Users AS (
SELECT UserId
FROM CompanyIds
CROSS APPLY (
SELECT Id AS UserId
FROM dbo.GetCompanyUsers(CompanyIds.Id)
) AS CA1
)
And then use it in the where statement
WHERE Document_RFIs.CreatedBy IN (SELECT UserId
FROM Users)