Why is SQL output parameter always null - sql

I have the following SP
CREATE PROCEDURE [dbo].[GetBaseSixtyTwoString]
#a_number_to_convert int,
#v_temp_val nvarchar(256) output
AS
DECLARE #v_modulo INTEGER;
DECLARE #v_temp_int decimal(38) = #a_number_to_convert;
DECLARE #v_temp_char VARCHAR(1);
DECLARE #c_base62_digits VARCHAR(62) = '0123456789aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ';
IF ( #a_number_to_convert = 0 )
BEGIN
SET #v_temp_val = '5';
END
WHILE ( #v_temp_int <> 0 )
BEGIN
SET #v_modulo = #v_temp_int % 62;
SET #v_temp_char = substring( #c_base62_digits, #v_modulo + 1, 1 );
SET #v_temp_val = #v_temp_char + #v_temp_val;
SET #v_temp_int = floor(#v_temp_int / 62);
END
I am calling it like this:
declare #shorturl nvarchar(256)
exec dbo.GetBaseSixtyTwoString 1, #shorturl output
But the variable #shorturl always returns null
However if I put print statements in the SP I can see that #v_temp_val is indeed getting the correct value.
What am I missing?

You need to initialise #v_temp_val inside the stored procedure to non-NULL value, to ''.
If #v_temp_val is NULL, then this line would still result in NULL:
SET #v_temp_val = #v_temp_char + #v_temp_val;
because "value" + NULL = NULL

check if any value you put into variable #v_temp_val is null. note that any non-null value + NULL will result to NULL:
SET #v_temp_val = ISNULL(#v_temp_char, '') + ISNULL(#v_temp_val, '');

Related

What's the limit of a variable in T-SQL? Why does my variable prints out as NULL?

I'm creating a stored procedure with the following code:
CREATE OR ALTER PROCEDURE Insert_Into_Table
#Origin VARCHAR(255),
#Destination VARCHAR(255),
#Origin_Columns VARCHAR (4000),
#Destination_Columns VARCHAR (4000),
#Delete_Date_Column_Name VARCHAR(63), --Nullable
#Delete_Period_Months INT -- Nullable
AS
BEGIN TRY
DECLARE #insert_query VARCHAR(4000) = NULL;
DECLARE #delete_query VARCHAR(4000) = NULL;
DECLARE #check_query VARCHAR (4000) = NULL;
DECLARE #Date_To_Delete DATETIME = CAST(DATEADD(MONTH, -#Delete_Period_Months, GETDATE()) AS DATETIME);
-- Table names cannot be referenced directly in SPs, so we bypass
-- this issue by declaring a variable containing the query
IF #Delete_Date_Column_Name IS NOT NULL
OR #Delete_Period_Months IS NOT NULL
SET #delete_query = 'DELETE FROM ' + #Destination + ' WHERE ' +
#Delete_Date_Column_Name + ' >= ' + CONCAT(CHAR(39),CAST(#Date_To_Delete AS VARCHAR(255)),CHAR(39));
ELSE
PRINT N'Missing or no values provided for table deletion. Only executing copy';
CREATE TABLE #temptable (count INT)
SET #check_query = 'INSERT INTO #temptable SELECT TOP 1 1 AS count FROM ' + #Origin
EXECUTE(#check_query)
SET #insert_query = 'INSERT INTO' + QUOTENAME(#Destination) + QUOTENAME(#Destination_Columns, '()') +
'SELECT ' + #Origin_Columns + ' FROM ' + QUOTENAME(#Origin);
BEGIN TRY
IF EXISTS (SELECT TOP 1 * FROM #temptable)
BEGIN TRANSACTION
EXECUTE(#delete_query);
EXECUTE(#insert_query);
COMMIT
END TRY
BEGIN CATCH
ROLLBACK;
THROW 51000, 'The Origin table is empty', 1;
END CATCH
END TRY
BEGIN CATCH
THROW 51000, 'Error creating transaction', 1;
END CATCH
GO
When executing the stored proecedure with the parameters shown, it works correctly:
EXEC Insert_Into_Table
#Origin = 'Sink_Proc',
#Destination = 'Sink_Test',
#Origin_Columns = 'customer, order_number, created_date',
#Destination_Columns = 'customer, order_number, created_date',
#Delete_Date_Column_Name = NULL,
#Delete_Period_Months = NULL
However, when executing it with 25+ columns as Origin/Destination columns, when I print the #insert_query variable, it returns NULL and no operation is done. Why is this happening?

Can not write the value to a variable

I have a function, which needs to return true if there is a row in a table with values which user inputs.
I need to write the value to a variable which Ii return, but I got an error:
Incorrect syntax near '#ret'.
USE BDLab5;
GO
Create Function WasComplaint (#date date, #component varchar)
Returns BIT
Begin
Declare #was int, #ret bit
Select #was = ComponentCode from Complaints
Where ComplaintDate = #date AND
ComponentCode = (Select ComponentCode from Components Where ComponentName = #component)
if (#was = 0)
#ret = 0
else
#ret = 1
Return #ret
End;
I tried different variant of if else syntax but it doesn't help.
You need to use SET when assigning a value to a variable.
USE BDLab5;
GO
Create Function WasComplaint (#date date, #component varchar)
Returns BIT
Begin
Declare #was int, #ret bit
Select #was = ComponentCode from Complaints
Where ComplaintDate = #date AND
ComponentCode = (Select ComponentCode from Components Where ComponentName = #component)
if (#was = 0)
set #ret = 0
else
set #ret = 1
Return #ret
End;
Put the word SET before #ret when you give it a value

Uniqueidentifier as parameter in SQL Server Function

I have created a Function in SQL Server 2012 that I will use in a Check Constraint on a table.
The function works as expected if I do:
SELECT [dbo].[CheckValidCardnumberForShellTankingen] ('700678036658047691' ,'2925CA00-6DD5-4F9D-AB0E-AA15DBBD388B')
But when I try to set the expression in Check Constraint so:
([dbo].[CheckValidCardnumberForShellTankingen]([Volledig kaartnummer],[RollBackCode])=(1))
I get a Messaage: "Error validating constraint 'CK_MyConstraint'"
I use the Uniqueidentifier in a Where clause and the strange thing is if I replace the parameter with string containing the Uniqueidentifier I dont get this error.
Here is the Function:
-- =============================================
-- Author: Anders Pedersen
-- Create date: 2015-02-13
-- Description: Check of the Cardnumber of a transaction is valid.
-- =============================================
CREATE FUNCTION [dbo].[CheckValidCardnumberForShellTankingen]
(
-- Add the parameters for the function here
#Cardnumber NvarChar(50),
#RollBackCode NvarChar(200)
)
RETURNS BIT
AS
BEGIN
-- Declare the return variable here
DECLARE
#Result BIT
,#ResultLenght BIT
,#ResultPrefix BIT
,#CardLenght INT
,#SupplierID INT
,#UseCardnumber BIT
,#Prefix NvarChar(50)
-- Add the T-SQL statements to compute the return value here
SET #Result = 0
SET #ResultLenght = 0
SET #ResultPrefix = 0
SET #CardLenght = -1
SET #SupplierID = -1
SET #UseCardnumber = 0
SET #Prefix = ''
-- Get the UseCardnumber and the SupplierID
SELECT #UseCardnumber = C.UseCardNumber, #SupplierID = F.SupplierID
FROM Client C INNER JOIN
ClientFileUploads F ON C.ClientID = F.ClientID
WHERE F.RollBackCode = #RollBackCode
--WHERE F.RollBackCode = '2925CA00-6DD5-4F9D-AB0E-AA15DBBD388B'
-- Only carry out the check if the Client use Cards else set the check to True (1)
IF #UseCardnumber = 1
BEGIN
SELECT #CardLenght = [CardNumberLenght], #Prefix = ISNULL([Prefix],'') FROM [dbo].[Supplier] AS S WHERE S.SupplierID = #SupplierID
IF (#CardLenght IS NULL) OR (#CardLenght = 0)
BEGIN
SET #ResultLenght = 1
END
ELSE
BEGIN
IF (LEN(#Cardnumber) - #CardLenght)= 0
BEGIN
SET #ResultLenght = 1
END
ELSE
BEGIN
SET #ResultLenght = 0
END
END
IF SUBSTRING(#Cardnumber, 1, LEN(#Prefix)) = #Prefix
BEGIN
SET #ResultPrefix = 1
END
ELSE
BEGIN
SET #ResultPrefix = 0
END
IF ((#ResultLenght = 1) AND (#ResultPrefix = 1))
BEGIN
SET #Result = 1
END
ELSE
BEGIN
SET #Result = 0
END
END
ELSE
BEGIN
SET #Result = 1
END
-- Return the result of the function
RETURN #Result
END
GO
If #RollBackCode is a uniqueidentifier, I recommend making the parameter a uniqueidentifier and not a varchar.
As Rhys Jones points out, you shouldn't use a UDF in a check constraint.
See
https://dba.stackexchange.com/questions/22297/udf-in-check-constraint-downside
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/078b720f-faac-425c-b51a-33bcecb263d2/check-constraint-with-udf-problem-with-lots-of-data?forum=transactsql
http://sqlblog.com/blogs/tibor_karaszi/archive/2009/12/17/be-careful-with-constraints-calling-udfs.aspx
If you need to check in a trigger and roll back -- SQL Server - After Insert/ For Insert - Rollback

How to extract an ID number from a URL string in SQL?

I am trying to extract an ID from a URL and running into some issues. The URL's will look something like this:
http://www.website.com/news/view.aspx?id=95
http://www.website.com/news/view.aspx?id=20&ReturnURL=%2fnews%2fview.aspx%3fid%3d20
I am trying to return back the number following "?id=" and nothing after the number. I will then convert it to an INT in reference to another table. Any suggestions as how to do this properly?
Use charindex to find the position of ?id and stuff to remove the characters that is before ?id. Then you use left to return the characters to the next &
declare #T table
(
URL varchar(100)
);
insert into #T values
('http://www.website.com/news/view.aspx?id=95'),
('http://www.website.com/news/view.aspx?id=20&ReturnURL=%2fnews%2fview.aspx%3fid%3d20');
select left(T2.URL, charindex('&', T2.URL) - 1) as ID
from #T as T
cross apply (select stuff(T.URL, 1, charindex('?id', T.URL) + 3, '')+'&') as T2(URL);
Here is an option that you can use when you want to find the value of any parameter value within a URL, it also supports parsing text values that contain a URL
DECLARE #Param varchar(50) = 'event'
DECLARE #Data varchar(8000) = 'User Logged into https://my.website.org/default.aspx?id=3066&event=49de&event=true from ip'
DECLARE #ParamIndex int = (select PatIndex('%'+#param+'=%', #Data)+LEN(#param)+1)
-- #ParamValueSubstring chops off everthing before the first instance of the parameter value
DECLARE #ParamValueSubstring varchar(8000) = SubString(#Data, #ParamIndex, 8000)
SELECT #ParamValueSubstring as ParamSubstring
DECLARE #SpaceIndex int = (SELECT CHARINDEX(' ', #ParamValueSubstring))-1
DECLARE #AmpIndex int = (SELECT CHARINDEX('&', #ParamValueSubstring))-1
DECLARE #valueLength int = -1
-- find first instance of ' ' or & after parameter value
IF #SpaceIndex = -1
SET #valueLength = #AmpIndex
ELSE IF #AmpIndex = -1
SET #valueLength = #SpaceIndex
ELSE IF #SpaceIndex < #AmpIndex
SET #valueLength = #SpaceIndex
ELSE
SET #valueLength = #AmpIndex
IF(#valueLength = -1) -- check to see if there was no space or '&' following the parameter value
BEGIN
SET #valueLength = 8000
END
select Left(#ParamValueSubstring, #valueLength) as ParamValue
-- approach similar to idea function found here http://blogs.lessthandot.com/index.php/DataMgmt/DataDesign/extracting-numbers-with-sql-server/
I'm not totally clear on what you're asking. Are you asking how to get the value of id from the url when you are in the asp.net application? Then in the code behind you can
In c#
string id = Request.QueryString["id"]; // returns null if id not found
Reference
From this SO question Try this for integers:
int id;
if (!int.TryParse(Request.QueryString["id"], out id))
{
// error case
}
You could do it in an SQL function, like this:
declare #URL varchar(100)
--set #URL = 'http://www.website.com/news/view.aspx?id=95'
set #URL = 'http://www.website.com/news/view.aspx?id=20&ReturnURL=%2fnews%2fview.aspx%3fid%3d20'
Set #URL = CASE charindex('&',#URL)
WHEN 0 then #URL else substring(#url,1,charindex('&',#URL)-1) end
select #URL,SUBSTRING(#URL,CHARINDEX('?id=',#URL)+4,99)
Both examples are in there, comment either one to see result

How to set column names to a declared Variable?

I am trying to set a column name to a declared variable but i keep getting invalid column name message. what is the right syntax? Here is the query
Declare #APPSHELTER Table
(tid int Identity(1,1),App_Id Numeric,PrimaryName Varchar(300),--EmployerAdress Varchar(500), rent_amt varchar(20),house_payment_amt varchar(20),ins_amt varchar(20),utilities_amt varchar(20),Trash_Collection_amt varchar(20),Sewerage_amt varchar(20),Telephone_amt varchar(20),water_amt varchar(20),other_amt varchar(20), total varchar(20), property_taxes_amt varchar(20),insurance_amt varchar(20), other_house_amt varchar(20), gas_amt varchar(20), elec_amt varchar(20), otherfuel_amt varchar(20))
DECLARE #rent_amt_h NUMERIC
DECLARE #house_payment_amt_h NUMERIC
DECLARE #insurance_amt_h NUMERIC
DECLARE #property_taxes_amt_h NUMERIC
DECLARE #Other_house_amt_h NUMERIC
DECLARE #gas_amt_u NUMERIC
DECLARE #elec_amt_u NUMERIC
DECLARE #otherfuel_amt_u NUMERIC
DECLARE #Trash_Collection_amt_u NUMERIC
DECLARE #Sewerage_amt_u NUMERIC
DECLARE #Telephone_amt_u NUMERIC
DECLARE #water_amt_u NUMERIC
DECLARE #other_amt_u NUMERIC
DECLARE #total_u NUMERIC
insert into #APPSHELTER(App_Id,PrimaryName,rent_amt,house_payment_amt,ins_amt,utilities_amt,Trash_Collection_amt,Sewerage_amt,Telephone_amt,water_amt,other_amt,total, property_taxes_amt, insurance_amt, other_house_amt, gas_amt, elec_amt, otherfuel_amt )
select #app_id,
ISNULL((select top 1 replace(first_name,'''','''''') + ' ' + isnull(replace(middle_name,'''',''''''),'') + ' '+replace(last_name,'''','''''')
from app_member (nolock)
where app_id = #app_id and msn=1),'') AS PrimaryName,
isnull(rent_amt,'0' ) AS rent_amt,
isnull(house_payment_amt,'0') AS house_payment_amt,
isnull((insurance_amt+property_taxes_amt),'0') AS ins_amt,
--isnull(HC_Costs_amt,'0') AS utilities_amt,
isnull(gas_amt,'0') + isnull(elec_amt,'0') + isnull(otherfuel_amt,'0') as utilities_amt,
isnull(Trash_Collection_amt,'0') AS Trash_Collection_amt,
isnull(Sewerage_amt,'0') AS Sewerage_amt,
isnull(Telephone_amt,'0') AS Telephone_amt,
isnull(water_amt,'0') AS water_amt,
isnull(other_amt,'0') + isnull(other_house_amt,'0') AS other_amt,
isnull(total,'0') AS total,
isnull(property_taxes_amt,'0' ) AS property_taxes_amt,
isnull(insurance_amt,'0' ) AS insurance_amt,
isnull(other_house_amt,'0' ) AS other_house_amt,
isnull(gas_amt,'0' ) AS gas_amt,
isnull(elec_amt,'0' ) AS elec_amt,
isnull(otherfuel_amt,'0' ) AS otherfuel_amt
from Ext_App_Group_Other_Expenses APP_DEP (nolock)
WHERE APP_DEP.APP_ID=#APP_ID
SET #rent_amt_h = 'rent_amt'
SET #house_payment_amt_h = 'house_payment_amt'
SET #insurance_amt_h = 'insurance_amt'
SET #property_taxes_amt_h = 'property_taxes_amt'
SET #Other_house_amt_h = 'other_house_amt'
SET #gas_amt_u = 'gas_amt'
SET #elec_amt_u = 'elec_amt'
SET #otherfuel_amt_u = 'otherfuel_amt'
SET #Trash_Collection_amt_u = 'Trash_Collection_amt'
SET #Sewerage_amt_u = 'Sewerage_amt'
SET #Telephone_amt_u = 'Telephone_amt'
SET #water_amt_u = 'water_amt'
SET #other_amt_u = 'other_amt'
SET #total_u = 'total'
DECLARE #APPSHELTER_COUNT INT
if (rent_amt!=0 or house_payment_amt!=0 or insurance_amt != 0 or property_taxes_amt != 0 or gas_amt != 0 or elec_amt != 0 or otherfuel_amt != 0 or Trash_Collection_amt != 0 or Sewerage_amt != 0 or Telephone_amt != 0 or water_amt != 0 or other_house_amt != 0 or other_amt != 0 or total !=0)
begin
SET #APPSHELTER_COUNT = (select Count(APP_ID) FROM ext_app_group_other_expenses (nolock) WHERE APP_ID = #App_Id )
end
else
begin
SET #APPSHELTER_COUNT = 0
end
Actually, I am trying the check whether the values in these text boxes are null or not. If not I have to set the count!
2 things:
(1). I think this is erroneous - I don't see these variables declared anywhere....
if (rent_amt!=0 or house_payment_amt!=0 or insurance_amt != 0 or property_taxes_amt != 0 or gas_amt != 0 or elec_amt != 0 or otherfuel_amt != 0 or Trash_Collection_amt != 0 or Sewerage_amt != 0 or Telephone_amt != 0 or water_amt != 0 or other_house_amt != 0 or other_amt != 0 or total !=0)
(2). You defined a bunch of variables at the top #rent_amt_h, #house_payment_amt_h, etc as NUMERIC, but then at the bottom you are setting them to a string value. This will also throw an error - if you are trying to say that these are your column names, then this is not the way to do it - you aren't selecting it anywhere, either. Please clarify what you are hoping to achieve...
Please find below simplified code which seemed to meet your requirements. To test it change values from 0 to 1 in insert statement:
-- Dynamic SQL command string variable
DECLARE #cmdSQL VARCHAR(1000)
-- Column names
DECLARE #rent_amt_h VARCHAR(20) = 'App_Id'
DECLARE #house_payment_amt_h VARCHAR(20) = 'PrimaryName'
-- Count variable
DECLARE #APPSHELTER_COUNT INT
-- Make SQL command
SET #cmdSQL = '
Declare #APPSHELTER Table
(App_Id Numeric,PrimaryName Varchar(300))
insert into #APPSHELTER(App_Id,PrimaryName) values (0,0)
SELECT * FROM #APPSHELTER WHERE ' + #rent_amt_h + ' !=0 OR ' + #house_payment_amt_h + ' != 0'
-- Execute dynamic SQL
EXEC(#cmdsql)
IF ##ROWCOUNT != 0
SET #APPSHELTER_COUNT = 1
ELSE
SET #APPSHELTER_COUNT = 0
SELECT #APPSHELTER_COUNT