Multiple argument IF statement - T-SQL - tsql

How do I write an IF statement with multiple arguments in T-SQL?
Current source error:
DECLARE #StartDate AS DATETIME
DECLARE #EndDate AS DATETIME
SET #StartDate = NULL
SET #EndDate = NULL
IF (#StartDate IS NOT NULL AND #EndDate IS NOT NULL)
BEGIN
-- do some work
END
It throws the following error:
Incorrect syntax near the keyword
'AND'. Incorrect syntax near the
keyword 'AND'. Incorrect syntax near
')'.

You are doing it right. The empty code block is what is causing your issue. It's not the condition structure :)
DECLARE #StartDate AS DATETIME
DECLARE #EndDate AS DATETIME
SET #StartDate = NULL
SET #EndDate = NULL
IF (#StartDate IS NOT NULL AND #EndDate IS NOT NULL)
BEGIN
print 'yoyoyo'
END
IF (#StartDate IS NULL AND #EndDate IS NULL AND 1=1 AND 2=2)
BEGIN
print 'Oh hey there'
END

Your code is valid (with one exception). It is required to have code between BEGIN and END.
Replace
--do some work
with
print ''
I think maybe you saw "END and not "AND"

That's the way to create complex boolean expressions: combine them with AND and OR. The snippet you posted doesn't throw any error for the IF.

Seems to work fine.
If you have an empty BEGIN ... END block you might see
Msg 102, Level 15, State 1, Line 10
Incorrect syntax near 'END'.

Not sure what the problem is, this seems to work just fine?
DECLARE #StartDate AS DATETIME
DECLARE #EndDate AS DATETIME
SET #StartDate = NULL
SET #EndDate = NULL
IF (#StartDate IS NOT NULL AND #EndDate IS NOT NULL)
BEGIN
Select 'This works just fine' as Msg
END
Else
BEGIN
Select 'No Lol' as Msg
END

Related

Creating function in PostgreSQL

I am trying to create the following procedure in Aginity workbench with DBMS PostgreSQL 8.0.2
CREATE PROCEDURE Step1_data_main
(
#startdate NVARCHAR(MAX),
#enddate NVARCHAR(MAX),
#season NVARCHAR(MAX)
) AS
SELECT level1_idnt,day_dt, sum(sls_qty) as sum_units,sum(sls_amnt_price) as sum_sales
FROM md1.loc_sku_dy_act_pos_full_v2
WHERE seasn_cd = '+#season+' and day_dt >= ''+#startdate+'' and day_dt <= ''+#enddate+''
GROUP_BY level1_idnt, day_dt;
END
EXEC Step1_data_main
'2015-03-01 00:00:00',
'2015-09-30 00:00:00',
'2'
GO
However I am getting the following error
syntax error at or near "PROCEDURE"
Any guidance on this will be greatly appreciated
EDIT
I am working in Aginity Workbench with PostgreSQL I had previously incorrectly said I am using mysql workbench.
This should work for you:
CREATE PROCEDURE `Step1_data_main`(
startdate NVARCHAR(1000),
enddate NVARCHAR(1000),
season NVARCHAR(1000)
)
begin
SELECT level1_idnt,day_dt, sum(sls_qty) as sum_units,sum(sls_amnt_price) as sum_sales
FROM md1.loc_sku_dy_act_pos_full_v2
WHERE seasn_cd = cast(season as UNSIGNED) and
day_dt >= cast(startdate as datetime) and
day_dt <= cast(enddate as datetime)
GROUP BY level1_idnt, day_dt;
END$$
You should try in this way, Yo are using sql server syntax in mysql thats why getting error.
This is for MySQL
DELIMITER $$
CREATE PROCEDURE Step1_data_main(
startdate NVARCHAR(20),
enddate NVARCHAR(20),
season NVARCHAR(20))
BEGIN
SELECT level1_idnt,day_dt, sum(sls_qty) as sum_units,sum(sls_amnt_price) as sum_sales
FROM md1.loc_sku_dy_act_pos_full_v2
WHERE seasn_cd = '+#season+' and day_dt >= ''+#startdate+''
and day_dt <= ''+#enddate+''
GROUP BY level1_idnt, day_dt;
END$$
Update1: This is for SQL Server
Create PROCEDURE Step1_data_main(
#startdate NVARCHAR(20),
#enddate NVARCHAR(20),
#season NVARCHAR(20)
)
AS
BEGIN
SELECT level1_idnt,day_dt, sum(sls_qty) as sum_units,sum(sls_amnt_price) as sum_sales
FROM md1.loc_sku_dy_act_pos_full_v2
WHERE seasn_cd = '+#season+' and day_dt >= ''+#startdate+''
and day_dt <= ''+#enddate+''
GROUP BY level1_idnt, day_dt;
END;

Date Comparison in If condition in DB2

I have two date parameters BeginDate and EndDate. I need to compare these two dates and then perform some sql select. For example, if BeginDate is lessthan or equal to EndDate, then only I need to query data. For example as below:
If #BeginDate <= #EndDate Then
select statement1
select statement2
...
End if
When I tried in DB2, I am getting an error.
Kindly suggest a sample with DB2 syntax.
In case you want to do it simple, just add the condition to both select statements:
SELECT *
FROM <table_name>
WHERE #BeginDate <= #EndDate;
Other solution would be using IF statement within PL/SQL contexts to execute SQL:
IF (#BeginDate <= #EndDate) THEN
statements
END IF;
A more complete example for inline SQL PL, would be something like:
CREATE PROCEDURE EXAMPLE_IF
(IN BeginDate DATE, IN EndDate DATE)
LANGUAGE SQL
BEGIN ATOMIC
IF (BeginDate <= EndDate)
THEN
statement1;
statement2;
END IF;
END!
Hope it's useful!

RAISERROR within Case statement

Can you not raise errors within a case statement in T-SQL? I always have problems with SQL case statements :/
begin try
declare #i int
--set #i = (select COUNT(1) from table_name)
select Item_Num =
CASE (select COUNT(1) from table_name)
when 1 then (select Item_Num from table_name)
when 0 then (raiserror('No records in database', 0, 0))
ELSE (raiserror('Multiple records in database', 0, 0))
END
from table_name
end try
begin catch
declare #errormsg nvarchar(1024),
#severity int,
#errorstate int;
select #errormsg = error_message(),
#severity = error_severity(),
#errorstate = error_state();
raiserror(#errormsg, #severity, #errorstate);
end catch
Think of Case/When as operating on a single piece of data. If you think of it this way, a lot of your problems will go away.
If/Then is used to control the flow of logic.
Something like this should work for you.
declare #i int
set #i = (select COUNT(1) from table_name)
If #i = 1
Begin
Print "1 row"
End
Else If #i = 0
Begin
Print "no rows"
End
Else
Begin
Print "too many rows"
End
You can raise an error from the case expression by converting an error string to int.
select case (select count(*) from mytable)
when 1 then 100
when 2 then 200
else convert(int, 'ERROR')
end
This gives an error message like
Conversion failed when converting the varchar value 'ERROR' to data type int.
which is about as good as you're going to get.
Not all failed conversions give the input string in the error message. Conversions to datetime, for example, do not. So if your case expression returns a datetime, you still have to trigger the error with a string-to-integer conversion:
select case (select count(*) from mytable)
when 1 then getdate()
else convert(datetime, convert(int, 'ERROR'))
end
It gets worse: if you are returning a date, you can't explicitly convert that from int, so you have to resort to
convert(date, convert(char(1), convert(int, 'ERROR')))
It's pretty horrible, but in my opinion the only thing more important than clean code is informative error messages, so I live with it.
As I said in the comment, I think it would be easier to simply create a flag that you check outside the scope of the CASE statement. Something along the lines of:
--- code before the TRY...
BEGIN TRY
DECLARE #i int
-- declare a variable to act as a flag
DECLARE #my_flag as int
-- than change your statement to simply fill the value of the flag
CASE (SELECT COUNT(1) FROM table_name)
WHEN 1 THEN SET #my_flag = 1
WHEN 0 THEN SET #my_flag = 0
ELSE SET #my_flag = -1
END
IF (NOT #my_flag in (-1, 0))
BEGIN
SET #Item_Num = (SELECT Item_Num FROM table_name) -- consider a filter here
END
ELSE
BEGIN
IF (-1 = #my_flag) RAISERROR('too many records', 0, 0)
IF (0 = #my_flag) RAISERROR('no records', 0, 0)
END
END TRY
BEGIN CATCH
--- rest of the code goes here....
With #TempTable as
(
Select * from ...
-- record set that determines if I should error out
)
SELECT CASE WHEN COUNT(1) > 0
THEN 'Multiple records in database'
ELSE 0
END AS [Value]
FROM #TempTable
datatype mismatch will kill the method if you're trying to error out this whole call with TSQL. Worked in my case because it was a heavy process that I needed to know was transferred correctly. If My record set was >1 then I know I should fail this. Useful if you're using SSIS or multiple methods within a .NET environment

Oracle:Check datatype of a variable

How can I check if the variable is a varchar/date/numeric datatype in oracle 10g procedure?
Like guess I have a variable in a procedure,that will be filled with various data(may be number,string or date).How to find this variable`s datatype in Oracle???
Declare
returnValue varchar2;
Begin
Text:=select col_name from tab_name where ID=:ID1;
EXECUTE IMMEDIATE Text into returnValue;
End;
Here 'ID1' will be sent dynamically."col_name" can have any data.
I have to check what kinda value is there in "returnValue" variable.?
Please suggest some answers.
you can do something like this, bit its not particularly nice:
declare
v_date DATE;
v_number NUMBER
begin
select to_date(variable_name,<date_format>) into v_date from dual;
exception when others then
//its not a date
begin
select to_date(variable_name,<date_format>) into v_number from dual;
exception when others then
//its not a number
...
...
end;
end;
Ideally, you shouldn't be putting multiple types of data into a single VARCHAR2 column - then you wouldn't have this problem in the first place..
You should declare the column_name by
returnvalue tablename.columnname%TYPE;
So by this way the datatype of column will have the value stored in returnvalue variable
Update 1
returnValue tab_name.col_name%TYPE;
begin
select col_name into returnValue from tab_name where ID=:ID1;
return returnValue;
end;
Update 2
You could the following to get the data types from the following
select data_type || '(' || data_length || ')' col from user_tab_columns where
TABLE_NAME = '<YOURTABLE>'

Cannot use function calls as parameters to RAISERROR()

I am using a try-catch block in T-SQL, and I want to only catch a specific error number. In other cases, I am using RAISERROR() as a poor-man's re-throw to return error information to the application.
When I try the following, I get an "Incorrect syntax near 'error_message'" error:
raiserror
(
error_message()
,1
,1
)
The following, however, works fine:
declare #err varchar(100)
set #err = error_message()
raiserror
(
#err
,1
,1
)
I thought it might be a typecasting quirk, so I tried this, but that also yielded a syntax error:
raiserror
(
cast(error_message() as varchar(100))
,1
,1
)
What's going on here? Why do I have to store the result of ERROR_MESSAGE() in a variable before using it as a parameter to RAISERROR(), instead of calling the function directly?
Below post answers your Question: https://stackoverflow.com/a/3415125/639960
In a nutshell (quoted from above post):
RAISERROR follows the same rules as any other stored procedure call.
Parameters passed in must be a constant or a variable. You cannot pass
a function directly as a parameter.
See Executing Stored Procedures for documentation on this.
Try switching error type by uncommenting set #Fail= GETDATE() and see its not very realiable
set nocount on
begin
declare #ErrorMessage varchar(100)
declare #ErrorState varchar(100)
declare #ErrorSeverity varchar(100)
declare #ErrorNumber varchar(100)
declare #Fail int
begin try
--set #Fail= GETDATE()
set #Fail = 1/0
end try
begin catch
print 'Why can''t it catch all type of errors like implicit conversion'
SELECT #ErrorMessage = ERROR_MESSAGE(), #ErrorSeverity = ERROR_SEVERITY(), #ErrorState = ERROR_STATE();
RAISERROR (#ErrorMessage -- Message text.
,#ErrorState -- State.
,#ErrorSeverity -- Severity.
);
end catch
end