September 4, 2019 at 4:29 am
CREATE PROCEDURE sp_area
@length int,
@width int,
@area int OUTPUT
AS
-- BEGIN is optional
SELECT @area = @length * @width;
-- END is optional
DECLARE @totalArea int
EXECUTE sp_area
@length = 100, @width = 50,
@area = @totalArea OUTPUT
SELECT @totalArea as totalArea;
For my stored procedure above, I have the following questions:
September 4, 2019 at 8:16 am
Also, do not prefix your stored procedure with sp_.
This has a performance impact, as SQL assumes that your proc is in the master DB.
September 4, 2019 at 8:25 am
apart from the items above, begin and end are controversial. I like them, many do not. In any case, if you use them, you still want to ensure you have a GO after the end of your procedure definition.
No sp_, as noted above. You can do spArea or uspArea, but really, I prefer more normal names, like CalculateArea.
For parameters, you can use @area as the parameter you are calling. The call to the procedure doesn't remove @area from your namespace, as it's a parameter. I can do this:
CREATE PROCEDURE sp_area
@length int,
@width int,
@area int OUTPUT
AS
BEGIN -- is optional
SELECT @area = @length * @width;
END -- is optional
GO
DECLARE @Area int
EXECUTE sp_area
@length = 100, @width = 50,
@area = @Area OUTPUT
SELECT @Area as totalArea;
Think about error handling if the procedure has an issue. Do you want the OUTPUT variable to return something here or remain as NULL? You might think about a RETURN value or some check before you start using @totalarea later in calculations.
OUTPUT variables aren't used a lot in the real world. More people return a result set and operate on that from a procedure.
September 4, 2019 at 2:39 pm
Micheal,
Unless you're just trying something simple out to learn how to use stored procedures, this should definitely NOT be a stored procedure. Which is it? Just a simple example for learning or something a bit more serious?
--Jeff Moden
Change is inevitable... Change for the better is not.
September 4, 2019 at 6:23 pm
If you're looking for something simple a scalar function could work. The calculation requires no rows or columns. If you know the function is accessed by query(s) in a proc then the value could be directly assigned to a variable. Something like this:
drop function if exists dbo.calc_area;
go
create function dbo.calc_area(
@lengthint,
@widthint)
returns int
as
begin
return (@length*@width);
end
go
drop proc if exists proc_area;
go
create proc proc_area
@lengthint,
@widthint
as
set nocount on;
declare
@areaint=dbo.calc_area(@length, @width);
select
@area variable_area,
dbo.calc_area(@length, @width) function_area;
go
exec proc_area 10, 12;
This pattern works great for json passed into procedures.
Aus dem Paradies, das Cantor uns geschaffen, soll uns niemand vertreiben können
September 4, 2019 at 9:54 pm
A simple Scalar Function will cause the code to take about 7 times longer than either inline code or an iTVF that acts like a scalar function. Please see the following article for more information on that.
https://www.sqlservercentral.com/articles/how-to-make-scalar-udfs-run-faster-sql-spackle
--Jeff Moden
Change is inevitable... Change for the better is not.
September 4, 2019 at 10:59 pm
If you run it a million times. In this case here the OP has no 'from' clause so it only executes once. I actually did read your article a while back. As a result I keep the number of times a udf runs per proc as low as possible, preferably once. Mostly udf is for code readability.
Aus dem Paradies, das Cantor uns geschaffen, soll uns niemand vertreiben können
September 5, 2019 at 1:55 am
If you run it a million times. In this case here the OP has no 'from' clause so it only executes once. I actually did read your article a while back. As a result I keep the number of times a udf runs per proc as low as possible, preferably once. Mostly udf is for code readability.
I absolutely agree that's how his code is written. The trouble is that he's new to this game and he wrote a RBAR stored procedure simply because he may not know any better, at this point. What I want to do is make sure that he knows better as a part of his "training". The way I know he's new at this is because he's said so in previous posts and also has stated that he wants to learn the best ways possible.
As for me, I can't wait for iSFs (automatic Inline Scalar Functions) in 2019 so, in the meantime, I'll continue to avoid Scalar and mTVFs like the plague and continue to write iTVFs. It's also my nature to teach what I do and to never justify not doing something just because someone is doing something with a low row count. 😀
--Jeff Moden
Change is inevitable... Change for the better is not.
September 6, 2019 at 2:13 am
In any case, if you use them, you still want to ensure you have a GO after the end of your procedure definition.
For parameters, you can use @area as the parameter you are calling. The call to the procedure doesn't remove @area from your namespace, as it's a parameter.
Steve,
Thank you for your reply. I have some questions about some parts that you brought up.
September 6, 2019 at 2:16 am
Micheal,
Unless you're just trying something simple out to learn how to use stored procedures, this should definitely NOT be a stored procedure. Which is it? Just a simple example for learning or something a bit more serious?
Jeff,
Good to hear from you. I was hoping you would jump in to offer your insights. This stored procedure is merely for testing or practicing purposes so I can learn how these work. This is not something that I actually intend to use.
I'm just curious, why do you say this should definitely not be used as a stored procedure?
I'm glad I asked, because I thought it was pretty much ok.
September 6, 2019 at 2:22 am
A simple Scalar Function will cause the code to take about 7 times longer than either inline code or an iTVF that acts like a scalar function. Please see the following article for more information on that.
https://www.sqlservercentral.com/articles/how-to-make-scalar-udfs-run-faster-sql-spackle
I'm going to find out what I can about stored procedures first. Then I will focus on functions. When I am working on functions, I will read the article you recommended. Thanks for posting the link.
September 6, 2019 at 2:36 am
If you run it a million times. In this case here the OP has no 'from' clause so it only executes once. I actually did read your article a while back. As a result I keep the number of times a udf runs per proc as low as possible, preferably once. Mostly udf is for code readability.
To scdecade,
I think I see what you are saying about how many times the function could execute and the fact that I don't have a FROM clause. Are you saying that if I had a FROM clause that references a table with 100 rows, that the function would execute 100 times (one for each row)?
September 6, 2019 at 3:47 pm
I think I see what you are saying about how many times the function could execute and the fact that I don't have a FROM clause. Are you saying that if I had a FROM clause that references a table with 100 rows, that the function would execute 100 times (one for each row)?
Generally speaking Jeff is more correct and scalar functions are not well suited for data access use. His article is definitive on that. I should've explained better the code I was posting. Your case here is not typical. When it comes to accessing data from tables there are always drastically better ways to do things than scalar functions.
Where I use scalar functions is to clean up repetitive elements of code. A few weeks ago someone posted a procedure with about 1/2 the lines of code were the 'procedure help instructions'. I might move that to a scalar function and assign it on declaration in the procedure. That way it's only 1 row instead of half the procedure. It's purely aesthetics I guess.
Would it execute 100 times? If the function was in the select list I would guess the answer is yes. It could be looked up in the documentation. Or maybe just run it a few different ways and see what happens.
Aus dem Paradies, das Cantor uns geschaffen, soll uns niemand vertreiben können
September 11, 2019 at 1:03 am
I tried another simple stored procedure above, which I executed. It didn't display the results window for the SELECT statement result at this time.
Then I right clicked the procedure and did execute procedure and got this code (with the results window this time):
USE [Amargosa Hotel]
GO
DECLARE@return_value int
EXEC@return_value = [dbo].[getData]
SELECT'Return Value' = @return_value
GO
The procedure is returning an int value to @return_value. But I don't understand the purpose of this SELECT statement and what it is doing. Why is SQL taking a text value ('Return Value') and assigning the value of @return_value to the text string? I guess I could understand if it were stated with the variable first, i.e. @return_value = 'Return Value' but then that wouldn't make sense since @return_value is supposed to be of type int instead of text.
Viewing 15 posts - 1 through 15 (of 15 total)
You must be logged in to reply to this topic. Login to reply