How to write dynamic insert statement in sql server? - sql

I have a Student table and Department table.
Student Table contains Three columns
StudentId | DeptId | StudentName
Department Table contains
DeptId | DeptName
It may be the case that DeptTable sometimes doesnot exists. That is I am deploying script with two scenarios sometimes with department and sometimes without. In the case without department , departmentId will not be there in student table
So when Department table exists I have to insert value of DeptId otherwise I have to write insert statement without departmentId
IF (EXISTS(
SELECT 1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'Department'
AND column_name = 'DeptId'
))
DECLARE #DeptId UNIQUEIDENTIFIER;
SET #DeptId = Select DeptId From Department Where DeptName = 'Computer'
INSERT INTO Student ([DeptId], [StudentName])
VALUES (#DeptId, 'TBAG')
But as DeptId column sometimes not present I need to create dynamic Sql.
So I created Select statement
DECLARE #sqlCommand nvarchar(1000)
DECLARE #DeptName varchar(75)
declare #DeptId uniqueIdentifier
SET #DeptName = 'Computer'
SET #sqlCommand = 'SELECT #dept=DeptId FROM customers WHERE DeptName = #DeptName'
EXECUTE sp_executesql #sqlCommand, N'#DeptName varchar(50),#dept uniqueIdentifier OUTPUT', #DeptName = #DeptName, #dept=#DeptId OUTPUT
But how to write Insert statement I am not getting

CREATE TABLE dbo.Student
(
DeptId UNIQUEIDENTIFIER,
StudentName VARCHAR(20)
)
GO
DECLARE #DeptId UNIQUEIDENTIFIER
IF COL_LENGTH('dbo.Department', 'DeptId') IS NOT NULL BEGIN
SELECT #DeptId = DeptId
FROM dbo.Department
WHERE DeptName = 'Computer'
END
INSERT INTO dbo.Student(DeptId, StudentName)
SELECT #DeptId /* null is when DeptId is not exists */, 'TBAG'
Output -
(1 row(s) affected)

As per my understanding you want to prepare dynamic insert statement for student table with two cases (with deptid or without deptid)
Please refer the code below.
DECLARE #STUDENTID INT='',--MENTION YOUR STUDENT ID VALUE AND USE THE SAME IN THE ELSE PART COMMENT OUT IF IT HAS IDENTITY
#STUDENTNAME VARCHAR(100)=''--MENTION YOUR STUDENT NAME
IF Col_length('dbo.Student', 'DeptId') IS NOT NULL
BEGIN
INSERT INTO dbo.Student
(DeptId,
StudentName)
SELECT DeptId,
'TBAG'
FROM dbo.Department
WHERE DeptName = 'Computer'
END
ELSE
BEGIN
INSERT INTO dbo.Student
(StudentName)
SELECT #STUDENTNAME
END

Related

How to compare String Variable with Integer

I have this table structure and and some sample data. I want return data for multiple ids via parameter. I have declared a parameter string and now I want to compare it with the column but it ain't allowing because ID is integer.
Can anybody give me any help here ?
CREATE TABLE EMPLOYEE
(
ID INT,
EMPLOYEE_NAME VARCHAR(50)
);
INSERT INTO EMPLOYEE VALUES (1, 'Isaac Frempong');
INSERT INTO EMPLOYEE VALUES (2, 'Eric Ortizz');
DECLARE #StrID VARCHAR(20) = '1, 2'
SELECT * FROM EMPLOYEE
WHERE ID = #StrID
SELECT * FROM EMPLOYEE
WHERE #StrID+',' LIKE '%'+cast(ID as varchar(20))+'%,'
Pretty bad performance as it will need to do a table scan but safe enough.
Generally though, your list of IDs should be a table variable you can do a proper JOIN or IN with
The easiest solution is to use dynamic SQL
DECLARE #sql VARCHAR(1000) = 'SELECT * FROM EMPLOYEE WHERE ID IN (' + #StrID + ')';
EXEC(#sql);
For SQL Server 2017+ you could use STRING_SPLIT a table-valued function that splits a string into rows of substrings
CREATE TABLE EMPLOYEE
(
ID INT,
EMPLOYEE_NAME VARCHAR(50)
);
INSERT INTO EMPLOYEE VALUES (1, 'Isaac Frempong');
INSERT INTO EMPLOYEE VALUES (2, 'Eric Ortizz');
DECLARE #StrID VARCHAR(20) = '1, 2'
SELECT * FROM EMPLOYEE
WHERE ID IN (SELECT value FROM STRING_SPLIT (#StrID,','))
Refer this working fiddle
Create a user defined table type and pass it as a parameter.
CREATE TYPE [UDT_INTIDS] AS TABLE(
[ID] [int] NOT NULL
)
GO
-- create a table value
DECLARE #IDs [UDT_INTIDS];
INSERT #IDs VALUES (1),(2);
-- search using table value.
SELECT e.*
FROM EMPLOYEE e
WHERE e.ID IN (SELECT p.ID FROM #IDs p);
-- or
SELECT e.*
FROM EMPLOYEE e
JOIN #IDs p ON e.ID = p.ID;
See https://learn.microsoft.com/en-us/sql/relational-databases/tables/use-table-valued-parameters-database-engine?view=sql-server-2017 for more details.
You can use the Cast in SQL-Server to cast it to the appropriate datatype. Source Here
WHERE CAST(ID AS VARCHAR(20)) = #StrID
Alternatively: You can use CONVERT function.
WHERE CONVERT(VARCHAR(20), ID) = #StrID

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

Generating insert statement dynamically based on conditions

I have two separate deployment of Student Table. In one case student table contains department Id and in other case it doesn't contain department Id.
I have a common post deployment script for both cases to insert value in student table.
CREATE TABLE dbo.Student
(
DeptId UNIQUEIDENTIFIER,
StudentName VARCHAR(20)
)
GO
DECLARE #DeptId UNIQUEIDENTIFIER
IF COL_LENGTH('dbo.Department', 'DeptId') IS NOT NULL BEGIN
SELECT #DeptId = DeptId
FROM dbo.Department
WHERE DeptName = 'Computer'
END
INSERT INTO dbo.Student(DeptId, StudentName)
SELECT #DeptId, 'TBAG'
But When I don't have department Id column this script doesn't work
Msg 207, Level 16, State 1, Line 23
Invalid column name 'DeptId'.
You can try something like this,
CREATE TABLE dbo.Student
(
DeptId UNIQUEIDENTIFIER,
StudentName VARCHAR(20)
)
GO
IF Col_length('dbo.Department', 'DeptId') IS NOT NULL
BEGIN
INSERT INTO dbo.Student
(DeptId,
StudentName)
SELECT DeptId,
'TBAG'
FROM dbo.Department
WHERE DeptName = 'Computer'
END
ELSE
BEGIN
INSERT INTO dbo.Student
(StudentName)
SELECT 'TBAG'
END

Creating Autoincrement on AlphaNumeric in Stored Procedure

My Table:
CREATE TABLE USER_DATA
([ID] NVARCHAR(10),[NAME] NVARCHAR(50))
My Stored Procedure:
CREATE PROC SP_INSERT_USER
#NAME VARCHAR(50)
AS
BEGIN
DECLARE #ID NVARCHAR(50)
DECLARE #IDTEMP INT
SELECT #IDTEMP=MAX(CAST(RIGHT([ID],3) AS INT) ) FROM USER_DATA
SELECT #IDTEMP=CASE WHEN #IDTEMP IS NULL THEN 1 ELSE #IDTEMP+1 END
SELECT #ID='RP'+RIGHT(('000'+CAST(#IDTEMP AS VARCHAR(10))),3)
INSERT INTO USER_DATA VALUES (#ID,#NAME)
END
Input:
SP_INSERT_USER 'Ajit'
SP_INSERT_USER 'Amit'
Output:
ID NAME
---------- --------------------------------------------------
RP001 Ajit
RP002 Amit
This code is working fine. But the ID is fixed. It is limited to 3 digits like 001, 002, etc. If it get 1000th employee, it is not displaying properly. Is there any way to make it dynamical without fixing the length?
Try this one -
CREATE TABLE dbo.USER_DATA
(
PK INT IDENTITY(1,1) PRIMARY KEY
, ID AS 'PR' + RIGHT('00' + CAST(PK AS VARCHAR(5)), 5)
, NAME NVARCHAR(50)
)
GO
CREATE PROC dbo.SP_INSERT_USER
#NAME VARCHAR(50)
AS BEGIN
INSERT INTO dbo.USER_DATA
VALUES (#NAME)
END
GO
EXEC dbo.SP_INSERT_USER 'Ajit'
EXEC dbo.SP_INSERT_USER 'Amit'
SELECT ID, NAME
FROM dbo.USER_DATA

SQL Recursive Coalesce

I'm trying to create a column that contains all cities of the referenced addresses.
DECLARE #AddressList nvarchar(max)
SELECT #AddressList = COALESCE(#AddressList + ' ', '') + City FROM [Address]
SELECT
Employee.*,
(SELECT #AddressList) AS AddressCities
FROM Employee
But I dont know where to put the WHERE clause.
...
(SELECT #AddressList WHERE EmployeeId = Employee.EmployeeId) AS AddressCities
...
The above test doesnt work..
Table schemas are:
Employee
EmployeeId
Name
Address
Street
City
EmployeeId
If i understand you correctly, you wish to show all Cities in a single column for the employee. So you wish to GROUP BY and CONCAT.
Using Sql Server 2005, try this (working example)
DECLARE #Employee TABLE(
EmployeeId INT,
NAME VARCHAR(100)
)
INSERT INTO #Employee (EmployeeId,[NAME]) SELECT 1, 'A'
INSERT INTO #Employee (EmployeeId,[NAME]) SELECT 2, 'B'
DECLARE #Address TABLE(
Street VARCHAR(50),
City VARCHAR(50),
EmployeeId INT
)
INSERT INTO #Address (Street,City, EmployeeId) SELECT 'A','A', 1
INSERT INTO #Address (Street,City, EmployeeId) SELECT 'B','B', 1
INSERT INTO #Address (Street,City, EmployeeId) SELECT 'C','C', 1
INSERT INTO #Address (Street,City, EmployeeId) SELECT 'D','D', 2
INSERT INTO #Address (Street,City, EmployeeId) SELECT 'E','E', 2
INSERT INTO #Address (Street,City, EmployeeId) SELECT 'F','F', 2
SELECT e.EmployeeId,
e.[NAME],
(
SELECT al.City + ','
FROM #Address al
WHERE al.EmployeeId = e.EmployeeId
FOR XML PATH('')
)
FROM #Employee e
GROUP BY e.EmployeeId,
e.[NAME]
Do need more information about what you mean by 'column that contains all cities'. How is what you want different to the following might help you phrase the question
SELECT e.EmployeeId,e.Name,a.City
FROM Employee e
INNER JOIN Address a ON a.EmployeeId = e.EmployeeId
GROUP BY e.EmployeeId,e.Name
-- update
I think I see what you mean, do you want like:
EmployeeID | Name | Address
1 | John | 'London','Paris','Rome'
2 | Jane | 'New York','Miami'
?