declare #d varchar
set #d = 'No filter'
if (#d like 'No filter')
BEGIN
select 'matched'
end
else
begin
select 'not matched'
end
the result of above is always not matched can anybody tell me why and how can I use the like or '=' result in my stored procedure.
thanks
Change your declaration to
declare #d varchar(10)
Then
declare #d varchar(10)
set #d = 'No filter'
if (#d LIKE 'No filter')
BEGIN
select 'matched'
end
else
begin
select 'not matched'
end
will work.
Please remember that LIKE is used for pattern matching,
something like
DECLARE #Val VARCHAR(10)
SET #Val = 'foo bar'
if (#Val LIKE '%foo%')
BEGIN
select 'matched'
end
else
begin
select 'not matched'
end
So in your case you might want to change the code to
declare #d varchar(10)
set #d = 'No filter'
if (#d = 'No filter')
BEGIN
select 'matched'
end
else
begin
select 'not matched'
end
with an "="
You need to declare d as varchar(100) not just varchar, otherwise it just becomes N
declare #d varchar
set #d = 'No filter'
Should be:
declare #d varchar(100)
set #d = 'No filter'
Also no need to use LIKE with this you can use =.
I find like operator very useful.
IF(
#PLI_Component = '' + #ITemID + '' +'BD'
OR #PLI_Component = '' + #ITemID + '' +'BD/1'
OR #PLI_Component = '' + #ITemID + '' +'BD/2'
OR #PLI_Component = '' + #ITemID + '' +'BD/3'
OR #PLI_Component = '' + #ITemID + '' +'BD/4'
OR #PLI_Component = '' + #ITemID + '' +'BD/5'
)
can be replaced
by only one line which is
#PLI_Component LIKE #ITemID +'BD'
Cheers
Related
I am trying to build a dynamic query in sybase like:
SELECT #v_query = #v_query + " tech= "+ ISNULL(''''+#stat+'''',"tech")
When I pass #stat as NULL, I get '' as output but expected output is tech which is wrong
If I pass#stat as NACK, it should return 'NACK' which works as expected
Thanks for any suggestions on how to achieve this
To be honest, you probably want this:
SELECT #v_query = #v_query +
(CASE WHEN #stat IS NULL THEN '1=1'
ELSE 'tech = ''' + #stat + ''''
END)
Don't use tech = tech as a no-op (it doesn't work for NULLs). Instead, just remove the comparison.
remove the '' and retry
declare #SQL_TXT varchar(100)
declare #stat varchar(100)
begin
select #stat= null
SELECT #SQL_TXT=#SQL_TXT + ' tech =' + ISNULL(#stat,'tech')
print #SQL_TXT
end
print tech =tech
edit you can do it like this
declare #SQL_TXT varchar(100)
declare #stat varchar(100)
begin
select #stat= null
SELECT #SQL_TXT=#SQL_TXT + ' tech = ''' + ISNULL(#stat,'tech') +''''
print #SQL_TXT
end
it seems adding quotes in null function give null value , can you add quotes originally to the variable as alternative ?
declare #SQL_TXT varchar(100)
declare #stat varchar(100)
begin
select #stat= 'SAMPLE'
select #stat= ''''+#stat+''''
SELECT #SQL_TXT=#SQL_TXT + ' tech = ' + ISNULL(#stat,'tech')
print #SQL_TXT
end
I am trying to create optional parameters in a stored process in which I group by the parameters under certain conditions.
For example:
SELECT
TP.ProductID,
case
when #passangers='Y' then (TP.Passangersgroup)
when #fareclass='Y' then (TP.Fareclass)
when #ispriorbooking='Y' then (TP.IsPriorBooking)
end
INTO ##B
FROM ##A TP
GROUP BY
TP.ProductID,
case
when #passangers='Y' then (TP.Passangersgroup)
when #fareclass='Y' then (TP.Fareclass)
when #ispriorbooking='Y' then (TP.IsPriorBooking)
end
In this case, I would be able to select 'Y' for any of the 3 parameters, and I would want to add them to select statement and group by.
Any ideas?
You need to do this with dynamic SQL; something like:
declare #sql varchar(max) = 'SELECT
TP.ProductID, ' +
case when #passangers='Y' then 'TP.Passangersgroup'
when #fareclass='Y' then 'TP.Fareclass'
when #ispriorbooking='Y' then 'TP.IsPriorBooking'
else ''
end
+ ' INTO ##B
FROM ##A TP'
--ETC
Exec(#sql)
If you want to add up to all three columns, you need three case statements:
declare #sql varchar(max) = 'SELECT
TP.ProductID, ' +
case when #passangers='Y' then 'TP.Passangersgroup' else '' end
+ case when #fareclass='Y' then 'TP.Fareclass' else '' end
--ETC.
+ ' INTO ##B
FROM ##A TP'
Dynamic SQL will be the best bet, but I would figure out the column you want and then pass in the one column as a variable. Less likely to suffer SQL injection and more readable.
DECLARE #passangers CHAR(1), #fareclass CHAR(1), #ispriorbooking CHAR(1)
SET #passangers='Y'
DECLARE #SQLCMD NVARCHAR(MAX), #YValue NVARCHAR(1000)
--set the select and group by field
SELECT #YValue=
case
when #passangers='Y' then N'TP.Passangersgroup'
when #fareclass='Y' then N'TP.Fareclass'
when #ispriorbooking='Y' then N'TP.IsPriorBooking'
else NULL
end
IF #YValue IS NOT NULL
BEGIN
SET #SQLCMD=N'
SELECT
TP.ProductID,'+#YValue+'
INTO ##B
FROM ##A TP
GROUP BY
TP.ProductID, '+#YValue
PRINT #SQLCMD
--EXEC sp_executesql #SQLCMD
END
ELSE
PRINT 'INVALID PARAMETER PASSED IN'
You have to use dynamic sql but case statement mentioned in Steve Mangiameli code will not work in case when more than one column is selected as 'Y'. The below code will be working fine for multiple columns selected as 'Y'-
create procedure proc1
#passangers varchar(100) = null,
#fareclass varchar(100) = null,
#ispriorbooking varchar(100) = null
as
begin
declare #sql nvarchar(100)
declare #var varchar(100)
if #passangers = 'y'
set #var = tp.Passangersgroup + ', '
if #fareclass = 'y'
set #var = #var + TP.Fareclass + ', '
if #ispriorbooking = 'y'
set #var = #var + TP.IsPriorBooking
set #sql = 'select ' + #var + ' into ##b from ##a as TP group by ' + #var + 'option(recomplile)'
exec sp_executesql #sql
end
I have table similar to:
Create Table #test (Letter varchar(5), Products varchar(30))
Insert into #test (Letter, Products)
Values ('A','B,C,D,E,F'),('B','B,C,D,E,F'),('G','B,C,D,E,F'),('Z','B,C,D,E,F'),('E','B,C,D,E,F')
Is it possible to write a CASE Statement which will check if the list in the 'Products' column contain a letter from 'Letter' column?
Thanks
Here is the query
Select *, Case When (charindex(Letter, Products, 0)>0) Then 'Yes' Else 'No' End AS [Y/N] from #test
I think i managed to do the trick:
CASE WHEN Products LIKE '%'+Letter+'%' THEN 'TRUE' ELSE 'FALSE' END
You could use EXISTS with a split-function:
SELECT Letter, Products,
ContainsLetter = CASE WHEN EXISTS
(
SELECT 1 FROM dbo.Split(t1.Products, ',')s
WHERE s.Item = Letter
)
THEN 'Yes' ELSE 'No' END
FROM #test t1
Demo
Here is the one i'm using on SQL-Server 2005:
CREATE FUNCTION [dbo].[Split]
(
#ItemList NVARCHAR(MAX),
#delimiter CHAR(1)
)
RETURNS #ItemTable TABLE (Item VARCHAR(250))
AS
BEGIN
DECLARE #tempItemList NVARCHAR(MAX)
SET #tempItemList = #ItemList
DECLARE #i INT
DECLARE #Item NVARCHAR(4000)
SET #i = CHARINDEX(#delimiter, #tempItemList)
WHILE (LEN(#tempItemList) > 0)
BEGIN
IF #i = 0
SET #Item = #tempItemList
ELSE
SET #Item = LEFT(#tempItemList, #i - 1)
INSERT INTO #ItemTable(Item) VALUES(#Item)
IF #i = 0
SET #tempItemList = ''
ELSE
SET #tempItemList = RIGHT(#tempItemList, LEN(#tempItemList) - #i)
SET #i = CHARINDEX(#delimiter, #tempItemList)
END
RETURN
END
I'm need to write a stored procedure for SQL Server 2008 for performing a large select query and I need it to filter results with specifying filtering type via procedure's parameters. I found some solutions like this:
create table Foo(
id bigint, code char, name nvarchar(max))
go
insert into Foo values
(1,'a','aaa'),
(2,'b','bbb'),
(3,'c','ccc')
go
create procedure Bar
#FilterType nvarchar(max),
#FilterValue nvarchar(max) as
begin
select * from Foo as f
where case #FilterType
when 'by_id' then f.id
when 'by_code' then f.code
when 'by_name' then f.name end
=
case #FilterType
when 'by_id' then cast(#FilterValue as bigint)
when 'by_code' then cast(#FilterValue as char)
when 'by_name' then #FilterValue end
end
go
exec Bar 'by_id', '1';
exec Bar 'by_code', 'b';
exec Bar 'by_name', 'ccc';
I'm finding that this approach doesn't work. It's possible to cast all the columns to nvarchar(max) and compare them as strings, but I think it will cause performance degradation.
Is it possible to parametrize the where clause in stored procedure without using constructs like EXEC sp_executesql?
This may become a little more long winded, for large filter requirements, but I think it probably more performant/easier to read/maintain:
create procedure Bar
#Id int,
#Code nvarchar,
#name nvarchar
begin
select * from Foo as f
where (#id = -1 or f.ID = #id)
and (#Code = '' or f.Code = #Code)
and (#Name = '' or f.Name = #Name)
end
go
exec Bar 1, '', ''
exec Bar -1, 'code', ''
exec Bar -1, '', 'name'
This also allows you to filter by more than one item at the same time.
Try this
create procedure Bar
#FilterType nvarchar(max),
#FilterValue nvarchar(max) as
begin
select * from Foo as f
where
(#FilterType ='by_id' and f.id =cast(#FilterValue as bigint) )
OR
(#FilterType ='by_code' and f.code =cast(#FilterValue as char)
OR
(#FilterType ='by_name' and f.name =#FilterValue
end
go
declare #field varchar(20)
declare #value varchar(100)
set #field = 'customerid'
set #value = 'ALFKI'
set #field = 'Country'
set #value = 'Germany'
set #field = 'ContactTitle'
set #value = 'Owner'
select * from customers
where (customerid = (case when #field = 'customerid' then #value else customerid end)
and ContactTitle = (case when #field = 'ContactTitle' then #value else ContactTitle end)
and country = (case when #field = 'Country' then #value else country end))
Example is adapted for Northwind database.
Hope this helps.
EDIT: Comment any 2 out of the 3 values for #field and #value for above.
If you don't have many filtering criteria, you could consider creating delegate functions and dispatching the request to the appropriate one. E.g.,
create procedure Bar
#FilterType nvarchar(max),
#FilterValue nvarchar(max) as
begin
case #FilterType
when 'by_id' then FilterById(#FilterValue)
when 'by_code' then FilterByCode(#FilterValue)
when 'by_name' then FilterByName(#FilterValue)
end
end
go
CREATE PROCEDURE USP_SEARCH_HOTELS
(
#Text varchar(50),
#Type varchar(40)
)
AS
BEGIN
Declare #Query VARCHAR(60)
IF #Type = 'By Country'
BEGIN
SET #Query = 'Hotel.countryName like '+ #Text+'%'
END
ELSE IF #Type = 'By State'
BEGIN
SET #Query = 'HOTEL.stateName like '+ #Text+'%'
END
ELSE IF #Type='By Property Name'
BEGIN
SET #Query='hotel.propertyname like'+ #Text+'%'
End
ELSE IF #Type='By Rating'
BEGIN
SET #Query='hotel.starRating='+ Cast(#Text as INT)
END
ELSE IF #Type='By City'
BEGIN
SET #Query='hotel.cityName like '+ #Text+'%'
END
begin
select * from hotel,tbl_cust_info
where
hotel.agentID=Tbl_Cust_Info.Cust_ID
and
(#Query)
end
END
WHAT IS THE ERROR IN THIS PROCEDURE PLEASE HELP.
DECLARE #Final nvarchar(1000) -- Separate partial and final
DECLARE #Partial nvarchar(100) -- let's you maintain and debug better
SET #Final = 'select * from hotel
join tbl_cust_info
on hotel.agentID=Tbl_Cust_Info.Cust_ID
where' + #Partial
Assumiung that you are invioking this via .NET run a Regexp on the Text to eliminate all chars that are not letters or space. Like [!##$%^&*()?;:'"\|].
Consider rewriting as 5 sprocs (HotelsByCountry, HotelsByState, HotelsByCity, HotelsByName, HotelsByRating). That will increase you perf and let you do orderby and paging (like Row_number() OVER(order by StartDate)). It will also make them totally safe.