SQL Server 2008 R2: Prepare Dynamic WHERE Clause - sql

I have the following stored procedure with four parameters.
Stored procedure spTest:
CREATE PROCEDURE spTest
#Name varchar(20) = '',
#Address varchar(100) = '',
#City varchar(50) = '',
#Pin varchar(50) = ''
AS
DECLARE #DynamicWhere varchar(max)
DECLARE #Query varchar(max)
/* Here I want to prepare a dynamic where clause for all possibilities */
SET #Query = 'SELECT * FROM Test_Table '+ #DynamicWhere +'';
EXECUTE(#Query);
GO
Well I am preparing it like this:
IF #Name = '' AND #Address = '' AND #City = '' AND #Pin = ''
BEGIN
SET #DynamicWhere = '';
END
ELSE IF #Name != '' AND #Address = '' AND #City = '' AND #Pin = ''
BEGIN
SET #DynamicWhere = 'Name ='''+#Name+'''';
END
ELSE IF #Name != '' AND #Address != '' AND #City = '' AND #Pin = ''
BEGIN
SET #DynamicWhere = 'Name ='''+#Name+''' AND Address ='''+#Address+'''';
END
......
......
Many possibilities
Is this a right way OR is there any better way to prepare the dynamic WHERE clause?

It's called catch-all queries and it basically goes like this:
CREATE PROCEDURE spTest
#Name varchar(20) = '',
#Address varchar(100) = '',
#City varchar(50) = '',
#Pin varchar(50) = ''
AS
SELECT *
FROM Test_Table
WHERE (#Name = '' OR Name = #Name)
AND (#Address = '' OR Address = #Address)
AND (#City = '' OR City = #City)
AND (#Pin = '' OR Pin = #Pin);
GO
You also might want to read this article about catch all queries

You can use ISNULL and NULLIF also in this case:
below code should work :
CREATE PROCEDURE spTest
#Name varchar(20) = '',
#Address varchar(100) = '',
#City varchar(50) = '',
#Pin varchar(50) = ''
AS
SET #Name=NULLIF(#Name,'')
SET #Address=NULLIF(#Address,'')
SET #City=NULLIF(#City,'')
SET #Pin=NULLIF(#Pin,'')
SELECT *
FROM Test_Table
WHERE Name = ISNULL(#Name,Name)
AND Address = ISNULL(#Address,Address)
AND City = ISNULL(#City,City)
AND Pin = ISNULL(#Pin,Pin)
GO

I update the #Zohar answer. Define blank is bad habits, ideally define with null and later use blank. So the query will be
CREATE PROCEDURE spTest
#Name varchar(20) = null,
#Address varchar(100) = null,
#City varchar(50) = null,
#Pin varchar(50) = null
AS
SELECT *
FROM Test_Table
WHERE (Name = ISNULL(#Name,'') )
AND (Address = ISNULL(#Address,''))
AND (City = ISNULL(#City,''))
AND (Pin = ISNULL(#Pin,''));
GO
Even I like the #Biswa answer as it use current version of sql server, but Sqlserver 2008R2 does not have this function.

Related

Stored procedure with OUTPUT - Must declare the scalar variable

I'm writing a stored procedure that will be executed from C# to get data from database. Therefore I have to pass a GUID to this stored procedure and it should find data in table Contact or in the Lead table & return data back to C# app via output parameters.
When I try to execute this stored procedure in SSMS, I get a SQL exception
Must declare the scalar variable "#LastName"
Code:
ALTER PROCEDURE [api].[GetUser_NetId]
#NetId uniqueidentifier
, #LastName nvarchar(200) = '' OUTPUT
, #FirstName nvarchar(200) = '' OUTPUT
, #Country uniqueidentifier = NULL OUTPUT
, #Newsletter bit = 0 OUTPUT
AS
DECLARE
#Table SMALLINT
SET #Table = (
SELECT MIN(T.ID) FROM (
SELECT 100 AS [ID] FROM dbo.Contact WHERE Net_ID = #NetId
UNION ALL
SELECT 200 AS [ID] FROM dbo.Lead WHERE Net_ID = #NetId
) T
)
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = CONCAT(
' SELECT
#LastName = tbl.LastName,
#FirstName = tbl.FirstName,
#Country = tbl.Address1CountryId,
#Newsletter = tbl.Newsletter,
FROM
dbo.'
, CASE #Table
WHEN 100 THEN 'Contact'
WHEN 200 THEN 'Lead'
END
, ' as tbl
WHERE 1=1
AND tbl.Net_Id = '''
, #NetId
, ''''
)
EXEC(#SQL)
..a slightly simpler approach
ALTER PROCEDURE [api].[GetUser_NetId]
#NetId uniqueidentifier
, #LastName nvarchar(200) = '' OUTPUT
, #FirstName nvarchar(200) = '' OUTPUT
, #Country uniqueidentifier = NULL OUTPUT
, #Newsletter bit = 0 OUTPUT
AS
BEGIN
IF EXISTS(SELECT * FROM dbo.Contact WHERE Net_ID = #NetId)
BEGIN
SELECT
#LastName = tbl.LastName,
#FirstName = tbl.FirstName,
#Country = tbl.Address1CountryId,
#Newsletter = tbl.Newsletter
FROM dbo.Contact WHERE Net_ID = #NetId;
END
ELSE
BEGIN
SELECT
#LastName = tbl.LastName,
#FirstName = tbl.FirstName,
#Country = tbl.Address1CountryId,
#Newsletter = tbl.Newsletter
FROM dbo.Lead WHERE Net_ID = #NetId;
END
END
I am getting an error like:
Msg 137, Level 15, State 2, Line 18
Must declare the scalar variable "#CustomerKey".
Msg 137, Level 15, State 1, Line 21
Must declare the scalar variable "#FirstName".
Msg 137, Level 15, State 1, Line 30
Must declare the scalar variable "#FirstName".
IF EXISTS(SELECT * FROM VW_FactInternetSales WHERE CustomerKey = #CustomerKey)
BEGIN
SELECT
#FirstName = .FirstName,
#TaxAmt = .TaxAmt,
#Country = .Country,
#CustomerKey = .CustomerKey
FROM DimCustomer WHERE CustomerKey = #CustomerKey
END
ELSE
BEGIN
SELECT
#FirstName = .FirstName,
#TaxAmt = .TaxAmt,
#Country = .Country,
#CustomerKey = .CustomerKey
FROM VW_FactInternetSales WHERE CustomerKey = #CustomerKey
END
END
I cant add my table in this line
#FirstName = .FirstName,
#TaxAmt = .TaxAmt,
#Country = .Country,
#CustomerKey = .CustomerKey

SQL Server Dynamic where clause query

I am trying to create a dynamic query I just to do with linq
from a in Customers
where (string.IsNullOrEmpty(name)? true : a.FirstName == name) && (string.IsNullOrEmpty(last)? true : a.LastName == last)
select a;
but now I need to do in on Stored Procedure and I don't want to concatenate for security reason and performance. The most close example I found is this query
declare #Name as varchar(100)
declare #GroupName as varchar(100)
set #Name = ''
set #GroupName = 'Manufacturing'
SELECT TOP (1000) [DepartmentID]
,[Name]
,[GroupName]
,[ModifiedDate]
FROM [AdventureWorks2017].[HumanResources].[Department]
where ([Name] = case
when #Name is null or #Name = '' then null
else #Name
end
)
and
(
[GroupName] = case
when #GroupName is null or #GroupName = '' then null
else #GroupName
end
)
This almost works. I think this should be the answer but the where clause fails for obvious reason.
I would like the where clause could produce '1=1' if the param "Name" or "GroupName" is null
example
#Name = "Somename"
#GroupName = null
where (Name = #Name) and (1 = 1)
--or
#Name = null
#GroupName = "Somegruopname"
where (1 = 1) and (GroupName = #GroupName)
--
#Name = null
#GroupName = null
where (1 = 1) and (1 = 1)
You want it to succeed if the variable is null or empty or a match, so I would just write that in your stored procedure.
WHERE (#FirstName is null OR #FirstName = '' OR [FirstName] = #FirstName)
AND (#LastName is null OR #LastName = '' OR [LastName] = #LastName)
Please try this:
declare #Name as varchar(100)
declare #GroupName as varchar(100) = 'Manufacturing'
set #Name = LTRIM(RTRIM(#Name))
set #GroupName = 'Manufacturing'
SELECT TOP (1000) [DepartmentID]
,[Name]
,[GroupName]
,[ModifiedDate]
FROM [AdventureWorks2017].[HumanResources].[Department]
where ([Name] = coalesce(#Name,'') = '' OR [Name] = #Name)
and
([GroupName] = coalesce(#GroupName, '') = '' OR [GroupName] = #GroupName)

Sql Scope_Identity() return Null?

I am facing this issue that my stored proc always return NULL though i have set my #output variable as well.I want to get last inserted scope Id from the table.
can someone help me where i have got wrong?
ALTER PROC spAddOrUpdateMember
#pMemberId INT = 0 ,
#pFirstName VARCHAR(50) = 'aa',
#pLastName VARCHAR(50)='aa' ,
#pMemberCode VARCHAR(15) = '12312',
#pDOB DATE = '03/10/2019',
#pGrade INT = 2 ,
#pCNIC VARCHAR(14) = '3423434',
#pFatherName VARCHAR(50) = 'asdasd' ,
#pCurrentAddress VARCHAR(MAX) = 'asds' ,
#pPermanentAddress VARCHAR(MAX) = 'fgdf',
#pEmploymentAddress VARCHAR(MAX) = 'ytuyu' ,
#pNationality INT =2
#output int = 0 output
AS
BEGIN
IF #pMemberId > 0
BEGIN
---UPDATE ME
UPDATE [dbo].[QC_Member_Profile]
SET
[FirstName] = #pFirstName
,[LastName] = #pLastName
,[DOB] = #pDOB
,[CNIC] = #pCNIC
,[FatherName] = #pFatherName
,[CurrentAddress] = #pCurrentAddress
,[PermanentAddress] = #pPermanentAddress
,[Nationality] = #pNationality
,[MemberTypeId] =#pMemberTypeId
WHERE MemberId = #pMemberId
END
ELSE
BEGIN
---INSERT ME
INSERT INTO QC_Member_Profile VALUES(
dbo.PIdentityKey(0),
#pFirstName,
#pLastName,
#pDOB,
#pCNIC,
#pFatherName,
#pCurrentAddress,
#pPermanentAddress,
#pNationality,
)
set #output = SCOPE_IDENTITY();
SELECT #output = SCOPE_IDENTITY();
select #output
END
END
I've guessed the name of your ID column, however, this should work. You'll need to amend the name of your ID column if it isn't called MemberID or if it doesn't have the data type int:
ALTER PROC spAddOrUpdateMember #pMemberId int = 0,
#pFirstName varchar(50) = 'aa',
#pLastName varchar(50) = 'aa',
#pMemberCode varchar(15) = '12312',
#pDOB date = '03/10/2019',
#pGrade int = 2,
#pCNIC varchar(14) = '3423434',
#pFatherName varchar(50) = 'asdasd',
#pCurrentAddress varchar(MAX) = 'asds',
#pPermanentAddress varchar(MAX) = 'fgdf',
#pEmploymentAddress varchar(MAX) = 'ytuyu',
#pNationality int = 2,
#output int = 0 OUTPUT
AS
BEGIN
IF #pMemberId > 0
BEGIN
UPDATE [dbo].[QC_Member_Profile]
SET [FirstName] = #pFirstName,
[LastName] = #pLastName,
[DOB] = #pDOB,
[CNIC] = #pCNIC,
[FatherName] = #pFatherName,
[CurrentAddress] = #pCurrentAddress,
[PermanentAddress] = #pPermanentAddress,
[Nationality] = #pNationality,
[MemberTypeId] = #pMemberTypeId
WHERE MemberId = #pMemberId;
END;
ELSE
BEGIN
DECLARE #ins table (OutputID int);
INSERT INTO QC_Member_Profile
OUTPUT Inserted.MemberID --guessed name
INTO #Ins
VALUES (dbo.PIdentityKey(0), #pFirstName, #pLastName, #pDOB, #pCNIC, #pFatherName, #pCurrentAddress, #pPermanentAddress, #pNationality);
SELECT #output = OutputID
FROM #ins;
SELECT #Output;
END;
END;
I've also fixed the syntax errors that were in your original question.

How to select the ALL passed parameter values inside the stored procedure in SQL like SQL Trace

How to select all parameters and values passed to the stored procedure as like in SQL Trace, inside the procedure using any ## function without any customization.
For Example I have a stored procedure like
CREATE PROC test_Procedure
#ln varchar(25) = '',
#fn varchar(25) = '',
#dob datetime = NULL,
#id INT = 0
AS
BEGIN
SELECT * FROM tb_users
WHERE ln= #ln
AND fn = #fn
AND dob = #dob
AND Id = #id
------------ SELECT ##
END
If I called the procedure like
EXEC [dbo].test_Procedure #ln = N'a',#fn = NULL,#dob = NULL,#id = 1
I need to select this exact string inside the procedure using any built in function or user defined function .
If you're trying to output debugging style info you could use something like this;
SELECT CONCAT('test_Procedure #ln = ', #ln, ', #fn = ', #fn, ', #dob = ', #dob, ', #id = ', #id)

Select parameters if a condition is fulfilled

I want to select particular elements if my condition is fulfilled. Please, look below at my code. How can I select the data in CASE clause? My way does not work
CREATE PROCEDURE [dbo].[GetUsers]
#firstName varchar(100) = '',
#isCounterSelected int,
#countries dbo.tvp_stringArray READONLY
AS
BEGIN
SET NOCOUNT ON;
SELECT [PK_UserID] AS Id
,[UserNickName]
,[description]
,CASE
WHEN #isCounterSelected = 1 THEN (NULL AS MCount, NULL AS GCount, NULL AS CCount)
ELSE ''
END
FROM [dbo].[User_Existing]
WHERE (#firstName NOT LIKE '' AND firstName LIKE #firstName + '%')
AND Country IN (SELECT inputValue FROM #countries)
I think this would be with syntax errors fixed:
CREATE PROCEDURE [dbo].[GetUsers]
#firstName varchar(100) = '',
#isCounterSelected int,
#countries dbo.tvp_stringArray READONLY
AS
BEGIN
SET NOCOUNT ON;
SELECT [PK_UserID] AS Id
,[UserNickName]
,[description]
,CASE
WHEN #isCounterSelected = 1 THEN NULL
ELSE ''
END AS MCount
,CASE
WHEN #isCounterSelected = 1 THEN NULL
ELSE ''
END AS GCount
,CASE
WHEN #isCounterSelected = 1 THEN NULL AS CCount
ELSE ''
END AS CCount
FROM [dbo].[User_Existing]
WHERE (#firstName NOT LIKE '' AND firstName LIKE #firstName + '%')
AND Country IN (SELECT inputValue FROM #countries)
END