Using a CASE statement in a WHERE clause in SQL Server - sql

I am trying to create query form on a website. First object is a dropdown list with operators. Default first value in the dropdown list is NULL(1), second value is LIKE(2), etc... Second object is a textbox where the user can enter a string like "A".
Therefore, I am trying to build the below SQL query to simulate the variables coming from the website. It runs and returns all values when the #op = 1. But I keep getting the following error when I change #op = 2:
Conversion failed when converting the nvarchar value 'Tom LIKE A%' to data type int."
DECLARE #StartDate DATETIME2(7) = '2017-11-08 00:00:00.0000000 +00:00'
DECLARE #EndDate DATETIME2(7) = '2017-11-08 00:00:00.0000000 +00:00'
DECLARE #Op INT = 2
DECLARE #name NVARCHAR(25) = 'A'
SELECT
name,
dttm
FROM
tableName
WHERE
dttm BETWEEN #StartDate AND #EndDate
AND CASE #Op
WHEN 1 THEN 1
WHEN 2 THEN name + ' LIKE ' + #name +'%'
END <> 0

Don't use case. Just use regular boolean logic:
WHERE dttm BETWEEN #StartDate AND #EndDate AND
( (#op = 1) OR
(#op = 2 AND name LIKE #name + '%')
)
Your specific issue involves constructing a LIKE comparison in a string. However, the above appears to be what you want to do.

Related

Executing select statement as variable from TVF

I have to get a list of results from a Table value function from a variable. I have done something like this:
DECLARE #Date char(8) = '20200508'
DECLARE #Type varchar(100) = 'Inbound'
DECLARE #Offset INT = 3600
DECLARE #EmployeeID INT = null
DECLARE #TypeFunc as varchar(max)
SET #TypeFunc= N'select EmpID, Callcount from dbo.fn_' + #Type + '('''+ #Date +''','+ CAST(#Offset as Varchar(100))+','+ CAST(#EmployeeID as varchar(100))+')';
EXEC (#TypeFunc)
I expect to see a list of results as if I'm doing a normal select query, however, it is just coming back with 'Commands completed successfully.' in the results grid, which doesn't seem like its doing it correctly.
The query it should run should look like
Select EmpID, Callcount From dbo.fn_Inbound('20200508', 3600, null)
Anything I'm missing here?
I found 2 mistakes in your Query:
1.) Use CONCAT instead of + because if any of your concatenating string is null it makes the whole Concatenation as NULL (For your case EmpID is null it will makes the Whole Query as null by using +)
2.)ISNULL(CAST(#EmployeeID as varchar(100)),'NULL') Use ISNULL fn to pass as null for that Parameter in your function
SET #TypeFunc= CONCAT(N'select EmpID, Callcount from dbo.fn_' , #Type , '(''', #Date
,''',', CAST(#Offset as Varchar(100)),',',ISNULL(CAST(#EmployeeID as
varchar(100)),'NULL'),')');

Assigning variables to use in query

I am moving from Oracle to SQL Server and I am noticing differences regarding assigning variables in a query. I wonder if someone could write me a simple example of how I can do this in SSMS please?
In the example below I am looking to assign the variable #date1 at the beginning of the select statement so that I can simply change the date at the top instead of having to change it several times in the query where #date1 is used several times.
SELECT *
FROM table
where date = #date1
Thanks
Based on your example the syntax would be as follows:
DECLARE #date1 DATETIME
SET #date1 = '2017-01-01 00:00:00.000'
Then reference #date1 in your query as you have above.
More broadly, the syntax is:
DECLARE #<name of variable> <type>
SET #<name of variable> = <value>
-- Simple declares
DECLARE #Variable1 VARCHAR(100)
DECLARE #Variable2 DATE
DECLARE #VariableTable TABLE (
numberColumnName INT,
textColumnName VARCHAR(MAX))
-- Chained declares
DECLARE
#Variable3 VARCHAR(100),
#Variable4 INT
-- Declare with initiation
DECLARE #Variable5 INT = 150
DECLARE #Variable6 DATE = '2018-05-05' -- Implicit conversion (varchar to date)
DECLARE #Variable7 FLOAT = 1945.15 * 1648.12 / #Variable5 -- Expressions can be used
DECLARE #Variable8 INT = (SELECT COUNT(1) FROM sys.objects)
-- Chained declares with initiation
DECLARE
#Variable9 VARCHAR(100) = 'Afla',
#Variable10 INT = 9164 * #Variable5
-- Change variable values (without declaring)
SET #Variable1 = 'Some value'
SET #Variable2 = CONVERT(DATE, GETDATE())
For your example:
DECLARE #DateFilter DATE = '2018-05-16' -- Use ISO standard date format (yyyy-MM-dd) when you hard-code them as literals
SELECT
*
FROM
YourTable AS T
WHERE
T.DateToFilter >= #DateFilter
DECLARE #date1 DATE = '2018-04-11'
This code may be fine, but be aware of dates formats :date (Transact-SQL)
and the need of using either Date, Datetime, or Datetime2.

How do I include optional parameters using IF-THEN-ELSE logic in a SQL query?

Here is the create statement for a stored procedure:
Create Procedure SearchCreatedAssignments
(#LessonName Varchar(50), #DateFrom date, #DateTo Date, #LocationCode Varchar(10))
As
BEGIN
Basically, I want to write a query that searches the database based on the values of the parameters. For example:
Select *
from dbo.test
where (LessonName = #LessonName)
AND (StartDate = #DateFrom)
AND (EndDate = #DateTo)
AND (LocationCode = #LocationCode)
Fairly simple, right? However, if any of these parameters are null (or contain an empty string), I would like to omit them from the search, and search by only the parameters that are not null. I was thinking something like this:
--if #LocationCode is null OR #LocationCode = '' -> omit #LocationCode from the search
This is obviously pseudo code. How can I do this? Forgive me if this is a simple task; I am new to SQL.
Consider the following. If a parameter is NULL or empty, the default value will be the field in question
Select *
from dbo.test
where LessonName = IsNull(NullIf(#LessonName,''),LessonName)
AND StartDate = IsNull(NullIf(#DateFrom,''),StartDate)
AND EndDate = IsNull(NullIf(#DateTo,''),EndDate)
AND LocationCode = IsNull(NullIf(#LocationCode,''),LocationCode)
You can either write a dynamic SQL statement and execute it using sp_ExecuteSQL in your procedure, or you can get tricky with the SQL like:
Select *
from dbo.test
where (LessonName = #LessonName)
AND (StartDate = #DateFrom)
AND (EndDate = #DateTo)
AND (LocationCode = #LocationCode or #LocationCode IS NULL or #LocationCode = '')
You can use the COALESCE function to do so in this way:
where LessonName = coalesce(#LessonName, LessonName)
AND StartDate = coalesce(#DateFrom, StartDate)
AND EndDate = coalesce(#DateTo, EndDate)
AND LocationCode = coaleasce(#LocationCode, LocationCode)
Although I'm not sure about the empty strings. It will work for null values, in other databases coalesce also handle the empty strings. If it do not work you can use case in the same manner:
LessonName = case when #LessonName is not null and #LessonName != ''
then #LessonName else LessonName end
And just use the same logic for the other parameters.
INHO on this case a good way is using a dynamic query.
DECLARE #cmd VARCHAR(MAX);
SET #CMD = 'SELECT * FROM dbo.Text WHERE #Param1 = 'x''; --at least on parameter
IF #PARAM2 IS NOT NULL
BEGIN
SET #CMD = #CMD + ' AND Param2 = #Param2'
END
IF #PARAM3 IS NOT NULL
BEGIN
SET #CMD = #CMD + ' AND Param3 = #Param3'
END
EXECUTE (#CMD);

How to extract date fields from string/text field in sql server 2005

There is a text filed in a table called as description. I would like to extract two date fields from this string when there is an occurrence of '~' character using sql server 2005 stored procedure. Help me out in this case.
Example: string: '长期租金;10/1/2012 ~ 10/31/2012'. At occurrence of ~ operator I would like to have from-date: 20121001 and to-date:20121031.
Here is a method which will give the start and end dates. I left most of the testing selects in place but commented out.
DECLARE #string AS NVARCHAR(255)
DECLARE #Seperator as char(1) = '~'
declare #CharStartDate as varchar(10)
declare #CharStopDate as varchar(10)
declare #StartDate as date
declare #StopDate as date
declare #I int
--SET #string = 'xvvvvvvcc;1/09/2012 ~ 1/10/2012xx'
--SET #string = 'xvvvvvvcc;12/31/2012 ~ 1/1/2012xx'
--SET #string = 'xvvvvvvcc;12/1/2012 ~ 10/0/2012xx'
SET #string = 'xvvvvvvcc;1/2/2012 ~ 1/3/2012xx'
--longest date 12/31/2011 = 10
--shortest date 1/1/2012 = 8
-- width of seperator = 3
SELECT
#CharStartDate = substring (#string, CHARINDEX(#Seperator,#string)-11,10)
,#CharStopDate = substring (#string, CHARINDEX(#Seperator,#string)+2,10)
--SELECT #CharStartDate,#CharStopDate
select #I = ascii(substring(#CharStartDate,1,1))
While #I > 57
BEGIN
set #CharStartDate = substring(#CharStartDate,2,10)
--select #CharStartDate
select #I = ascii(substring(#CharStartDate,1,1))
END
select #I = ascii(substring(REVERSE(#CharStopDate),1,1))
While #I > 57
BEGIN
set #CharStopDate = REVERSE(substring(REVERSE(#CharStopDate),2,10))
--select #CharStopDate
select #I = ascii(substring(REVERSE(#CharStopDate),1,1))
END
--select ascii(';'),ascii('9'),ascii('8'),ascii('7'),ascii('6'),ascii('6'),ascii('4'),ascii('3'),ascii('2'),ascii('1'),ascii('0')
SELECT #StartDate = #CharStartDate,#StopDate = #CharStopDate
--SELECT #I,#string,#Seperator,#CharStartDate,#CharStopDate,#StartDate,#StopDate
select datediff(dd,#StartDate,#StopDate) AS 'DateDiff',#StartDate as 'Start Date',#StopDate as 'Stop Date'
I will leave it to you to check for the seperator.
CREATE FUNCTION [dbo].[RemoveAlphaCharacters](#Temp nvarchar(max))
RETURNS nvarchar(max)
AS
BEGIN
WHILE PatIndex ('%[^0-9~/]%', #Temp) > 0
SET #Temp = Stuff(#Temp, PatIndex('%[^0-9~/]%', #Temp), 1, '')
RETURN #Temp
END
DECLARE #string nvarchar(max) = '长期租金;10/1/2012 ~ 10/31/2012'
SELECT CONVERT(date, SUBSTRING([dbo].[RemoveAlphaCharacters](#string), 0,
CHARINDEX('~', [dbo].[RemoveAlphaCharacters](#string))), 101) AS BDate,
CONVERT(date, SUBSTRING([dbo].[RemoveAlphaCharacters](#string),
CHARINDEX('~', [dbo].[RemoveAlphaCharacters](#string)) + 1,
CHARINDEX('~', REVERSE([dbo].[RemoveAlphaCharacters](#string)))), 101) AS EDate
In this instance you can use the following but really you need an exists clause or something like that to test the string for the tilde (~) and as everyone else has stated, this only works if the string always has a semicolon(;) and a tilde(~). You can convert to the strings into datetime fields if you need.
I have placed the string in a variable to make it easier to read...
DECLARE #string AS NVARCHAR(255)
SET #string = '长期租金;10/1/2012 ~ 10/31/2012'
SELECT StartDate = SUBSTRING(#string,CHARINDEX(';',#string)+1,LEN(#string)-CHARINDEX('~',#string)-1)
,EndDate = LTRIM(RIGHT(#string,LEN(#string)-CHARINDEX('~',#string)))
i have never used the older version of SQL cause i just graduated but doesnt it have the EXTRACT() function?.. The syntax goes like this below.
SELECT First_Name ,
EXTRACT ( CAST(Created_date AS DATE) FROM Created_date ) AS Date_only ;
You specify 'First_name' to let SQL know you want it as a column and 'created_date' is the field from which youre trying to separate the date. the cast function converts your field to DATE value before extractig it.
i hope this helps . thank you. if im wrong please let me know i would like to improve myself.

Try/Catch in UDF not possible? How to "TryCast" a varchar to datetime?

how can i convert a varchar parameter into datetime and if cast fails use GetDate() as default?
I've tried to put it in a Try/Catch but apparently that doesn't work in a UDF. It also does not work to simply check if the datetime is null, because it'll throw an exception('The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value'):
CREATE FUNCTION [dbo].[getRZUInfo]
(
#IMEI varchar(20),
#StrDeliveryDate varchar(20)
)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE #Info VARCHAR(8000)
DECLARE #DeliveryDate datetime;
SET #DeliveryDate = Convert(datetime,#StrDeliveryDate,102);
IF #DeliveryDate IS NULL
SET #DeliveryDate=GetDate();
SELECT #Info = COALESCE(#Info + '|', '') + 'TAT_B2B: ' + Convert(varchar,tabData.TAT_B2B) + ', AC' + Convert(varchar,tabData.fimaxActionCode) + ', Diff: ' + Convert(varchar,DateDiff(day,tabData.Received_date,#DeliveryDate))
FROM tabData
WHERE (SSN_Number = #IMEI) AND (Received_Date >= DATEADD(month, -3, #DeliveryDate))
ORDER BY SSN_Number,Received_Date DESC
return #Info
END
SET #DeliveryDate = CASE
WHEN Isdate(#StrDeliveryDate) = 1 THEN
CONVERT(DATETIME, #StrDeliveryDate, 102)
ELSE Getdate()
END
A common flaw with IsDate is that it is unable to take in a date format specifier that CAST/CONVERT can.
See this:
set dateformat dmy
declare #StrDeliveryDate varchar(20) set #StrDeliveryDate = '2011.12.13'
select CASE
WHEN Isdate(#StrDeliveryDate) = 1 THEN
CONVERT(DATETIME, #StrDeliveryDate, 102)
ELSE Getdate()
END
output: 2011-03-21 22:19:54.683
This is a better function for testing 102-formatted dates specifically. Actually 102 is much easier, this is flexible enough to pick up yy/yyyy, m/mm, d/dd.
create function dbo.Is102Date(#any varchar(50))
-- 102 = yyyy.mm.dd
returns bit as begin
set #any = ltrim(rtrim(#any))
declare #theyear varchar(10)
set #TheYear = case
when #any like '%[^0-9.]%' then null
when #any like '[0-9][0-9].%[0-9].%[0-9]' then
case when LEFT(#any,2) >=50
then '19'+LEFT(#any,2)
else '20'+LEFT(#any,2)
end
when #any like '[0-9][0-9][0-9][0-9].%[0-9].%[0-9]' then
LEFT(#any,4)
end
declare #YYYYMMDDToTest varchar(50)
set #YYYYMMDDToTest = case
when #TheYear is not null then
#TheYear
+ -- month
SUBSTRING(#any, charindex('.',#any) +1,
charindex('.',#any,charindex('.',#any)+1)-
charindex('.',#any)-1)
+ -- day
right(#any,charindex('.',reverse(#any))-1)
end
return ISDate(#YYYYMMDDToTest)
end
GO
Use it instead of ISDATE to test for 102-formatted dates in varchar.
Just checking when Null
IF #StrDeliveryDate IS NULL
SET #DeliveryDate = GetDate();
ELSE
SET #DeliveryDate = Convert(datetime, #StrDeliveryDate, 102);