How to output the results of a stored procedure with a while loop MS SQL Server? - sql

I'm performing some calculations on tsunami's wave time between different radii. I'm having trouble outputting the results of the stored procedure into a table. The output I get is a blank table without any data stored. The log says "0 rows affected". For some reason my inputs and outputs are not registering. I thinking it could have something to do with the way I'm using the loop inside to SP.
CREATE PROCEDURE SP_Tsunami
(
#oceanDepth int,
#radii1 int,
#radii2 int,
#tsunamiSpeed int OUTPUT,
#tsunamiTimeDifference int OUTPUT
)
AS
BEGIN
SET #tsunamiSpeed = sqrt(32.1725 * #oceanDepth) * (60.0/88.0);
Truncate Table dbo.Tsunami
DECLARE #i int
SET #i = 0;
WHILE (#i <= 10000)
BEGIN
INSERT INTO dbo.Tsunami (Radius, Wavetime)
VALUES
(#i, (#i / #tsunamiSpeed))
SET #i = #i + 100;
END
DECLARE #tsunamiTime1 int
DECLARE #tsunamiTime2 int
SET #tsunamiTime1 = (Select Wavetime From Tsunami WHERE Radius = #radii1);
SET #tsunamiTime2 = (Select Wavetime From Tsunami WHERE Radius = #radii2);
SET #tsunamiTimeDifference = (#tsunamiTime2 - #tsunamiTime1);
END
/* Outputs */
DECLARE #Out_tsunamiSpeed int
DECLARE #Out_tsunamiTimeDifference int
/* Inputs */
DECLARE #IN_oceanDepth int
DECLARE #IN_radii1 int
DECLARE #IN_radii2 int
SET #IN_oceanDepth = 15088;
SET #IN_radii1 = 2500;
SET #IN_radii2 = 7500;
Execute SP_Tsunami #oceanDepth = #IN_oceanDepth, #radii1 = #IN_radii1, #radii2 = #IN_radii2, #tsunamiSpeed = #Out_tsunamiSpeed OUTPUT, #tsunamiTimeDifference = #Out_tsunamiTimeDifference OUTPUT

Doesn't make much sense to insert the data into table and then read it from there. All the rows you are inserting into your table eventually only one row is being read from the table to assign values to variables.
Also change the procedure name prefix from sp_ to something else, sp_ is system stored procedure prefix.
I have changed the procedure definition a little bit hope it makes sense.
ALTER PROCEDURE SP_Tsunami
(
#oceanDepth int,
#radii1 int,
#radii2 int,
#tsunamiSpeed int OUTPUT,
#tsunamiTimeDifference int OUTPUT
)
AS
BEGIN
SET #tsunamiSpeed = sqrt(32.1725 * #oceanDepth) * (60.0/88.0);
DECLARE #tsunamiTime1 int
DECLARE #tsunamiTime2 int
SET #tsunamiTime1 = #radii1 / #tsunamiSpeed;
SET #tsunamiTime2 = #radii2 / #tsunamiSpeed;
SET #tsunamiTimeDifference = (#tsunamiTime2 - #tsunamiTime1);
END
GO
Execute the procedure with your provided data.
/* Outputs */
DECLARE #Out_tsunamiSpeed int
DECLARE #Out_tsunamiTimeDifference int
/* Inputs */
DECLARE #IN_oceanDepth int
DECLARE #IN_radii1 int
DECLARE #IN_radii2 int
SET #IN_oceanDepth = 15088;
SET #IN_radii1 = 2500;
SET #IN_radii2 = 7500;
Execute SP_Tsunami #oceanDepth = #IN_oceanDepth
, #radii1 = #IN_radii1
, #radii2 = #IN_radii2
, #tsunamiSpeed = #Out_tsunamiSpeed OUTPUT
, #tsunamiTimeDifference = #Out_tsunamiTimeDifference OUTPUT
SELECT #Out_tsunamiSpeed AS Out_tsunamiSpeed
,#Out_tsunamiTimeDifference AS Out_tsunamiTimeDifference
Result Set:
Out_tsunamiSpeed Out_tsunamiTimeDifference
475 10

Related

SQL function to calculate simple interest

I have worked on the solution, I need some intervention to optimize the solution.
Here is my current script:
create function SI (#Principal int, #roi int , #time int)
returns int
as
begin
declare #Principal_Amt int
--set #Principal_Amt = 10000
set #Principal_Amt = #Principal
declare #rate int
--set #rate=10
set #rate = #roi
declare #time_period int
--set #time_period = 5
set #time_period = #time
declare #Simple_Interest int
set #Simple_Interest = #Principal_Amt * #rate * #time_period / 100
return #Simple_Interest
end
select dbo.SI(10000, 8, 5)
It's only
create function SI(#Principal int = 0, #roi int = 0, #time int = 0)
returns int
as
begin
return (#Principal * #roi * #time /100)
end
You don't need to declare those variables, since you already have them, so use them directly.

How to compare two strings based on percent match in SQL

I want to post a solution to a interesting problem I was facing in T-SQL.
The problem:
Compare two string fields based on a percent match.
In addition, the two strings may have the words in them translocated.
For example: "Joni Bravo" and "Bravo Joni". These two strings should return a match of 100%, which means that position is not relevant. Few more things worth noting are that this code is made to compare strings that have space as delimiter in them. If the first string doesnt have space the match is set to 100% without actual check. This was not developed, because the strings this function is ment to compare always contain two or more words. Also, it is written on MS SQL Server 2017 if that mathers.
So here is the solution, hope this helps anyone :)
gl
/****** Object: UserDefinedFunction [dbo].[STRCOMP] Script Date: 29/03/2018 15:31:45 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[STRCOMP] (
-- Add the parameters for the function here
#name_1 varchar(255),#name_2 varchar(255)
)
RETURNS float
AS
BEGIN
-- Declare the return variable and any needed variable here
declare #p int = 0;
declare #c int = 0;
declare #br int = 0;
declare #p_temp int = 0;
declare #emergency_stop int = 0;
declare #fixer int = 0;
declare #table1_temp table (
row_id int identity(1,1),
str1 varchar (255));
declare #table2_temp table (
row_Id int identity(1,1),
str2 varchar (255));
declare #n int = 1;
declare #count int = 1;
declare #result int = 0;
declare #total_result float = 0;
declare #result_temp int = 0;
declare #variable float = 0.0;
--clean the two strings from unwanted symbols and numbers
set #name_1 = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(#name_1,'!',''),' ',' '),'1',''),'2',''),'3',''),'4',''),'5',''),'0',''),'6',''),'7',''),'8',''),'9','');
set #name_2 = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(#name_2,'!',''),' ',' '),'1',''),'2',''),'3',''),'4',''),'5',''),'0',''),'6',''),'7',''),'8',''),'9','');
--check if the first string has more than one words inside. If the string does
--not have more than one words, return 100%
set #c = charindex(' ',substring(#name_1,#p,len(#name_1)));
IF(#c = 0)
BEGIN
RETURN 100.00
END;
--main logic of the operation. This is based on sound indexing and comparing the
--outcome. This loops through the string whole words and determines their soundex
--code and then compares it one against the other to produce a definitive number --showing the raw match between the two strings #name_1 and #name_2.
WHILE (#br != 2 or #emergency_stop = 20)
BEGIN
insert into #table1_temp(str1)
select substring (#name_1,#p,#c);
set #p = len(substring (#name_1,#p,#c))+2;
set #p = #p + #p_temp - #fixer;
set #p_temp = #p;
set #c = CASE WHEN charindex(' ',substring(#name_1,#p,len(#name_1))) = 0 THEN len(#name_1) ELSE charindex(' ',substring(#name_1,#p,len(#name_1))) END;
set #fixer = 1;
set #br = CASE WHEN charindex(' ',substring(#name_1,#p,len(#name_1))) = 0 THEN #br + 1 ELSE 0 END;
set #emergency_stop = #emergency_stop +1;
END;
set #p = 0;
set #br = 0;
set #emergency_stop = 0;
set #fixer = 0;
set #p_temp = 0;
set #c = charindex(' ',substring(#name_2,#p,len(#name_2)));
WHILE (#br != 2 or #emergency_stop = 20)
BEGIN
insert into #table2_temp(str2)
select substring (#name_2,#p,#c);
set #p = len(substring (#name_2,#p,#c))+2;
set #p = #p + #p_temp - #fixer;
set #p_temp = #p;
set #c = CASE WHEN charindex(' ',substring(#name_2,#p,len(#name_2))) = 0 THEN len(#name_2) ELSE charindex(' ',substring(#name_2,#p,len(#name_2))) END;
set #fixer = 1;
set #br = CASE WHEN charindex(' ',substring(#name_2,#p,len(#name_2))) = 0 THEN #br + 1 ELSE 0 END;
set #emergency_stop = #emergency_stop +1;
END;
WHILE((select str1 from #table1_temp where row_id = #n) is not null)
BEGIN
set #count = 1;
set #result = 0;
WHILE((select str2 from #table2_temp where row_id = #count) is not null)
BEGIN
set #result_temp = DIFFERENCE((select str1 from #table1_temp where row_id = #n),(select str2 from #table2_temp where row_id = #count));
IF(#result_temp > #result)
BEGIN
set #result = #result_temp;
END;
set #count = #count + 1;
END;
set #total_result = #total_result + #result;
set #n = #n + 1;
END;
--gather the results and transform them in a percent match.
set #variable = (select #total_result / (select max(row_count) from (
select max(row_id) as row_count from #table1_temp
union
select max(row_id) as row_count from #table2_temp) a));
RETURN #variable/4 * 100;
END
GO
PS: I decided to write it in a user-defined function just for the needs of my project.

How to get stored procedure internal Declare Variable value in SQL Server

This is my stored procedure:
CREATE PROCEDURE MYSP
(#PARAM INT,
#PARAM2 NVARCHAR(34),
#OUTPARAM3 NVARCHAR(34) OUTPUT)
AS
BEGIN
DECLARE #RParam INT
DECLARE #ErrParam2 NVARCHAR(34)
IF(#PARAM = 1 AND #PARAM2 = 'abc' )
BEGIN
SET #OUTPARAM3 = 'EQUAL'
SET #RPARAM = 0
END
ELSE
BEGIN
SET #ERRPARAM2 = 'SOME ERROR..MSG'
SET #RPARAM = -1
END
RETURN #RPARAM
END
And I am trying to get the value of the internally declare variable value.
DECLARE #RParam INT
DECLARE #ErrParam2 NVARCHAR(34)
#RParam is returned but how can I return #ErrParam2 value?
Declare #RP int
Declare #ErrMsg Nvarchar(40)
Exec #RP = MYSP 1,'abc'
You need to specify the output parameter both when the stored procedure is defined and when it is called:
Declare #RP int;
Declare #ErrMsg Nvarchar(40);
Exec #RP = MYSP 1, 'abc' , #ErrMsg output;

sql server The multi-part identifier " " could not be bound stored procedure

I create a stored procedure in which I call two functions .
I'm getting an error:
Msg 4104, Level 16, State 1, Procedure Add_Translation, Line 25
The multi-part identifier ".word" could not be bound.
This is my stored procedure:
ALTER PROCEDURE [dbo].[Add_Translation]
#english nvarchar(70),
#kurdish nvarchar(70),
#english_category int,
#kurdish_category int,
#result int out
AS
BEGIN
SET NOCOUNT ON;
if #english is not null and #kurdish is not null and #english_category is not null and #kurdish_category is not null
begin
declare #intEnId int=-1;
exec #intEnId = Check_English_word #text = #english;
declare #identityEnglish int;
declare #identityKurdish int;
if #intEnId = -1
begin
insert into english_table values(#english, #english_category);
set #identityEnglish = SCOPE_IDENTITY();
end
else
begin
set #identityEnglish = (select e.english_id from english_table e where UPPER(.word)=UPPER(#english));
end
declare #intKuId int=-1;
exec #intKuId=Check_Kurdish_Word #word=#kurdish;
if #intKuId =-1
begin
insert into kurdish_table values(#kurdish, #kurdish_category);
set #identityKurdish = SCOPE_IDENTITY();
end
else
begin
set #identityKurdish = (select k.kurdish_id from kurdish_table k where upper(k.word)=upper(#kurdish));
end
declare #translated int =0;
exec #translated = Check_Translation #english_id = #identityEnglish, #kurdish_id = #identityKurdish;
if #translated=0
begin
insert into transactions values(#identityEnglish, #identityKurdish);
set #result = 1;
end
else
begin
set #result = 2;
end
end
else
begin
set #result = 0;
end
END
Here is the first function:
ALTER FUNCTION [dbo].[Check_English_word]
(
#text nvarchar(70)
)
RETURNS int
AS
BEGIN
DECLARE #Result int
set #Result=-1;
if #text is not null
begin
SELECT #Result = e.english_id
from english_table e
where UPPER(e.word) = UPPER(#text);
end
RETURN #Result
END
Second function:
ALTER FUNCTION [dbo].[Check_Kurdish_Word]
(
#word nvarchar(70)
)
RETURNS int
AS
BEGIN
DECLARE #Result int
set #Result=-1;
if #word is not null
begin
SELECT #Result = k.kurdish_id
from kurdish_table k
where UPPER(k.word) = UPPER(#word);
end
RETURN #Result
END
You are missing an e in this line
set #identityEnglish=(select e.english_id from english_table e
where UPPER(.word)=UPPER(#english));
Change it to
set #identityEnglish=(select e.english_id from english_table e
where UPPER(e.word)=UPPER(#english));
Also, it is good practice to specify columns when doing an insert -
ie
insert into english_table values(#english,#englsih_category);
should be
insert into english_table (word, category) values(#english,#englsih_category);

Stored Procedure Fill Variable with a ResultSet of a Query

I have a little Problem but don't know the Solution!
I have wrote a Stored Procedure. The function of this isn't necessary.
I want to declare a Variable from Type int.
This Variable must get the Value of a SQL Query.
My attempt:
DECLARE #ParentServiceProviderId int = null
SET #ParentServiceProviderId = (SELECT ParentServiceProviderId
FROM ServiceProvider
WHERE ServiceProviderId = #ServiceProviderId)
It didn't work! The ResultSet of the Query have one Row every Time!
I don't know how to solve this Problem!
Here is the complete Stored Procedure:
ALTER PROCEDURE [dbo].[InsertCarmakerPartnership_ChildToParent]
#ServiceProviderId int,
#CarmakerId int,
#ValidFrom datetime,
#ValidTo datetime
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #parentSPPId int, #parentSPPParentId int, #superParentId int, #ParentServiceProviderId int = null
SET #ParentServiceProviderId = (SELECT ParentServiceProviderId
FROM ServiceProvider
WHERE ServiceProviderId = #ServiceProviderId)
DECLARE ServiceProviderParent_Cursor CURSOR FOR
SELECT ServiceProviderId, ParentServiceProviderId
FROM ServiceProvider
WHERE ServiceProviderId = #ParentServiceProviderId
OPEN ServiceProviderParent_Cursor;
FETCH NEXT FROM ServiceProviderParent_Cursor INTO #parentSPPId, #parentSPPParentId
IF (#ParentServiceProviderId is NULL)
BEGIN
SET #superParentId = #ServiceProviderId
EXEC InsertCarmakerPartnership_ParentToChild #superParentId, #CarmakerId, #ValidFrom, #ValidTo;
END
WHILE ##FETCH_STATUS = 0
BEGIN
IF #ServiceProviderId > 0
BEGIN
EXEC InsertCarmakerPartnership_ChildToParent #parentSPPId, #CarmakerId, #parentSPPParentId, #ValidFrom, #ValidTo ;
IF (SELECT COUNT(*) FROM dbo.CarmakerPartnership WHERE ServiceProviderId = #parentSPPId AND CarmakerId = #CarmakerId AND IsDeleted = 0) = 0
BEGIN
INSERT INTO dbo.CarmakerPartnership (CarmakerId, ServiceProviderId, CreatedBy, ChangedBy, ValidityPeriodFrom, ValidityPeriodTo) VALUES (#CarmakerId, #parentSPPId, SYSTEM_USER, SYSTEM_USER, #ValidFrom, #ValidTo)
END
END
FETCH NEXT FROM ServiceProviderParent_Cursor INTO #parentSPPId, #parentSPPParentId
END;
CLOSE ServiceProviderParent_Cursor;
DEALLOCATE ServiceProviderParent_Cursor;
END
Thanks for your help and sorry for my bad english!
Best regards.
Anyway, use next code to populate a variable:
DECLARE #ParentServiceProviderId int
SELECT #ParentServiceProviderId = ParentServiceProviderId
FROM ServiceProvider
WHERE ServiceProviderId = #ServiceProviderId
do not assign default value to this variable and the rest of the code is:
DECLARE #ParentServiceProviderId int
SELECT #ParentServiceProviderId = ParentServiceProviderId
FROM ServiceProvider
WHERE ServiceProviderId = #ServiceProviderId