Single Line IF in T-SQL - tsql

In C# we can write single if syntax:
string test;
int value=1;
test = value>=1 ? "is bigger or equal one" : "is less than one";
T-SQL in SQL Server 2008 R2 has single IF syntax?

SQL Server 2008 doesn't, you'd have to use a CASE statement...
SQL Server 2012 does have the function:
SELECT IIF ( #FirstArgument > #SecondArgument , 'TRUE', 'FALSE' )
AS [Output Using IIF Logical Function]

DECLARE #test VARCHAR(50);
DECLARE #value INT = 1;
SET #test = CASE WHEN #value >= 1 THEN 'is bigger or equal one' ELSE 'is less than one' END

Related

How to use IIf function inside IN Clause?

I have a stored procedure as under
ALTER PROCEDURE [dbo].[usp_testProc]
(#Product NVARCHAR(200) = '',
#BOMBucket NVARCHAR(100) = '')
--exec usp_testProc '','1'
AS
BEGIN
SELECT *
FROM Mytbl x
WHERE 1 = 1
AND (#Product IS NULL OR #Product = '' OR x.PRODUCT = #Product)
AND (#BOMBucket IS NULL OR #BOMBucket = '' OR CAST(x.BOMBucket AS NVARCHAR(100)) IN (IIF(#BOMBucket != '12+', #BOMBucket, '13,14')))
END
Everything else if working fine except when I am passing the bucket value as 12+ . It should ideally show the result for bucket 13 and 14. But the result set is blank.
I know IN expects values as ('13','14'). But somehow not able to fit it in the program.
You can express that logic in a Boolean expression.
...
(#BOMBucket <> '12+'
AND cast(x.BOMBucket AS nvarchar(100)) = #BOMBucket
OR #BOMBucket = '12+'
AND cast(x.BOMBucket AS nvarchar(100)) IN ('13', '14'))
...
But casting the column prevents indexes from being used. You rather should cast the other operand. Like in:
x.BOMBucket = cast(#BOMBucket AS integer)
But then you had the problem, that the input must not be a string representing an inter but can be any string. this would cause an error when casting. In newer SQL Server versions you could circumvent that by using try_cast() but not in 2012 as far as I know. Maybe you should rethink your approach overall and pass a table variable with the wanted BOMBucket as integers instead.

SQL Server 2008 r2: TSQL IIF Query not recognized

I'm trying to use IIF for the first time instead of a CASE and SQL Server is throwing this error:
Msg 102, Level 15, State 1, Line 9
Incorrect syntax near '>'.
My code:
DECLARE #lDate date = CONVERT(date,GETDATE());
DECLARE #lMonth int = MONTH(#lDate);
DECLARE #lDay int = DAY(#lDate);
DECLARE #lPeriodStart date, #lPeriodEnd date, #lPayPeriod int, #lCutOffDay int = 14;
--there are 24 pay periods find which one
SET #lPayPeriod = #lMonth * 2 - IIF(#lDay > #lCutOffDay, 0, 1);
SELECT #lPayPeriod
I don't understand how this is different from the guidelines from MSDN.
IIF was introduced in SQL Server 2012. As you've tagged your question with SQL Server 2008 I'd say that is the source of the problem.
Your syntax is valid and the code would work in a newer version.

Declaring an INT to VARCHAR for a Parameter in SQL Server 2008 for Crystal Reports

I have a field invoices.return which is an integer 0 or 1. I need to set it to a parameter (this will go into crystal reports once done) so I have it like this:
SET #InvoiceType = '%{InvoiceType}%';
Select statement is:
, CASE WHEN CONVERT(VARCHAR(10),invoices.revenue) = '1'
OR CONVERT(VARCHAR(10),invoices.revenue) = 'BILLED' THEN 'BILLED'
WHEN CONVERT(VARCHAR(10),invoices.revenue) = '0' OR
CONVERT(VARCHAR(10),invoices.revenue) = 'PENDING' THEN 'PENDING'
End AS 'InvoiceType'

How to extract letters from a string using Firebird SQL

I want to implement a stored procedure that extract letters from a varchar in firebird.
Example :
v_accountno' is of type varchar(50) and has the following values
accountno 1 - 000023208821
accountno 2 - 390026826850868140H
accountno 3 - 0700765001003267KAH
I want to extract the letters from v_accountno and output it in o_letter.
In my example: o_letter will store H for accountno 2 and KAH for accountno 3.
I tried the following stored procedure, which obviously won't work for accountno 3. (Please help).
CREATE OR ALTER PROCEDURE SP_EXTRACT_LETTER
returns (
o_letter varchar(50))
as
declare variable v_accountno varchar(50);
begin
v_accountno = '390026826850868140H';
if (not (:v_accountno similar to '[[:DIGIT:]]*')) then
begin
-- My SP won't work in for accountno 3 '0700765001003267KAH'
v_accountno = longsubstr(v_accountno, strlen(v_accountno), strlen(v_accountno));
o_letter = v_accountno;
end
suspend;
end
One solution would be to replace every digits with empty string like:
o_letter = REPLACE(v_accountno, '0', '')
o_letter = REPLACE(o_letter, '1', '')
o_letter = REPLACE(o_letter, '2', '')
...
Since Firebird 3, you can use substring for this, using its regex facility (using the similar clause):
substring(v_accountno similar '[[:digit:]]*#"[[:alpha:]]*#"' escape '#')
See also this dbfiddle.

How do I use T-SQL's Case/When?

I have a huge query which uses case/when often. Now I have this SQL here, which does not work.
(select case when xyz.something = 1
then
'SOMETEXT'
else
(select case when xyz.somethingelse = 1)
then
'SOMEOTHERTEXT'
end)
(select case when xyz.somethingelseagain = 2)
then
'SOMEOTHERTEXTGOESHERE'
end)
end) [ColumnName],
Whats causing trouble is xyz.somethingelseagain = 2, it says it could not bind that expression. xyz is some alias for a table which is joined further down in the query. Whats wrong here? Removing one of the 2 case/whens corrects that, but I need both of them, probably even more cases.
SELECT
CASE
WHEN xyz.something = 1 THEN 'SOMETEXT'
WHEN xyz.somethingelse = 1 THEN 'SOMEOTHERTEXT'
WHEN xyz.somethingelseagain = 2 THEN 'SOMEOTHERTEXTGOESHERE'
ELSE 'SOMETHING UNKNOWN'
END AS ColumnName;
As soon as a WHEN statement is true the break is implicit.
You will have to concider which WHEN Expression is the most likely to happen. If you put that WHEN at the end of a long list of WHEN statements, your sql is likely to be slower. So put it up front as the first.
More information here: break in case statement in T-SQL
declare #n int = 7,
#m int = 3;
select
case
when #n = 1 then
'SOMETEXT'
else
case
when #m = 1 then
'SOMEOTHERTEXT'
when #m = 2 then
'SOMEOTHERTEXTGOESHERE'
end
end as col1
-- n=1 => returns SOMETEXT regardless of #m
-- n=2 and m=1 => returns SOMEOTHERTEXT
-- n=2 and m=2 => returns SOMEOTHERTEXTGOESHERE
-- n=2 and m>2 => returns null (no else defined for inner case)
If logical test is against a single column then you could use something like
USE AdventureWorks2012;
GO
SELECT ProductNumber, Category =
CASE ProductLine
WHEN 'R' THEN 'Road'
WHEN 'M' THEN 'Mountain'
WHEN 'T' THEN 'Touring'
WHEN 'S' THEN 'Other sale items'
ELSE 'Not for sale'
END,
Name
FROM Production.Product
ORDER BY ProductNumber;
GO
More information - https://learn.microsoft.com/en-us/sql/t-sql/language-elements/case-transact-sql?view=sql-server-2017