IF statement not raising error as expected - sql-server

Assume #Ref <> 0 in first condition. Therefore my code will not reach the declaration of #XYZ (line 2).
I think it must raise an error in the second IF because of #XZY was not declared.
But I'm surprised that there is no error raised.
IF #Ref = 0
BEGIN
DECLARE #XYZ int
SELECT #XYZ = RISKGROUP
FROM POLCONT WITH (NOLOCK, NOWAIT)
WHERE CONT = 555
END
IF #RISKGROUP <> #XYZ
BEGIN
-- do something ...
END
For example.
In python it raises this error:
Error: local variable 'XYZ' referenced before assignment

You need to declare your variable with a type before you can use it
declare #xyz int -- assuming the datatype of column riskgroup is also int
select #xyz = riskgroup
from polcont
where polcont = 555
EDIT
You altered your question since I have posted my answer, now your problem is you declare the variable in the wrong scope.
DECLARE #XYZ int
if #Ref = 0
begin
SELECT #XYZ = RISKGROUP
FROM POLCONT --WITH (NOLOCK, NOWAIT) don't do nolock everywhere !
WHERE CONT = 555
end
if #RISKGROUP <> #XYZ
begin
-- do something ...
end
EDIT 2
As to your question why it does not give any error, that is strange indeed
See this DBFiddle
I would indeed expect an error, but it somehow does not
This is explained in the documents as normal per design, though in my mind it is a flaw.
Also see this Question about the same subject
EDIT 3
So it seems that is does not matter much in TSQL where you declare your variables, but as a programmer I find this looking weird, so I prefer to put my variables in what is for me the correct scope.

Related

Check if there are any records in a table which may not exist

I have to check if some records with specific conditions exist in a table which may not exist and I must do this in a scalar function.
Here is my code:
CREATE FUNCTION CheckIfRecordsExistInTestTable()
RETURNS INT
BEGIN
DECLARE #Result INT
SELECT #Result =
CASE WHEN OBJECT_ID('TestTable') IS NULL THEN 0
ELSE
CASE WHEN EXISTS(SELECT * FROM TestTable) THEN
1
ELSE
0
END
END
RETURN #Result
END
While trying it in SQL Server executing the following statement:
SELECT dbo.CheckIfRecordsExistInTestTable()
Whenever TestTable exists it returns my expected result. But whenever it does not, SQL Server raises an exception (Invalid object name 'TestTable') and I cannot get what I expect (I want a zero return value in this situation).
So what do you propose to do for this problem which can be coded to a scalar function?
The other answer gives a correct workaround.
As to why you are getting the problem...
This is a compile time error.
If the statement references a non existent object compilation is deferred until just before execution, but still eventually the whole statement needs to be compiled into an execution plan before it is executed.
This fails when the table doesn't exist and execution of that statement doesn't even begin.
(Execution plan that it tries to create - using a passthru predicate to avoid evaluation of the condition if the CASE not met)
In the workaround the SELECT against testtable is moved into a different statement. Compilation of this statement is still deferred and as the statement is never executed all works fine.
Try changing the function like this
CREATE FUNCTION Checkifrecordsexistintesttable()
returns INT
BEGIN
DECLARE #Result INT
IF Object_id('TestTable') IS NULL
SET #Result = 0
ELSE
SELECT #Result = CASE
WHEN EXISTS(SELECT 1 FROM testtable) THEN 1
ELSE 0
END
RETURN #Result
END;
To know more about the reason behind the error you are getting check Martin's answer.
update function like this:
CREATE FUNCTION CheckIfRecordsExistInTestTable()
RETURNS INT
BEGIN
DECLARE #Result INT
SELECT #Result = case when count(1) = 0 then 0 else 1 end from sys.tables where name = 'TestTable'
RETURN #result
END

SQL Server : Select Local Variable After Some Process

