I have a function in SQL that returns where clause result like this
CREATE FUNCTION dwd.GetSearchCriteria
(
#pValue NVARCHAR(50),
#pCriteriaOption NVARCHAR(3)
)
RETURNS varchar(30)
AS
BEGIN
declare
#WHERE varchar(2000)
IF(#pValue IS NOT NULL)
BEGIN
SET #WHERE = CASE WHEN #pCriteriaOption = 'ST' THEN ' like ''' + #pValue + '%'''
WHEN #pCriteriaOption = 'ET' THEN ' like ''' + '%' + #pValue + ''''
WHEN #pCriteriaOption = 'CT' THEN ' like ' + '''%' + #pValue + '%'''
ELSE ''
END
END
ELSE
BEGIN
SET #WHERE = '= NULL';
END
RETURN #WHERE
END
I have a query that like this which calls this function
declare
#WHERE varchar(2000)
SET #WHERE=dwd.GetSearchCriteria ('A','ET')
SELECT FirstName FROM dwd.[User] WHERE FirstName + #WHERE
My function returns suppose { like %A% } . I need to append it to first name .
It returns this error
An expression of non-boolean type specified in a context where a
condition is expected, near '#WHERE'.
I have along SP like this
ALTER PROCEDURE [dwd].[ADMIN_USER_DETAIL]
(
#pApplicationClientID bigint,
#pUserID bigint,
/* Optional Filters for Dynamic Search*/
#pFirstName nvarchar(50) = NULL,
#pLastName nvarchar(50) = NULL,
#pEmail nvarchar(255) = NULL,
#pLocation nchar(10) = NULL,
#pPhoneNumber nvarchar(50) = NULL,
#pPseudoName nvarchar(500) = NULL,
/*– Pagination Parameters */
#pPageNo INT = 1,
#pPageSize INT = 10,
/*– Sorting Parameters */
#pSortColumn nvarchar(50) = 'FirstName',
#pSortOrder nvarchar(4)='ASC',
#pTotalCount int output
)
AS
BEGIN
/*–Declaring Local Variables corresponding to parameters for modification */
DECLARE
#lFirstName nvarchar(50),
#lLastName nvarchar(50),
#lEmail nvarchar(255),
#lLocation nchar(10),
#lPhoneNumber nvarchar(50),
#lPseudoName nvarchar(500),
#lPageNbr INT,
#lPageSize INT,
#lSortCol NVARCHAR(50),
#lFirstRec INT,
#lLastRec INT,
#lTotalRows INT,
#TotalCount INT
/*Setting Local Variables*/
SET #lFirstName = LTRIM(RTRIM(#pFirstName))
SET #lLastName = LTRIM(RTRIM(#pLastName))
SET #lEmail = LTRIM(RTRIM(#pEmail))
SET #lLocation = LTRIM(RTRIM(#pLocation))
SET #lPhoneNumber = LTRIM(RTRIM(#pPhoneNumber))
SET #lPseudoName = LTRIM(RTRIM(#pPseudoName))
SET #lPageNbr = #pPageNo
SET #lPageSize = #pPageSize
SET #lSortCol = LTRIM(RTRIM(#pSortColumn))
SET #lFirstRec = ( #lPageNbr - 1 ) * #lPageSize
SET #lLastRec = ( #lPageNbr * #lPageSize + 1 )
SET #lTotalRows = #lFirstRec - #lLastRec + 1
; WITH User_Results
AS (
SELECT ROW_NUMBER() OVER (ORDER BY
CASE WHEN (#lSortCol = 'FirstName' AND #pSortOrder='ASC')
THEN U1.FirstName
END ASC,
CASE WHEN (#lSortCol = 'FirstName' AND #pSortOrder='DESC')
THEN U1.FirstName
END DESC,
CASE WHEN (#lSortCol = 'LastName' AND #pSortOrder='ASC')
THEN U1.LastName
END ASC,
CASE WHEN #lSortCol = 'LastName' AND #pSortOrder='DESC'
THEN U1.LastName
END DESC,
CASE WHEN #lSortCol = 'Email' AND #pSortOrder='ASC'
THEN U1.Email
END ASC,
CASE WHEN #lSortCol = 'Email' AND #pSortOrder='DESC'
THEN U1.Email
END DESC,
CASE WHEN #lSortCol = 'Location' AND #pSortOrder='ASC'
THEN U1.LocationID
END ASC,
CASE WHEN #lSortCol = 'Location' AND #pSortOrder='DESC'
THEN U1.LocationID
END DESC,
CASE WHEN #lSortCol = 'PhoneNumber' AND #pSortOrder='ASC'
THEN U1.PhoneNumber
END ASC,
CASE WHEN #lSortCol = 'PhoneNumber' AND #pSortOrder='DESC'
THEN U1.PhoneNumber
END DESC,
CASE WHEN #lSortCol = 'PseudoName' AND #pSortOrder='ASC'
THEN U1.PseudoName
END ASC,
CASE WHEN #lSortCol = 'PseudoName' AND #pSortOrder='DESC'
THEN U1.PseudoName
END DESC
) AS ROWNUM,
Count(*) over () AS TotalCount,
U1.ID,
U1.FirstName,
U1.LastName,
U1.Email,
DPD.Value as Location,
U1.PhoneNumber,
U2.FirstName+' '+U2.LastName as ReportTo,
U1.PseudoName,
U1.IsActive,
US.ID AS SId,
US.SkillID AS SkillId,
UR.ID AS RId,
UR.RoleID AS RoleId,
U1.Created,
U1.Deleted
FROM dwd.[User] U1 with (nolock)
INNER JOIN dwd.[User] U2 with (nolock) ON U2.ID=U1.ReportTo
INNER JOIN dwd.[DomainParameterDetail] DPD with (nolock) ON DPD.ID=U1.LocationID
INNER JOIN dwd.[UserSkill] US WITH(NOLOCK) ON U1.ID = US.UserID
INNER JOIN dwd.[UserRole] UR WITH(NOLOCK) ON U1.ID = UR.UserID
WHERE
(#lFirstName IS NULL OR U1.FirstName = #lFirstName)
AND(#lLastName IS NULL OR U1.LastName LIKE '%' + #lLastName + '%')
AND(#lEmail IS NULL OR U1.Email LIKE '%' + #lEmail + '%')
AND (#lLocation IS NULL OR U1.LocationID LIKE '%' + #lLocation + '%')
AND (#lPhoneNumber IS NULL OR U1.PhoneNumber = #lPhoneNumber)
AND (#lPseudoName IS NULL OR U1.PseudoName LIKE '%' +#lPseudoName+ '%')
AND U1.IsActive=1 AND U1.Deleted=0 AND U1.ApplicationClientID=#pApplicationClientID
AND U1.ID<>1
)
SELECT
TotalCount,
ROWNUM,
ID,
FirstName,
LastName,
Email,
Location,
PhoneNumber,
ReportTo,
PseudoName,
IsActive,
S
Id,
SkillId,
RId,
RoleId,
Created,
Deleted
FROM User_Results AS USER_GET_RESULT
WHERE
ROWNUM > #lFirstRec
AND ROWNUM < #lLastRec
ORDER BY ROWNUM ASC
Select #TotalCount = Count(*) from dwd.[User]
WHERE IsActive=1 AND Deleted=0 AND ID<>1
Set #pTotalCount = #TotalCount
END
SO I have to get this donw in where clause of SP.
This is a bit long for a comment.
You can only do what you want using dynamic SQL. But, that seems entirely unnecessary, because all the comparisons use LIKE. So, it is better to write the function as:
CREATE FUNCTION dwd.GetSearchCriteria (
#pValue NVARCHAR(50),
#pCriteriaOption NVARCHAR(3)
)
RETURNS varchar(2000)
AS
BEGIN
declare #LIKEPATTERN varchar(2000) ;
SET #LIKEPATTERN = (CASE WHEN #PValue IS NULL THEN ''''''
WHEN #pCriteriaOption = 'ST' THEN '''' + #pValue + '%'''
WHEN #pCriteriaOption = 'ET' THEN '''' + '%' + #pValue + ''''
WHEN #pCriteriaOption = 'CT' THEN '''%' + #pValue + '%'''
ELSE ''''''
END)
RETURN #LIKEPATTERN
END ;
Note: Using an IF and CASE is redundant. The logic can be combined into a single expression. I also think return types should match the type of the variable being returned.
Then you can express the call as:
DECLARE #LIKEPATTERN varchar(2000);
SET #LIKEPATTERN = dwd.GetSearchCriteria('A','ET');
SELECT FirstName FROM dwd.[User] WHERE FirstName LIKE #LIKEPATTERN;
Related
I have two stored procedures that they have the same where clause, one of them is use for pagination:
ALTER PROCEDURE [dbo].[ret_PayrollCalculations_GetPagedFilteredPersonnels]
(
#SortField varchar(512),
#PageNo int,
#PageSize int,
#CalculationCommandType int,
#StartWorkingPeriodId int,
#StartYear int,
#EndWorkingPeriodId int,
#EndYear int,
#Status int,
#SalariedGuid uniqueidentifier,
#SalariedType int,
#OfficeNumber varchar(64),
#SalariedResultSetId int,
#Keyword nvarchar(2024),
#OperationalUnitIds [dbo].[ListOfID] READONLY
)
AS
DECLARE #AccessibleSalariedGuids [dbo].[ListOfGuid]
IF EXISTS (SELECT * FROM #OperationalUnitIDs)
BEGIN
INSERT INTO #AccessibleSalariedGuids
SELECT FeatureGuid FROM prs_OperationalUnitFeatures
WHERE
OperationalUnitID in (SELECT * FROM #OperationalUnitIDs) AND
FeatureFlag IN (2,4)
END
ELSE BEGIN
INSERT INTO #AccessibleSalariedGuids
SELECT [Guid] FROM ret_vwSalaried
END
DECLARE #OffsetRows INT = CASE WHEN #PageNo = 1 THEN 0 ELSE (#PageNo - 1) * #PageSize END;
DECLARE #TotalCount INT;
WITH Result AS(
SELECT
CASE
WHEN #SortField = N'[FullName]' THEN ROW_NUMBER() OVER (ORDER BY salaried.[FullName])
WHEN #SortField = N'[FullName] DESC' THEN ROW_NUMBER() OVER (ORDER BY salaried.[FullName] DESC)
WHEN #SortField = N'[WorkingPeriodTitle]' THEN ROW_NUMBER() OVER (ORDER BY calcs.[Year],workingPeriods.[Index])
WHEN #SortField = N'[WorkingPeriodTitle] DESC' THEN ROW_NUMBER() OVER (ORDER BY calcs.[Year] DESC,workingPeriods.[Index] DESC)
WHEN #SortField = N'[PersonnelNo]' THEN ROW_NUMBER() OVER (ORDER BY salaried.[PersonnelNo])
WHEN #SortField = N'[PersonnelNo] DESC' THEN ROW_NUMBER() OVER (ORDER BY salaried.[PersonnelNo] DESC)
END AS [RowNumber],
calcs.[Guid],
calcs.[CalculationCommandGuid],
calcs.[SalariedGuid],
salaried.[PersonnelNo],
salaried.[FullName] AS [PersonnelFullName],
command.[Type] [CommandType],
salaried.[SalariedType],
workingPeriods.Title AS [WorkingPeriodTitle],
command.[MainYear] AS [Year],
command.[Approved],
command.[FinalApproved]
FROM
ret_PayrollCalculationCommands command INNER JOIN
ret_PayrollCalculations calcs ON calcs.[CalculationCommandGuid] = command.[Guid] INNER JOIN
ret_vwSalaried salaried ON calcs.[SalariedGuid] = salaried.[Guid] INNER JOIN
prs_workingPeriods workingPeriods ON workingPeriods.[Id] = command.[MainWorkingPeriodID]
WHERE
ISNULL(calcs.[MainCalculation],0) = 1 AND
ISNULL(command.[Deleted],0)=0 AND
(#Keyword = '' OR salaried.PersonnelNo = #Keyword OR salaried.FullName LIKE N'%' + #Keyword + '%' OR salaried.FullNameReversed LIKE N'%' + #Keyword + '%') AND
(ISNULL(#calculationCommandType, 0) = 0 OR command.[Type] = #calculationCommandType) AND
(ISNULL(#StartYear, 0) = 0 OR command.[MainYear] >= #StartYear) AND
(ISNULL(#StartWorkingPeriodId, 0) = 0 OR command.[MainWorkingPeriodID] >= #StartWorkingPeriodId) AND
(ISNULL(#EndYear, 0) = 0 OR command.[MainYear] <= #EndYear) AND
(ISNULL(#EndWorkingPeriodId, 0) = 0 OR command.[MainWorkingPeriodID] <= #EndWorkingPeriodId) AND
(ISNULL(#Status, -1) = -1 OR command.[Approved] = #Status) AND
(ISNULL(#SalariedType, -1) = -1 OR salaried.[SalariedType] = #SalariedType) AND
(ISNULL(#SalariedGuid,'00000000-0000-0000-0000-000000000000') = '00000000-0000-0000-0000-000000000000' OR calcs.[SalariedGuid] = #SalariedGuid) AND
(#OfficeNumber IS NULL OR salaried.[OfficeNumber] LIKE '%'+#OfficeNumber+'%') AND
(ISNULL(#SalariedResultSetId, -1) = -1 OR calcs.[SalariedGuid] IN (SELECT [SalariedGuid] FROM ret_SalariedResultSetItems WHERE SalariedResultSetID = #SalariedResultSetId)) AND
(calcs.[SalariedGuid] IN (SELECT * FROM #AccessibleSalariedGuids))
), TableForTotalCount AS (SELECT COUNT(*) As TotalCount FROM Result)
SELECT
(SELECT TOP 1 TotalCount FROM TableForTotalCount) AS TotalCount,
*
FROM Result
ORDER BY
[RowNumber]
OFFSET #OffsetRows ROWS
FETCH NEXT #PageSize ROWS ONLY
and another one supposed to return some Guids
ALTER PROCEDURE [dbo].[ret_PayrollCalculations_GetFilteredPersonnels]
(
#CalculationCommandType int,
#StartWorkingPeriodId int,
#StartYear int,
#EndWorkingPeriodId int,
#EndYear int,
#Status int,
#SalariedGuid uniqueidentifier,
#SalariedType int,
#OfficeNumber varchar(64),
#SalariedResultSetId int,
#Keyword nvarchar(2024),
#OperationalUnitIds [dbo].[ListOfID] READONLY
)
AS
DECLARE #AccessibleSalariedGuids [dbo].[ListOfGuid]
IF EXISTS (SELECT * FROM #OperationalUnitIDs)
BEGIN
INSERT INTO #AccessibleSalariedGuids
SELECT FeatureGuid FROM prs_OperationalUnitFeatures
WHERE
OperationalUnitID in (SELECT * FROM #OperationalUnitIDs) AND
FeatureFlag IN (2,4)
END
ELSE BEGIN
INSERT INTO #AccessibleSalariedGuids
SELECT [Guid] FROM ret_vwSalaried
END
SELECT
calcs.[Guid]
FROM
ret_PayrollCalculationCommands command INNER JOIN
ret_PayrollCalculations calcs ON calcs.[CalculationCommandGuid] = command.[Guid] INNER JOIN
ret_vwSalaried salaried ON calcs.[SalariedGuid] = salaried.[Guid]
WHERE
ISNULL(calcs.[MainCalculation],0) = 1 AND
ISNULL(command.[Deleted],0)=0 AND
(#Keyword = '' OR salaried.PersonnelNo = #Keyword OR salaried.FullName LIKE N'%' + #Keyword + '%' OR salaried.FullNameReversed LIKE N'%' + #Keyword + '%') AND
(ISNULL(#calculationCommandType, 0) = 0 OR command.[Type] = #calculationCommandType) AND
(ISNULL(#StartYear, 0) = 0 OR command.[MainYear] >= #StartYear) AND
(ISNULL(#StartWorkingPeriodId, 0) = 0 OR command.[MainWorkingPeriodID] >= #StartWorkingPeriodId) AND
(ISNULL(#EndYear, 0) = 0 OR command.[MainYear] <= #EndYear) AND
(ISNULL(#EndWorkingPeriodId, 0) = 0 OR command.[MainWorkingPeriodID] <= #EndWorkingPeriodId) AND
(ISNULL(#Status, -1) = -1 OR command.[Approved] = #Status) AND
(ISNULL(#SalariedType, -1) = -1 OR salaried.[SalariedType] = #SalariedType) AND
(ISNULL(#SalariedGuid,'00000000-0000-0000-0000-000000000000') = '00000000-0000-0000-0000-000000000000' OR calcs.[SalariedGuid] = #SalariedGuid) AND
(#OfficeNumber IS NULL OR salaried.[OfficeNumber] LIKE '%'+#OfficeNumber+'%') AND
(ISNULL(#SalariedResultSetId, -1) = -1 OR calcs.[SalariedGuid] IN (SELECT [SalariedGuid] FROM ret_SalariedResultSetItems WHERE SalariedResultSetID = #SalariedResultSetId)) AND
(calcs.[SalariedGuid] IN (SELECT * FROM #AccessibleSalariedGuids))
When a bug appears I have to fix the problem in both stored procedures, to avoid duplication I wanted Where clauses in a function and call the function in stored procedures,
But I don't know how?
This is how I would approach this:
If you're using Microsoft sql-server, you can make transact-sql code.
Convert your sql procedure into a string and make the Where clause a text variable that you declare elsewhere.
So it's creating a meta- procedure.
For eg.
DECLARE #whereClause LONGTEXT;
DECLARE #SQLString LONGTEXT;
SET #whereClause = 'i=1'
SET #SQLString = 'SELECT * FROM table WHERE' & #whereClause
sp_executesql SQLString
I have a stored procedure for paging and searching and I have a parameter #Condition. I need to pass it to the SQL statement in my stored procedures, and in #Condition, I have pass the where clause that is
And p.BrandID=1 And s.Store_Name='xyz'
But I get an error
Msg 102, Level 15, State 1, Line 29
Incorrect syntax near 'p'.
CREATE PROCEDURE [dbo].[spGetProduct]
#DisplayLength int,
#DisplayStart int,
#SortCol int,
#SortDir nvarchar(10),
#Search nvarchar(255) = NULL,
#Condition nvarchar(500) = NULL
as
begin
Declare #FirstRec int, #LastRec int
Set #FirstRec = #DisplayStart;
Set #LastRec = #DisplayStart + #DisplayLength;
DECLARE #ExequteSql NVARCHAR(MAX)
SET #ExequteSql = N'
WITH CTE_Products AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY
CASE WHEN (#SortCol = 3 AND #SortDir = "asc")
THEN p.ProductID
END ASC,
CASE WHEN (#SortCol = 3 AND #SortDir = "desc")
THEN p.ProductID
END DESC,
CASE WHEN (#SortCol = 4 AND #SortDir = "asc")
THEN s.Store_Name
END ASC,
CASE WHEN (#SortCol = 4 AND #SortDir = "desc")
THEN s.Store_Name
END DESC) AS RowNum,
COUNT(*) over() as TotalCount,
p.*, s.Store_Name, ss.SubStore_Name
FROM
((MST_Product p
INNER JOIN
MST_Store s on s.Store_ID = p.BrandID)
INNER JOIN
MST_SubStore ss on ss.SubStore_ID = p.SubStore_ID)
WHERE
(#Search IS NULL
OR p.ProductID LIKE "% + #Search + %"
OR s.Store_Name LIKE "% + #Search + %"
OR ss.SubStore_Name LIKE "% + #Search + %"
OR p.StoreRefCode LIKE "% + #Search + %"
OR p.PName LIKE "% + #Search + %") ' + #Condition + '
)
Select *
from CTE_Products
where RowNum > #FirstRec and RowNum <= #LastRec'
EXEC SP_EXECUTESQL #ExequteSql ,N'#FirstRec INT, #LastRec INT, #Search nvarchar(255), #SortCol int, #SortDir nvarchar(10)' ,
#FirstRec = #FirstRec ,#LastRec = #LastRec, #Search=#Search, #SortCol=#SortCol, #SortDir=#SortDir
END
Error is because of double quotes, It is used for identifiers. For string literals need use single quotes
Made few more changes as well
DECLARE #FirstRec INT,
#LastRec INT
SET #FirstRec = #DisplayStart;
SET #LastRec = #DisplayStart + #DisplayLength;
SET #Search = '%' + #Search + '%'
DECLARE #ExequteSql NVARCHAR(MAX)
SET #ExequteSql = N'
With CTE_Products as
(
Select ROW_NUMBER() over (order by '+case #SortCol when 3 then 'p.ProductID ' when 4 then 's.Store_Name ' end +case when #SortDir = 'asc' then 'asc' else 'desc' end+')
as RowNum,
COUNT(*) over() as TotalCount,
p.*, s.Store_Name, ss.SubStore_Name
from
MST_Product p INNER JOIN MST_Store s on s.Store_ID = p.BrandID
INNER JOIN MST_SubStore ss on ss.SubStore_ID = p.SubStore_ID
where (#Search IS NULL
Or p.ProductID like #Search
Or s.Store_Name like #Search
Or ss.SubStore_Name like #Search
Or p.StoreRefCode like #Search
Or p.PName like #Search ) '
+ #Condition
+ '
)
Select *
from CTE_Products
where RowNum > #FirstRec and RowNum <= #LastRec'
print #ExequteSql
EXEC Sp_executesql
#ExequteSql,
N'#FirstRec INT, #LastRec INT, #Search nvarchar(255), #SortCol int, #SortDir nvarchar(10)',
#FirstRec = #FirstRec,
#LastRec = #LastRec,
#Search=#Search,
#SortCol=#SortCol,
#SortDir=#SortDir
To call the procedure
EXEC Spgetproduct
#DisplayLength = 1,
#DisplayStart = 1,
#SortCol = 3,
#SortDir ='asc',
#Search = 'ab',
#Condition = ' And p.BrandID=1 And s.Store_Name=''xyz''' -- here you need to double the single quotes
I have a stored procedure as following, I need to pass paramters to the dynamic pivot. My query runs, I just need to do some filtering based on the passed parameters
-- AND (#SelectedSystemIDs IS NULL OR System.ID IN(select * from dbo.SplitInts_RBAR_1(#SelectedSystemIDs, ',')))
--AND ((#PlatformID IS NULL) OR (System.PlatformID = #PlatformID) OR (#PlatformID = 12 AND System.PlatformID <= 2))
-- AND (ServiceEntry.ServiceDateTime between #StartDate and #EndDate)
so I want to add the above criteria, how could achieve that?
ALTER PROCEDURE [dbo].[spExportStuff]
(#StartDate datetime,
#EndDate datetime,
#SelectedSystemIDs nvarchar (2000) = NULL,
#SelectedTsbIDs nvarchar (2000) = NULL,
#UserRoleID int
)
AS
DECLARE #InstrumentType int = NULL
DECLARE #PlatformID int = null
IF (#SelectedSystemIDs = '')
begin
SET #SelectedSystemIDs = NULL
END
IF (#SelectedTsbIDs = '')
begin
SET #SelectedTsbIDs = NULL
END
IF(#UserRoleID = 1)
BEGIN
SET #PlatformID = 1
END
IF(#UserRoleID = 2)
BEGIN
SET #PlatformID = 2
END
IF (#UserRoleID = 3)
BEGIN
SET #PlatformID = 12
END
IF(#UserRoleID = 4)
BEGIN
SET #PlatformID = 3
END
IF(#UserRoleID = 5)
BEGIN
SET #PlatformID = 4
END
IF(#UserRoleID = 6)
BEGIN
SET #PlatformID = NULL
END
DECLARE #PivotColumnHeaders NVARCHAR(MAX)
SELECT #PivotColumnHeaders =
COALESCE(
#PivotColumnHeaders + ',[' + cast(SystemFullName as Nvarchar) + ']',
'[' + cast(SystemFullName as varchar)+ ']'
)
FROM System
DECLARE #PivotTableSQL NVARCHAR(MAX)
SET #PivotTableSQL = N'
SELECT *
FROM (
SELECT
TSBNumber [TSBNumber],
SystemFullName,
ClosedDate
FROM ServiceEntry
INNER JOIN System
ON ServiceEntry.SystemID = System.ID
Group By TSBNumber, SystemFullName, ClosedDate
) AS PivotData
PIVOT (
max(ClosedDate)
FOR SystemFullName IN (
' + #PivotColumnHeaders + '
)
) AS PivotTable
'
EXECUTE(#PivotTableSQL)
you can construct the required criteria as another input to the stored procedure and append it to the dynamic query
ALTER PROCEDURE [dbo].[spExportStuff]
(#StartDate datetime,
#EndDate datetime,
#SelectedSystemIDs nvarchar (2000) = NULL,
#SelectedTsbIDs nvarchar (2000) = NULL,
#UserRoleID int,
#WhereClause varchar(max) -> this is the new parameter.
)
DECLARE #PivotTableSQL NVARCHAR(MAX)
SET #PivotTableSQL = N'
SELECT *
FROM (
SELECT
TSBNumber [TSBNumber],
SystemFullName,
ClosedDate
FROM ServiceEntry
INNER JOIN System
ON ServiceEntry.SystemID = System.ID
Group By TSBNumber, SystemFullName, ClosedDate
) AS PivotData
PIVOT (
max(ClosedDate)
FOR SystemFullName IN (
' + #PivotColumnHeaders + '
)
) AS PivotTable
' + #WhereClause -> you can append the where clause here.
EXECUTE(#PivotTableSQL)
I have this stored procedure:
exec SearchResume #KeywordSearch=N'', #GreaterThanDate='2013-09-22 00:00:00',
#CityIDs=N'0,56,31,271,117,327,3,328,228',
#ProvinceIDs=N'0,1,12,13',
#CountryIDs=N'1',
#IndustryIDs=N'0,2,3,4,38,113,114,115,116,117'
Which doesn't return any results because the ids are in nvarchar but the actual values are integer.
Now, when I test the actual SP with a manual list of int values I'm able to get the results, this is the example:
SELECT DISTINCT
UserID,
ResumeID,
CASE a.Confidential WHEN 1 THEN 'Confidential' ELSE LastName + ',' + FirstName END as 'Name',
a.Description 'ResumeTitle',
CurrentTitle,
ModifiedDate,
CASE ISNULL(b.SalaryRangeID, '0') WHEN '0' THEN CAST(SalarySpecific as nvarchar(8)) ELSE c.Description END 'Salary',
h.Description 'Relocate',
i.Description + '-' + j.Description + '-' + k.Description 'Location'
FROM dbo.Resume a JOIN dbo.Candidate b ON a.CandidateID = b.CandidateID
LEFT OUTER JOIN SalaryRange c ON b.SalaryRangeID = c.SalaryRangeID
JOIN EducationLevel e ON b.EducationLevelID = e.EducationLevelID
JOIN CareerLevel f ON b.CareerLevelID = f.CareerLevelID
JOIN JobType g ON b.JobTypeID = g.JobTypeID
JOIN WillingToRelocate h ON b.WillingToRelocateID = h.WillingToRelocateID
JOIN City i ON b.CityID = i.CityID
JOIN StateProvince j ON j.StateProvinceID = b.StateProvinceID
JOIN Country k ON k.CountryID = b.CountryID
WHERE (b.CityID IN (0,56,31,125,229,5,219,8,228))
AND (b.StateProvinceID IN (0,1,13))
AND (b.CountryID IN (1))
AND (b.IndustryPreferenceID IN (0,2,3,4,5,6,115,116,117))
I would like to know what can I do to send a list of int values, not a list of nvarchar values since as you can see the query doesn't work properly.
Update
Original SP:
ALTER PROCEDURE [dbo].[SearchResume]
#KeywordSearch nvarchar(500),
#GreaterThanDate datetime,
#CityIDs nvarchar(500),
#ProvinceIDs nvarchar(500),
#CountryIDs nvarchar(500),
#IndustryIDs nvarchar(500)
AS
BEGIN
DECLARE #sql as nvarchar(4000)
SET #sql = 'SELECT DISTINCT
UserID,
ResumeID,
CASE a.Confidential WHEN 1 THEN ''Confidential'' ELSE LastName + '','' + FirstName END as ''Name'',
a.Description ''ResumeTitle'',
CurrentTitle,
ModifiedDate,
CurrentEmployerName,
PersonalDescription,
CareerObjectives,
CASE ISNULL(b.SalaryRangeID, ''0'') WHEN ''0'' THEN CAST(SalarySpecific as nvarchar(8)) ELSE c.Description END ''Salary'',
e.Description ''EducationLevel'',
f.Description ''CareerLevel'',
g.Description ''JobType'',
h.Description ''Relocate'',
i.Description + ''-'' + j.Description + ''-'' + k.Description ''Location''
FROM dbo.Resume a JOIN dbo.Candidate b ON a.CandidateID = b.CandidateID
LEFT OUTER JOIN SalaryRange c ON b.SalaryRangeID = c.SalaryRangeID
JOIN EducationLevel e ON b.EducationLevelID = e.EducationLevelID
JOIN CareerLevel f ON b.CareerLevelID = f.CareerLevelID
JOIN JobType g ON b.JobTypeID = g.JobTypeID
JOIN WillingToRelocate h ON b.WillingToRelocateID = h.WillingToRelocateID
JOIN City i ON b.CityID = i.CityID
JOIN StateProvince j ON j.StateProvinceID = b.StateProvinceID
JOIN Country k ON k.CountryID = b.CountryID
WHERE ( (ModifiedDate > ''' + CAST(#GreaterThanDate as nvarchar(55)) + ''')
'
IF (LEN(#CityIDs) >0)
BEGIN
SET #sql = #sql + 'AND (b.CityID IN (' + #CityIDs + '))'
END
IF (LEN(#ProvinceIDs) >0)
BEGIN
SET #sql = #sql + 'AND (b.StateProvinceID IN (' + #ProvinceIDs + '))'
END
IF (LEN(#CountryIDs) >0)
BEGIN
SET #sql = #sql + 'AND (b.CountryID IN (' + #CountryIDs + '))'
END
IF (LEN(#IndustryIDs) >0)
BEGIN
SET #sql = #sql + 'AND (b.IndustryPreferenceID IN (' + #IndustryIDs + '))'
END
IF (LEN(#KeywordSearch) > 0)
BEGIN
SET #sql = #sql + ' AND (' + #KeywordSearch + ')'
END
SET #sql = #sql + ') ORDER BY ModifiedDate desc'
--select #sql
exec sp_executesql #sql
END
You can create a Table-Valued Function which takes the nVarChar and creates a new record for each value, where you tell it the delimiter. My example here returns a table with a single Value column, you can then use this as a sub query for your IN Selection :
Create FUNCTION [dbo].[fnSplitVariable]
(
#List nvarchar(2000),
#delimiter nvarchar(5)
)
RETURNS #RtnValue table
(
Id int identity(1,1),
Variable varchar(15),
Value nvarchar(100)
)
AS
BEGIN
Declare #Count int
set #Count = 1
While (Charindex(#delimiter,#List)>0)
Begin
Insert Into #RtnValue (Value, Variable)
Select
Value = ltrim(rtrim(Substring(#List,1,Charindex(#delimiter,#List)-1))),
Variable = 'V' + convert(varchar,#Count)
Set #List = Substring(#List,Charindex(#delimiter,#List)+len(#delimiter),len(#List))
Set #Count = #Count + 1
End
Insert Into #RtnValue (Value, Variable)
Select Value = ltrim(rtrim(#List)), Variable = 'V' + convert(varchar,#Count)
Return
END
Then in your where statement you could do the following:
WHERE (b.CityID IN (Select Value from fnSplitVariable(#CityIDs, ','))
I have included your original Procedure, and updated it to use the function above:
ALTER PROCEDURE [dbo].[SearchResume]
#KeywordSearch nvarchar(500),
#GreaterThanDate datetime,
#CityIDs nvarchar(500),
#ProvinceIDs nvarchar(500),
#CountryIDs nvarchar(500),
#IndustryIDs nvarchar(500)
AS
BEGIN
DECLARE #sql as nvarchar(4000)
SET #sql = N'
DECLARE #KeywordSearch nvarchar(500),
#CityIDs nvarchar(500),
#ProvinceIDs nvarchar(500),
#CountryIDs nvarchar(500),
#IndustryIDs nvarchar(500)
SET #KeywordSearch = '''+#KeywordSearch+'''
SET #CityIDs = '''+#CityIDs+'''
SET #ProvinceIDs = '''+#ProvinceIDs+'''
SET #CountryIDs = '''+#CountryIDs+'''
SET #IndustryIDs = '''+#IndustryIDs+'''
SELECT DISTINCT
UserID,
ResumeID,
CASE a.Confidential WHEN 1 THEN ''Confidential'' ELSE LastName + '','' + FirstName END as ''Name'',
a.Description ''ResumeTitle'',
CurrentTitle,
ModifiedDate,
CurrentEmployerName,
PersonalDescription,
CareerObjectives,
CASE ISNULL(b.SalaryRangeID, ''0'') WHEN ''0'' THEN CAST(SalarySpecific as nvarchar(8)) ELSE c.Description END ''Salary'',
e.Description ''EducationLevel'',
f.Description ''CareerLevel'',
g.Description ''JobType'',
h.Description ''Relocate'',
i.Description + ''-'' + j.Description + ''-'' + k.Description ''Location''
FROM dbo.Resume a JOIN dbo.Candidate b ON a.CandidateID = b.CandidateID
LEFT OUTER JOIN SalaryRange c ON b.SalaryRangeID = c.SalaryRangeID
JOIN EducationLevel e ON b.EducationLevelID = e.EducationLevelID
JOIN CareerLevel f ON b.CareerLevelID = f.CareerLevelID
JOIN JobType g ON b.JobTypeID = g.JobTypeID
JOIN WillingToRelocate h ON b.WillingToRelocateID = h.WillingToRelocateID
JOIN City i ON b.CityID = i.CityID
JOIN StateProvince j ON j.StateProvinceID = b.StateProvinceID
JOIN Country k ON k.CountryID = b.CountryID
WHERE ( (ModifiedDate > ''' + CAST(#GreaterThanDate as nvarchar(55)) + ''')
'
IF (LEN(#CityIDs) >0)
BEGIN
SET #sql = #sql + N'AND (b.CityID IN (Select Value from fnSplitVariable(#CityIDs,'','') ))'
END
IF (LEN(#ProvinceIDs) >0)
BEGIN
SET #sql = #sql + N'AND (b.StateProvinceID IN (Select Value from fnSplitVariable(#ProvinceIDs,'','') ))'
END
IF (LEN(#CountryIDs) >0)
BEGIN
SET #sql = #sql + N'AND (b.CountryID IN (Select Value from fnSplitVariable(#CountryIDs,'','') ))'
END
IF (LEN(#IndustryIDs) >0)
BEGIN
SET #sql = #sql + N'AND (b.IndustryPreferenceID IN (Select Value from fnSplitVariable(#IndustryIDs,'','') ))'
END
IF (LEN(#KeywordSearch) > 0)
BEGIN
SET #sql = #sql + N' AND (' + #KeywordSearch + ')'
END
SET #sql = #sql + N') ORDER BY ModifiedDate desc'
--select #sql
exec sp_executesql #sql
END
DECLARE #SQL AS NVARCHAR(MAX)
SET #SQL = 'SELECT DISTINCT
UserID,
ResumeID,
CASE a.Confidential WHEN 1 THEN ''Confidential'' ELSE LastName + '','' + FirstName END as ''Name'',
a.Description ''ResumeTitle'',
CurrentTitle,
ModifiedDate,
CASE ISNULL(b.SalaryRangeID, ''0'') WHEN ''0'' THEN CAST(SalarySpecific as nvarchar(8)) ELSE c.Description END ''Salary'',
h.Description ''Relocate'',
i.Description + ''-'' + j.Description + ''-'' + k.Description ''Location''
FROM dbo.Resume a JOIN dbo.Candidate b ON a.CandidateID = b.CandidateID
LEFT OUTER JOIN SalaryRange c ON b.SalaryRangeID = c.SalaryRangeID
JOIN EducationLevel e ON b.EducationLevelID = e.EducationLevelID
JOIN CareerLevel f ON b.CareerLevelID = f.CareerLevelID
JOIN JobType g ON b.JobTypeID = g.JobTypeID
JOIN WillingToRelocate h ON b.WillingToRelocateID = h.WillingToRelocateID
JOIN City i ON b.CityID = i.CityID
JOIN StateProvince j ON j.StateProvinceID = b.StateProvinceID
JOIN Country k ON k.CountryID = b.CountryID
WHERE (b.CityID IN (' + #CityIDs + '))
AND (b.StateProvinceID IN (' + #ProvinceIDs + '))
AND (b.CountryID IN (' + #CountryIDs + '))
AND (b.IndustryPreferenceID IN (' + #IndustryIDs + '))'
EXEC #SQL
You could do a split on the id's that are coming in to the store procedure. So consider this split function:
CREATE FUNCTION [dbo].[Split]
(
#String NVARCHAR(4000),
#Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
WITH Split(stpos,endpos)
AS(
SELECT 0 AS stpos, CHARINDEX(#Delimiter,#String) AS endpos
UNION ALL
SELECT endpos+1, CHARINDEX(#Delimiter,#String,endpos+1)
FROM Split
WHERE endpos > 0
)
SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
'Data' = SUBSTRING(#String,stpos,COALESCE(NULLIF(endpos,0),LEN(#String)+1)-stpos)
FROM Split
)
Then you could write your where statement like this:
WHERE
EXISTS(SELECT NULL FROM dbo.Split(#CityIDs,',') AS city
WHERE city.Data=b.CityID)
AND EXISTS(SELECT NULL FROM dbo.Split(#ProvinceIDs,',') AS Province
WHERE Province.Data=b.StateProvinceID)
AND EXISTS(SELECT NULL FROM dbo.Split(#CountryIDs,',') AS Country
WHERE Country.Data=b.CountryID)
AND EXISTS(SELECT NULL FROM dbo.Split(#IndustryIDs,',') AS Industry
WHERE Industry.Data=b.IndustryPreferenceID)
I don't know how exactly I should frame my Question as even I don't know what exactly I have to search. May be this is the best place to put my question. I want to use If condition in where clause this can be done using case but my problem is I don't want to use it after a column name instead I want to avoid entire execution of that column. You can understand it by going through my procedure in the last I have commented, So I want to achieve something like that as I want to write the same procedure again for that condition which i think can be achievable by doing something like that. I searched on internet what I got is to use case in where which doesn't satisfy my purpose. Please look the last lines to understand the problem. Thanx
USE [overseascrm]
GO
/****** Object: StoredProcedure [dbo].[candidatesearch] Script Date: 05-07-2014 00:48:17 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[candidatesearch]
#candidate_id varchar(50),
#firstname varchar(50),
#lastname varchar(50),
#emailid_1 varchar(100),
#mobile_1 varchar(20),
#from varchar(50),
#to varchar(50),
#agentid varchar(50),
#passportno varchar(50),
#profession int,
#isactive bit
as
begin
DECLARE #candidateid_var varchar(50)
DECLARE #firstname_var varchar(50)
DECLARE #lastname_var varchar(50)
DECLARE #emailid1_var varchar(100)
DECLARE #mobile_1_var varchar(20)
DECLARE #agentid_var varchar(50)
IF(#agentid = '')
begin
SET #agentid_var = '%'
END ELSE BEGIN
SET #agentid_var = #agentid
END
IF (#candidate_id = '') BEGIN
SET #candidateid_var = '%'
END ELSE BEGIN
SET #candidateid_var = #candidate_id
END
IF (#firstname = '') BEGIN
SET #firstname_var = '%'
END ELSE BEGIN
SET #firstname_var = #firstname
END
IF (#lastname = '') BEGIN
SET #lastname_var = '%'
END ELSE BEGIN
SET #lastname_var = #lastname
END
IF (#emailid_1 = '') BEGIN
SET #emailid1_var = '%'
END ELSE BEGIN
SET #emailid1_var = #emailid_1
END
IF (#mobile_1 = '') BEGIN
SET #mobile_1_var = '%'
END ELSE BEGIN
SET #mobile_1_var = #mobile_1
END
IF (#from = '') BEGIN
SELECT
*
FROM candidate C
LEFT JOIN candidate_profession_map CM
ON C.candidate_id = CM.candidate_id
LEFT JOIN passport_details PD
ON C.candidate_id = PD.candidate_id
WHERE C.candidate_id LIKE '' + #candidateid_var + '%'
AND firstname LIKE '' + #firstname_var + '%'
AND lastname LIKE '' + #lastname_var + '%'
AND emailid_1 LIKE '' + #emailid1_var + '%'
AND mobile_1 LIKE '' + #mobile_1_var + '%'
AND agent_id LIKE '' + #agentid_var + '%'
AND CM.profession_id = #profession
AND C.isactive = #isactive
AND PD.passport_no = #passportno
END ELSE BEGIN
SELECT
*
FROM candidate C
LEFT JOIN candidate_profession_map CM
ON C.candidate_id = CM.candidate_id
LEFT JOIN passport_details PD
ON C.candidate_id = PD.candidate_id
WHERE C.candidate_id LIKE '' + #candidateid_var + '%'
AND firstname LIKE '' + #firstname_var + '%'
AND lastname LIKE '' + #lastname_var + '%'
AND emailid_1 LIKE '' + #emailid1_var + '%'
AND mobile_1 LIKE '' + #mobile_1_var + '%'
AND agent_id LIKE '' + #agentid_var + '%'
AND C.addedon BETWEEN CONVERT(DATETIME, #from, 103) AND CONVERT(DATETIME, #to, 103)
--IF (#profession <> 0)BEGIN
--AND CM.profession_id = #profession
--END
AND C.isactive = #isactive
OR PD.passport_no = #passportno
END
END
You could use dynamic sql execution where you create your select statement as varchar to your liking, executing it at the end using sp_executesql
http://msdn.microsoft.com/en-us/library/ms188001.aspx
ALTER procedure [dbo].[candidatesearch]
#candidate_id varchar(50),
#firstname varchar(50),
#lastname varchar(50),
#emailid_1 varchar(100),
#mobile_1 varchar(20),
#from varchar(50),
#to varchar(50),
#agentid varchar(50),
#passportno varchar(50),
#profession int,
#isactive bit
AS Begin
SELECT *
FROM candidate C
LEFT JOIN candidate_profession_map CM ON C.candidate_id = CM.candidate_id
LEFT JOIN passport_details PD ON C.candidate_id = PD.candidate_id
WHERE (#candidateid='' or C.candidate_id LIKE #candidateid + '%')
AND (#firstname = '' or firstname LIKE #firstname + '%')
AND (#lastname = '' or lastname LIKE #lastname + '%')
AND (#emailid_1='' or emailid_1 LIKE #emailid1 + '%')
AND (#mobile_1 = '' or mobile_1 LIKE #mobile_1 + '%')
AND (#agentid='' agent_id LIKE #agentid + '%')
AND C.isactive = #isactive
And ((#from=''
AND CM.profession_id = #profession
AND PD.passport_no = #passportno)
or (#from<>''
And C.addedon BETWEEN CONVERT(DATETIME, #from, 103) AND CONVERT(DATETIME, #to, 103)
OR PD.passport_no = #passportno)
End