Select and Set not working together in TSQL FUNCTION - sql

I am using a function in SQL SERVER and setting a user variable using select and after that set . But seems set is not working .
--#id is input
Declare #result varchar(MAX)
SELECT #result = INFO FROM USER_INFO WHERE ID= +''+'DOMAIN\'+#id+''
IF #result IS NULL
SET #result = 'DOMAIN\'+#id+''
return (#result)
If user is not found I want to select id not the null values. Buts seems it coming null always
Set is not working in conditional statement.
What I am doing wrong?
Below is the update:
yes Slippery, I checked its coming null. If I set
SET #result ='MY ID'
it works but #result = 'DOMAIN\'+#id did not work
The whole function
FUNCTION [dbo].[USER_INFO]
(
-- Add the parameters for the function here
#id varchar(300)
)
RETURNS varchar(MAX)
AS
BEGIN
Declare #result varchar(MAX)
SELECT #result = INFO FROM USER_INFO WHERE ID= +''+'DOMAIN\'+#id+''
IF #result IS NULL
SET #result = 'DOMAIN\'+#id+''
return (#result)
END

Just in case that really is the entire function, you'll need that first line to be "CREATE FUNCTION" (or "ALTER FUNCTION" if it already exists), instead of just "FUNCTION"...
This will eliminate NULL's from being returned by your function:
DECLARE #result VARCHAR(MAX)
-- Eliminate NULL being passed in so string concatenation doesn't return NULL
IF #id IS NULL
SET #id = ''
-- Set the output value...if nothing exists, set it to 'x'
SET #result = (SELECT TOP 1 ISNULL(INFO,'x') FROM USER_INFO WHERE ID = 'DOMAIN\' + #id);
-- Now, neither #result OR #id will be NULL so the following should always return something other than NULL
IF #result = 'x'
SET #result = 'DOMAIN\' + #id
RETURN (#result)

Based on the other comments, try this:
Declare #result varchar(MAX)
SELECT #result = INFO FROM USER_INFO WHERE ID= 'DOMAIN\'+#id
IF #result IS NULL
SET #result = 'DOMAIN\'+ ISNULL(#id, '')
return (#result)
I don't think you need all that handing with the quotes and pluses

You should try like this. No need of those extra '' single quotes at end
Declare #result varchar(MAX)
SELECT #result = INFO FROM USER_INFO WHERE ID= 'DOMAIN\' + #id
IF #result IS NULL
SET #result = 'DOMAIN\' + #id
return (#result)
Few points to mention: your function name and the table name both are same user_info. Try naming them differently like
FUNCTION [dbo].[Get_USER_INFO]
(
-- Add the parameters for the function here
#id varchar(300)
)
SELECT #result = INFO FROM USER_INFO
Also, you should call your function like
select dbo.Get_USER_INFO('my-user_id')

The difference between select and set is that if set didn't found any value then it will return null but if select didn't found any value then it will show the previous value of the variable, the same case is happening for you when the #result value is null select don't assign any value and return the same previous value instead of assigning null and that is the reason the if statement is false and its not moving to the Set statement.
koppinjo, if the #result variable never set to anything then it should hit the block, but i guess the first time the #result variable value is not null so it's not hitting the block.
please view this for post more clarification.
http://www.mssqltips.com/sqlservertip/1888/when-to-use-set-vs-select-when-assigning-values-to-variables-in-sql-server/

Related

SQL Server select variable where no results

Can I set variables if the query returns no results?
DECLARE #Output AS VARCHAR(MAX);
SELECT #Output = 'Old';
SELECT #Output = 'New' WHERE 0 = 1;
PRINT #Output;
Output value is: Old
Expected value is: NULL
DECLARE #Output AS VARCHAR(MAX);
SELECT #Output = 'Old';
SELECT #Output = 'New' WHERE 0 = 1;
PRINT #Output;
You get 'Old' cause the variable already has this value, and it will not update the value since in the WHERE clause you use the condition 0=1, which will return FALSE and the value in the variable won't change.
WHERE 0 = 1 It will be False
WHERE 0 <> 1 It will be True
It's just similar to IF 0=1 THEN UpdateMyVar
So in your case the value will always 'Old', it won't return 'New' or NULL either.
I don't know what are you trying to do really, but if you want to return NULL then
DECLARE #Output AS VARCHAR(MAX);
SELECT #Output = 'Old';
SELECT #Output = NULL WHERE 0 <> 1; --If 0<> 1 then update my var and set NULL else leave it as it is
PRINT #Output;
Try this:
DECLARE #Output AS VARCHAR(MAX);
SELECT #Output = 'Old';
SELECT #Output = CASE 0 WHEN 1 THEN 'New' ELSE NULL END
SELECT #Output;
Sami provides a good explanation of what is going on.
If you want to be sure that a value is assigned, then you need to be sure that the query returns one row for the assignment. One way to do this is to use aggregations:
DECLARE #Output AS VARCHAR(MAX);
SELECT #Output = 'Old';
SELECT #Output = MAX('New') WHERE 0 = 1;
SELECT #Output;
This is simply how assigning variables in SELECT is implemented in SQL Server. As #SMor said in the comments, use SET instead of SELECT.
DECLARE #Output AS VARCHAR(MAX);
SET #Output = 'Old';
SET #Output = (SELECT 'New' WHERE 0 = 1);
-- this would change the #Output value to NULL
SELECT #Output;
The only problem with SET is that it can assign only one variable, while in SELECT you can assign many variables at the same time.

SQL Server function to get output zero or not

I am stuck to get output from function that takes an input parameter and should return zero or not:
alter function dbo.ZERONOT(#input int)
returns varchar(30)
as
begin
declare #result varchar(30)
declare #result1 varchar(30)
select #input = P_PRICE
from Product_ID
if (#input > 0)
set #result = 'YES'
return #result
else
set #result1 = 'NO'
return #result1
end
I think you want this:
ALTER FUNCTION dbo.ZERONOT(#Input INT) --The input value stored here
-- The variable used to pass the value to the function and make some
-- operations based on it, do not change his value.
RETURNS VARCHAR(3)
AS
BEGIN
DECLARE #Result VARCHAR(3);
IF EXISTS (SELECT 1 FROM Products WHERE Product_ID = #Input)
--Or maybe the price because I don't think you have a table named Product_ID
SET #Result = 'Yes'
ELSE
SET #Result = 'No';
RETURN #Result
END
Don't forget to visit the documentation

SQL use function returned string in select where in(..) query

I have a function that returns a string with id's connected by comma, something like that:
CREATE FUNCTION [dbo].[fGetChildIdByPId]
(
#ID INT
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #RET VARCHAR(1000)
SET #RET = ''
DECLARE CUR CURSOR LOCAL FORWARD_ONLY READ_ONLY FOR
SELECT ID FROM tControl WHERE parentID = #ID
OPEN CUR
FETCH FROM CUR INTO #ID
WHILE ##FETCH_STATUS = 0
BEGIN
SET #RET = #RET + CAST(#ID AS VARCHAR(10)) + ','
+ dbo.fGetChildIdByPId(#ID)
FETCH NEXT FROM CUR INTO #ID
END
CLOSE CUR
DEALLOCATE CUR
RETURN #RET
END
In another function I want to use the string returned from previous function in another select query like that:
CREATE FUNCTION ShouldOutput
(
#id int,
#gid int
)
returns int
as
begin
declare #out int
if exists(SELECT * FROM tControl
where id in (select [dbo].[fGetChildIdByPId](#id))
and summaryIndex=1 and goodId = #gid)
set #out = 1
else
set #out = 0
return #out
end
But of course, there is the problem because the value of select [dbo].fGetChildIdByPId can't be cast to integer and can't be used in a query. I thought of using EXEC or sp_executesql but I can't use them in a function, only in stored procedures but I need a function, because I need to use the returned 1 or 0 value in another sql query. What is the easiest way to make the mentioned query work?
You shouldn't.
Your second function should take a table valued parameter - where that parameter is a table of values that you wish to use in the function - rather than a concatenated string.
To that end, your first function should return a table of values, not a string.
While in an explicit IN function (where you define a set of results i.e. state IN (1, 2)) does use a comma separated list if you pass it a function that returns a comma separated list that wont work.
If you alter your first function to
CREATE FUNCTION [dbo].[fGetChildIdByPId]
(
#ID INT
)
RETURNS VARCHAR(MAX)
AS
BEGIN
SELECT ID, GoodId FROM tControl WHERE parentID = #ID
END
Then everything should work fine (not tested).

Put Where Clause in a parameter

I would like to use a where clause in a parameter. I already tried the following code but it doesnt work. the last line us red underlined, i reckon that i have to bind the parameter to the select command somehow. Would be great if anyone could help me with it.
Begin
declare #name varchar(MAX)
declare #x int
Set #x = 1
If #x = 1
BEGIN
SET #name = 'WHERE Username = Frank'
END
ELSE
BEGIN
SET #name = ''
END
END
now use it in:
SELECT * FROM dbo.person #name
Here is a typical way to have optional parameters in a query:
declare #UserName varchar(255) = 'Frank'
select *
from person p
where (#UserName is null or UserName = #UserName)
If you set the variable to NULL then all users are chosen. If you set it to a value, then only that user is chosen.
Looks like you want an optional Stored Procedure parameter to either pull rows with the parameter value or pull all rows:
CREATE PROCEDURE foo
#name AS VARCHAR(MAX) = NULL
AS
BEGIN
SELECT * FROM dbo.person WHERE Username = #name OR #name IS NULL
END
GO

T-SQL While Loop and concatenation

I have a SQL query that is supposed to pull out a record and concat each to a string, then output that string. The important part of the query is below.
DECLARE #counter int;
SET #counter = 1;
DECLARE #tempID varchar(50);
SET #tempID = '';
DECLARE #tempCat varchar(255);
SET #tempCat = '';
DECLARE #tempCatString varchar(5000);
SET #tempCatString = '';
WHILE #counter <= #tempCount
BEGIN
SET #tempID = (
SELECT [Val]
FROM #vals
WHERE [ID] = #counter);
SET #tempCat = (SELECT [Description] FROM [Categories] WHERE [ID] = #tempID);
print #tempCat;
SET #tempCatString = #tempCatString + '<br/>' + #tempCat;
SET #counter = #counter + 1;
END
When the script runs, #tempCatString outputs as null while #tempCat always outputs correctly. Is there some reason that concatenation won't work inside a While loop? That seems wrong, since incrementing #counter works perfectly. So is there something else I'm missing?
Looks like it should work but for somereason it seems to think #tempCatString is null which is why you are always getting a null value as nullconcatenated to anything else is still null. Suggest you try with COALESCE() on each of the variables to set them to " " if they are null.
this would be more efficient....
select #tempCatString = #tempCatString + Coalesce(Description,'') + '<br/>' from Categories...
select #fn
also look at concat_null_yields_null as an option to fix your concatenation issue, although I would avoid that route
I agree with keithwarren, but I would always be sure to add an ORDER BY clause to the query. You can then be sure as to exactly what order the values are being concatenated in.
Also, the COALESCE to replace the NULL value with '' will effectively yield blank rows. I don't know if you want them or not, but if not just filter in the WHERE clause instead...
Finally, you appear to have a temp table including the IDs you're interested in. This table can just be included in a JOIN to filter the source table...
DELCARE #output VARCHAR(8000)
SET #output = ''
SELECT
#output = #output + [Categories].Description + '<br/>'
FROM
Categories
INNER JOIN
#vals
ON #vals.val = [Categories].ID
WHERE
[Categories].Description IS NOT NULL
ORDER BY
[Categories].Description