CREATE PROCEDURE dbo.test2
AS
BEGIN
DECLARE #status as int
DECLARE #error as int
SET #status = 1
SET #Error = ##ERROR
UPDATE dbo.BView
SET bview='dar'
WHERE pt='foo'
IF #Error > 0
print 'ERROR'
else
SELECT #status as 'status'
END;
Why does this query always return the default value of the local variable #status regardless of what was assigned to it?
status
------
0
Server version: MS SQL Server 2014 Express
In sql server 2005 : Run this in your sql server.
You cannot assign a default value at declaration.
and post the result in command.
DECLARE #status int
SET #status = 1
SELECT #status as 'status'
Suggestions. Although can't find some thing amiss, why not do it the normal way.
Always Declare a variable first before your update,insert or any action.
CREATE PROCEDURE dbo.sp_test2
AS
BEGIN
DECLARE #status as int
SET #status = 1
UPDATE dbo.BView
SET bview='dar'
WHERE pt='foo'
SELECT #status as 'status'
END
Second Always use the keyword AS then variable type , the followed by the size. If you dont follow by the variable size, it mostly return 0, note nvarchar types/varchar types mostly. Example
DECLARE #status as nvarchar
Often return 0 when use against a string of length 20 . Where as ,
Declare #status as nvacrhar(20)
Works fine.
There might exist an error in your update/Insert etc processes and i can see u put the declaration and the select process in the same node(i.e begin and end). You can check for an error like.
CREATE PROCEDURE dbo.sp_test2
AS
BEGIN
DECLARE #status as int
DECLARE #error as int
SET #status = 1
SET #Error = ##ERROR
--Some statement, update or insert, let's say:
UPDATE dbo.BView
SET bview='dar'
WHERE pt='foo'
IF #Error > 0
print 'ERROR'
else
SELECT #status as 'status'
END
These are suggestions though, I often do this way and it never fails me. FOr better understanding of variable in SQL Here and . Raising Errors in MSSql here and many more. Hope it helps.

Incorrect syntax near 'BEGIN'. in TSQL

