Stored procedure with multiple insert - sql

I want a value of #temp table and People table value together. I can use json_modify but it will work only for single value insert. But in case of multiple values, we can make both in JSON object which will be array of object and combine both. But how?
CREATE PROCEDURE [dbo].[SpPersonIns]
(#json nvarchar(max) OUTPUT)
AS
BEGIN
CREATE TABLE #temp (PersonId int)
INSERT INTO People (FirstName, MiddleName, LastName, SSN, UserPersonId)
OUTPUT inserted.PersonId
INTO #temp
SELECT p.firstName, p.middleName, p.lastName, p.ssN, p.userPersonId
FROM OPENJSON(#json) WITH(
firstName varchar(100),
middleName varchar(100),
lastName varchar(100),
ssN varchar(9),
userPersonId int
) as p
declare #p nvarchar(max);
select #p = t.PersonId from #temp as t
SELECT #json = JSON_MODIFY(#json,'$.PersonId',#p)
END

You have two options.
The simplest is to just output the whole inserted and then rebuild the JSON from it
CREATE OR ALTER PROCEDURE [dbo].[SpPersonIns]
#json nvarchar(max) OUTPUT
AS
DECLARE #temp TABLE (
PersonId int,
firstName varchar(100),
middleName varchar(100),
lastName varchar(100),
ssN varchar(9),
userPersonId int
);
INSERT INTO People (FirstName, MiddleName, LastName, SSN, UserPersonId)
OUTPUT inserted.PersonId, inserted.firstName, inserted.middleName, inserted.lastName, inserted.ssN, inserted.userPersonId
INTO #temp (PersonId, firstName, middleName, lastName, ssN, userPersonId)
SELECT p.firstName, p.middleName, p.lastName, p.ssN, p.userPersonId
FROM OPENJSON(#json)
WITH (
firstName varchar(100),
middleName varchar(100),
lastName varchar(100),
ssN varchar(9),
userPersonId int
) as p;
SET #json = (
SELECT *
FROM #temp
FOR JSON PATH
);
Or, if you have a unique natural key within the JSON (for example userPersonId), you can use some kind of join.
CREATE OR ALTER PROCEDURE [dbo].[SpPersonIns]
#json nvarchar(max) OUTPUT
AS
DECLARE #temp TABLE (PersonId int not null, userPersonId int PRIMARY KEY);
INSERT INTO People (FirstName, MiddleName, LastName, SSN, UserPersonId)
OUTPUT inserted.PersonId, inserted.userPersonId
INTO #temp (PersonId, userPersonId)
SELECT p.firstName, p.middleName, p.lastName, p.ssN, p.userPersonId
FROM OPENJSON(#json)
WITH (
firstName varchar(100),
middleName varchar(100),
lastName varchar(100),
ssN varchar(9),
userPersonId int
) as p;
SET #json = (
SELECT
'[' +
STRING_AGG(
JSON_MODIFY(
arr.value,
'$.PersonId',
t.PersonId
),
','
) +
']'
FROM OPENJSON(#json) AS arr -- if you don't specify a schema then you get the whole array object
JOIN #temp t ON t.userPersonId = JSON_VALUE(arr.value, '$.userPersonId')
);

Related

How to insert a dynamic sql variable into a temporary table

So I want to insert the variables email, username, and age from a stored procedure into a temporary table and am running into a few issues.
Declare #email [varchar](8000)
,#user_name [varchar](8000)
, age[int]
select distinct value as value
into #temptable
from #email
,#user_name
,#age
select *
from #temptable
I am getting a syntax error. Does anybody have any advice?
Generally, I would use this syntax to insert the results of a stored procedure into a table or table variable:
INSERT #temptable EXECUTE dbo.MyStoredProcedureName
For example (table variable example):
declare #temptable table
(
name varchar(255),
field varchar(255),
filename varchar(255),
filegroup varchar(255),
size varchar(255),
maxsize varchar(255),
growth varchar(255),
usage varchar(255)
);
INSERT #temptable Exec sp_helpfile;
select * from #temptable ;
EDIT: Per your question about why can't you do this in the SP itself, the syntax would be something like:
DECLARE #Email nvarchar(4000),#UserName nvarchar(4000),#age int
declare #temptable table
(
email nvarchar(4000),
UserName nvarchar(4000),
age int
)
SELECT #Email = 'test#test.com', #UserName = 'MyName', #age = 21
INSERT INTO #temptable(Email, UserName, age) SELECT #Email, #UserName, #age
SELECT * FROM #temptable

How To Filter SQL Results Efficiently

I have a requirement to filter the table records based on passed input criteria to the SQL stored procedure. To make it simple, I'm elaborating the question using simple Employee table (I'm using MSSQL server for my project):
Table: Employee(Id, FirstName,LastName, Designation)
The stored procedure takes 3 input arguments (Id, LastName, Designation). This will be invoked with at-least one input parameter (other parameter will be set to empty string (in case of LastName, Designation) or 0 (In case of Id)).
Here is the stored procedure:
Create Procedure GetEmployees
(
#id int,
#lastName varchar(30),
#designation varchar(30)
)
AS
BEGIN
Create Table #employees (Id int, FirstName varchar(30),LastName varchar(30), Designation varchar(30);
IF(#id != 0)
BEGIN
Insert Into #employees (Id,FirstName,LastName,Designation)
Select Id, FirstName,LastName,Designation From Employee Where Id = #id
END
IF(#lastName != ‘’)
BEGIN
Insert Into #employees (Id,FirstName,LastName,Designation)
Select Id, FirstName,LastName,Designation From Employee Where LastName = #lastName
END
IF(designation != ‘’)
BEGIN
Insert Into #employees (Id,FirstName,LastName,Designation)
Select Id, FirstName,LastName,Designation From Employee Where Designation = #designation
END
-- Returning filtered record set to the application layer
Select Id,FirstName,LastName,Designation From #employees;
END
GO
I think there a lot of code repetition in the stored procedure. Is there an efficient way of solving this scenario ?
You may use a single insert query with a WHERE clause which covers all the logic:
BEGIN
INSERT INTO #employees (Id, FirstName, LastName, Designation)
SELECT Id, FirstName, LastName, Designation
FROM Employee
WHERE
(Id = #id AND #id <> 0) OR
(LastName = #lastName AND #lastName <> '') OR
(Designation = #designation AND #designation <> '');
You can use Case condition in Where clause, Find Below Query.
INSERT INTO #employees (Id, FirstName, LastName, Designation)
SELECT Id, FirstName, LastName, Designation
FROM Employee
WHERE
(Id = CASE WHEN #id = 0 THEN ID ELSE #ID END) OR
(LastName = CASE WHEN #lastName = '' THEN LastName ELSE #lastName END) OR
(Designation = CASE WHEN #designation = '' THEN Designation ELSe #designation END);
We can also Use AND Instead of OR in Where clause.
As #trincot said, there is no need for a temporary table. My suggestion is:
Create Procedure GetEmployees
(
#id int,
#lastName varchar(30),
#designation varchar(30)
)
AS
BEGIN
Select Id, FirstName,LastName,Designation From Employee
Where (#id>'' AND Id = #id)
OR (#lastName>'' AND LastName = #lastName)
OR (#designation>'' AND Designation = #designation);
END
GO

How to map table fields from source as the variables of stored procedure in destination in SSIS Package?

I want to transfer data from source Database table named Patient (which contains many rows) to destination database tables(2) named Person & Patient.
I already have stored procedure named AddPatient in destination database which will add person related fields to Person table and other fields to Patient table, so I would like to execute that procedure and to assign the fields from source database as variables to it. The following are the code of AddPatient sp in destination database.
ALTER PROCEDURE [dbo].[AddPatient]
(
#TenantId BIGINT,
#FirstName NVARCHAR(100),
#LastName NVARCHAR(100),
#PersonNumber NVARCHAR(20),
#MobileNumber NVARCHAR(20),
#EmailId NVARCHAR(100),
#Address NVARCHAR(255),
#City NVARCHAR(50),
#ZipCode NVARCHAR(20),
#ListComments NVARCHAR(1000),
#Comment NVARCHAR(500),
#AlternateEmailId NVARCHAR(100) ,
#HomePhone NVARCHAR(20) ,
#Relative NVARCHAR(255) ,
#HasDiabetes [bit],
#HasBlooPressure [bit],
#AddedBy BIGINT,
#AddedDateTime smalldatetime,
#PersonId BIGINT OUTPUT
)
AS
BEGIN
SET NOCOUNT ON
IF #TenantId IS NULL
RAISERROR('The value for #TenantID should not be null', 15, 1) -- with log
ELSE
BEGIN
DECLARE #new_person_id BIGINT
DECLARE #new_patient_id BIGINT
DECLARE #PatientIdentifier NVARCHAR(50)
EXEC dbo.GetNextPatientIdForTenant #TenantID, #PatientIdentifier OUTPUT
INSERT INTO dbo.Person
(
TenantId,
FirstName,
LastName,
PersonNumber,
MobileNumber,
EmailId,
Address,
City,
ZipCode,
AddedBy,
AddedDateTime
)
VALUES
(
#TenantId,
#FirstName,
#LastName,
#PersonNumber,
#MobileNumber,
#EmailId,
#Address,
#City,
#ZipCode,
#AddedBy,
#AddedDateTime
)
SELECT #new_person_id = SCOPE_IDENTITY()
INSERT INTO dbo.Patient
(
TenantId,
PatientIdentifier,
PersonId,
ListComments,
Comment,
AlternateEmailId,
HomePhone,
Relative,
HasDiabetes,
HasBlooPressure,
AddedBy,
AddedDateTime
)
VALUES
(
#TenantId,
#PatientIdentifier,
#new_person_id,
#ListComments ,
#Comment ,
#AlternateEmailId,
#HomePhone ,
#Relative ,
#HasDiabetes,
#HasBlooPressure,
#AddedBy ,
#AddedDateTime
)
SELECT #new_patient_id = SCOPE_IDENTITY()
SELECT #PersonId = #new_person_id
SELECT #new_patient_id
END
END
There is no TenantId & AddedBy field in source, so I want to assign both as 1 for all rows to be transfered.
I know Execute SQL Task will handles stored procedure and for each row data Foreach Loop Container will take care in SSIS. But I don't know how to assign the variables of sp in destination database to the fields of table from source database.
Anyone help me with this.
Thanks in advance !

How to have multiple inserts in one sql query that uses the identities from the previous table

I am trying to insert data into many tables in one SQL Server stored procedure. I am also using the identities from the tables that I have inserted data into to then resolve the many to many relationship by writing those identities to another table.
In theory the logic seems to be there for the stored procedure, but on execution only the first insert statement has been executed. Please could anyone assist with this.
The stored procedure is as follows:
Create Procedure [dbo].[InsertAllCustomerDetails]
(
--#CustomerID Bigint output,
#Firstname varchar(100),
#LastName varchar(100),
#Initials varchar(10),
#Title varchar(20),
#DateCreated datetime,
#isDeleted Bit,
--#ContactNumberID BIGINT Output,
#ContactNumber Varchar(100),
#ContactTypeID bigint,
#Street Varchar(550),
#AreaID BIGINT,
#isPreferred Bit
--#AddressID Bigint OutPut
)
AS
Insert Into Customer
(
FisrtName,
LastName,
Initials,
[Title],
DateCreated,
isDeleted
)
Values
(
#Firstname,
#LastName,
#Initials,
#Title,
#DateCreated,
#isDeleted
)
Declare #CustomerID BIGINT
SELECT #CustomerID = ##IDENTITY
RETURN #CustomerID
--This will now insert the contact details for the customer
Insert Into ContactNumber
(
ContactNumber,
ContactTypeID
)
Values
(
#ContactNumber,
#ContactTypeID
)
Declare #ContactNumberID BIGINT
SELECT #ContactNumberID = ##IDENTITY
--This will insert into the CustomerContactNumber
Insert Into CustomerContactNumber
(
ContactNumberID,
CustomerID
)
Values
(
#ContactNumberID,
#CustomerID
)
--This will insert the address
Insert Into [Address]
(
Street,
AreaID,
isPreferred
)
Values
(
#Street,
#AreaID,
#isPreferred
)
Declare #AddressID BIGINT
SELECT #AddressID = ##IDENTITY
--This will insert the relationship for the customer Address table
Insert into CustomerAddress
(
CustomerID,
AddressID
)
Values
(
#CustomerID,
#AddressID
)
I see two things:
You seem to have a typo in the Customer insert:
Insert Into Customer
(
FisrtName, <-- should be FirstName?
LastName,
You are RETURNing after the Customer insert - that's why only the first one runs
Declare #CustomerID BIGINT
SELECT #CustomerID = ##IDENTITY
RETURN #CustomerID <---- This exits the sproc
--This will now insert the contact details for the customer
Insert Into ContactNumber
I'm guessing the RETURN was there for debugging and not removed since it's obscured by the indentation.

Join on select SQL Server stored procedure

I am trying to create a stored procedure to insert data into 2 tables in SQL Server.
I have tried putting the join in all different positions of the code and still get an error.
CREATE PROCEDURE sp_Insert_Person
#s_FirstName nvarchar(50),
#s_Surname nvarchar(50),
#s_AddressLine1 nvarchar(50),
#s_AddressLine2 nvarchar(50),
#s_Postcode nvarchar(10),
#s_Phone nvarchar(50),
#s_Department nvarchar(50)
AS
BEGIN
INSERT INTO
tbl_person(FirstName, Surname, AddressLine1, AddressLine2,
Postcode, Phone, tbl_Department.Department)
INNER JOIN tbl_person
ON tbl_person.DepartmentID = tbl_Department.DepartmentID
VALUES (#s_FirstName,
#s_Surname,
#s_AddressLine1,
#s_AddressLine2,
#s_Postcode,
#s_Phone,
#s_Department)
END
I have tried the join at the end and at the beginning I have looked all over for insert joins, wondered if i was just getting it all wrong.
I have a department table and a person table and thought I would be able to access the department table through the FK DepartmentID which I have in the Person table, as is the PK in the Department table
I think something like this
INSERT INTO tbl_person
(FirstName,
Surname,
AddressLine1,
AddressLine2,
Postcode,
Phone,
DepartmentID)
Select #s_FirstName,
#s_Surname,
#s_AddressLine1,
#s_AddressLine2,
#s_Postcode,
#s_Phone,
tbl_Department.DepartmentID
from tbl_person
join DepartmentID
ON tbl_person.DepartmentID = tbl_Department.DepartmentID
where tbl_Department.Department = #s_Department
CREATE PROCEDURE sp_Insert_Person
#s_FirstName nvarchar(50),
#s_Surname nvarchar(50),
#s_AddressLine1 nvarchar(50),
#s_AddressLine2 nvarchar(50),
#s_Postcode nvarchar(10),
#s_Phone nvarchar(50),
#s_Department nvarchar(50)
AS
BEGIN
if not Exists(select * from tbl_Department where Department=#s_Department)
insert into tbl_Department (Department) Values (#s_Department)
INSERT INTO tbl_person
(FirstName,
Surname,
AddressLine1,
AddressLine2,
Postcode,
Phone,
DepartmentID)
select #s_FirstName,
#s_Surname,
#s_AddressLine1,
#s_AddressLine2,
#s_Postcode,
#s_Phone,
#s_Department,
DepartmentID
from tbl_Department
where Department=#s_Department
END