hello programmers i'm writing a TSQL in-line table function, actually im not good enough in sql, when i finished my code i've got this error "Incorrect syntax near 'BEGIN'." , anyone know the solution please give it to me.
by the way when i clicked double-click over the error msg it's selected the last "end"
create FUNCTION [dbo].[CheckLogin]
(
#un varchar(max),
#pw varchar(max)
)
RETURNS TABLE
AS
begin
declare #unexist int, #unpwmatch int, #uid bigint
declare #uisactivated bit , #uisdeleted bit
-----
set #unexist = (select COUNT(UserAccessInfo.UserId) FROM UsersAccessInfo
WHERE UserAccessInfo.UserName = #un OR UserAccessInfo.UserEmail = #un)
------
set #unpwmatch = (select count(usersaccessinfo.userid) from usersaccesinfo
WHERE (usersaccessinfo.UserName = #un) AND (usersaccessinfo.UserPassword = #pw) OR
(usersaccessinfo.UserEmail = #un) AND (usersaccessinfo.UserPassword = #pw))
------
set #uid =(select usersaccessinfo.userid from usersaccessinfo where
serAccessInfo.UserName = #un OR UserAccessInfo.UserEmail = #un)
------
if #uid <> Null
begin
set #uisactivated =(select usersaccessinfo.userisactivated from usersaccessinfo
where usersaccessinfo.userid=#uid)
end
------
if #uid <> null
begin
set #uisactivated =(select usersaccessinfo.userisactivated from usersaccessinfo
where usersaccessinfo.userid=#uid)
end
------
if #unexist = 0
begin
select dbo.getreportbyid('1004')
end;
else if #unpwmatch = 0
begin
select dbo.getreportbyid('1005')
end;
else if #uid<>0
begin
if #uisactivated =0
begin
select dbo.getreportbyid('1002')
end;
else if #uisdeleted = 1
begin
select dbo.getreportbyid('1003')
end;
end;
else
begin
select ('successful') as report
end;
return
end;
The problem is these lines:
...
RETURNS TABLE
AS
...
This is not valid syntax for any of the four types of user-defined functions.
Assuming that you are trying to define a multi-statement table-valued function, it should look like this:
...
RETURNS #YourTableName TABLE( <column-definitions>... )
AS
...
And then your function statements should be putting the function return data into that table before it executes the RETURN statement, which it also is not doing.
Your problem is that you are mixing the syntax of multi-statement table valued functions and inline table valued functions. For examples of each and some performance considerations check out my post here: http://sqlity.net/en/498/t-sql-tuesday-24-prox-n-funx/
In short, if you want to use multiple statements within a table valued function you have to declare a table variable after the RETURNS keyword and insert the rows you want to return in there in the function body. However, this type of function has serious performance implications and you should try hard to stay away from it.
Besides of that, you seem to have mismatching BEGINs and ENDs. As Barry said, "A little indentation would go a long way here" in helping you and others understand you code better.
You cannot have ; before the if command end. Also null checing is wrong. For ex;
if #uid <> null -- (1) note: should be if #uid is not null
Begin
-- query
End; --(2)-Note: this is wrong
Else
Begin
--Query
End

Problems with SQL EXISTS

I'm going mad on this one. I have the following SP:
ALTER PROCEDURE [BankImport].[spBI_getIsBatchUnique]
#batchName varchar = 500
AS
BEGIN
SET NOCOUNT ON;
IF (EXISTS (SELECT 1 FROM [ACN_Main].[BankImport].[tblBI_Jobs]
WHERE [batchNumber] = #batchName))
BEGIN
SELECT 1
END
ELSE
BEGIN
SELECT 0
END
END
GO
But whatever the request is, I always get back 0!
I tried to modify it in several ways but with no success!
What I need to do is check if there is a record with that batch number and return true, otherwise return false.
Any tip?
Thanks
Your input parameter looks a bit funny
#batchName varchar = 500
Should it have been this?
#batchName varchar(500)
Ie set the length of the varchar datatype, how you currently have it, 500 is the default value for the batchName param.
I think because you compare batchNumber and batchName, try
EXISTS (SELECT 1 FROM [ACN_Main].[BankImport].[tblBI_Jobs]
WHERE [batchName] = #batchName)

Empty statement in T-SQL

Is there an empty statement keyword in T-SQL in Sql Server 2005 or newer? Something like NULL statement in PL/SQL.
You can declare a label to do nothing.
DECLARE #value INT
IF #value IS NULL
BEGIN
no_op1:
END
ugly happens sometimes. I believe their is a valid use. In a lengthy/complicated decision branching structure with several if else statements, some of those statements may contain conditions in which you specifically desire no action. You also don't want those condition falling thru do the default else, where certain work is done. In that case, it's a valid use.
Here are two ways to do this - see B and C
Declare #status as char(1)
set #status = 'D'
If (#status = 'A')
select 'Great!'
Else if (#status = 'B')
begin
if null=null select null -- predicate never resolves true
end
Else if (#status = 'C')
set #status = #status -- set a variable to itself
Else
select 'Needs work!'
Note, this is an over-simplified example. It is best used for readability when conditions are complex.
I also believe there are sometimes legitimate uses for a nothing script (automatically generated scripts for example).
Although it's an old thread, I'll put in my two cents. I think declaring a variable is one of the most benign statements you can use. The statement doesn't even show up in execution plans:
IF (#variable = 0)
BEGIN
DECLARE #placeHolder BIT;
END
No. There is not a "No operation" equivalent.
For a stored proc, you'd have at least SET NOCOUNT ON.
For an IF/ELSE, if a condition is empty omit it
while 1 = 0 break
In function I can not use:
if 1 = 0 print ''
if 1 = 0 set nocount on
if 1 = 0 waitfor delay '00:00'
if 1 = 0 throw 50000, '', 10
if 1 = 0 select 1
if 1 = 0 return
Labels or variables cannot be declared twice.

Resources