Hey guys I want to use SQL Server function,
I never use function in SQL Server and I only know that function must return a value so I have two stored procedure (1 for insert and 1 for select)
My stored procedures look like this
For insert:
create proc INS_tblteststud
#stdtid int=null,
#name varchar(50) =null,
#fullname varchar(50)=null,
#address varchar(50)=null,
#city varchar(50)=null,
#country varchar(50)=null,
#contno varchar(50)=null
as
begin
insert into tbl_student_test(name,fullname,address,city,country,contno)
values
(#name,#fullname,#address,#city,#country,#contno)
end
And for select:
Create proc SEL_tblteststud
as
begin
select * from tbl_student_test
end
Now I want to know, how can I convert these statements(Insert, Select) into functions? And which is better to use stored procedure or function?
You are mixing procedure and function...
A procedure is meant for doing something
A function is meant for reading only
It is not allowed to place data changing commands within a function.
What you are trying is just not possible...
UPDATE Some insight about functions and procedures
There are three types of functions
scalar functions: Return one scalar value and are very bad performing
multi statement table valued functions (with BEGIN ... END): Return a resultset, but are bad performing too
inline table valued functions: They are great, but restricted. Think of them like of a VIEW with pre-compiled parameters
A procedure has a return value too, which is of tpye INT and is not used to return the SP's result, but kind of execution status.
A SP might just do something and return no procedure result at all. If you want to return procedural results you must either use
output parameters
or you must call a SELECT within your SP. It is possible to grab the result of an internal SELECT from outside, but this is very cumbersome...
Related
I have a recursive procedure "FindLoopMakingNode" which is used to find loops, and I'm not expecting nested level to be more than 30.
Here is the recursive procedure:
alter procedure FindLoopMakingNode
#p1 int,
#p2 nvarchar(max)
as
begin
-- recursively calls itself
end
Also, I have another procedure "CheckFormulaForLoop" which is responsible for finding every kind of loop and it uses the recursive procedure mentioned above as well as other statements.
Here is the main wrapper
alter procedure CheckFormulaForLoop
#p1 int,
#p2 nvarchar(max),
#p3 bit
as
begin
--search for other kinds of loop
--if no other loop exists calls recursive procedure
EXEC dbo.FindLoopMakingNode #p1,#p2
--writes the result in a temp table which has been created by wrapper procedure
end
Because I use the second proc for different scenarios, I have different wrapper procedures which use it
Here is the problem: when I execute "CheckFormulaForLoop" for a given set of parameters there is no problem but when I execute one of those wrapper procedures for the exact same set of parameters, I get the Error blew:
Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32)
Here is the wrapper(the one which throws exception, and yes, it's really that simple)
alter procedure CheckFormulaForLoopWrapper
#p1 int,
#p2 nvarchar(max),
#p3 bit
as
begin
Create table #tempLoopHolder(id int,code int)
EXEC CheckFormulaForLoop #p1,#p2,#p3
SELECT id,code from #tempLoopHolder
end
Now when I run
Execute CheckFormulaForLoopWrapper 1212,'2',1
It throws the exception but when I run
Create table #tempLoopHolder(id int,code int)
EXEC CheckFormulaForLoop 1212,'2',1
SELECT id,code from #tempLoopHolder
it runs successfully
I'm wondering if there is a problem with recursion levels why sql doesn't throw an exception when running the main procedure? and can nesting be responsible for this error?
You may maintain this by adding one more parameter to keep the count of recursive call.
You can pass a parameter and before executing your procedure check the value, in your case <30. For true condition before executing your procedure increment your value by +1. By this way you can keep the track of how many times your recursive call is made.
Sample code for same will be like this
Create proc Calltab ( #id int, #cou int=0 )
as
Begin
if(#cou <30 )
Begin
--- perform your operation in this section
set #cou = #cou + 1 --- here increment your value by +1 for the count
exec CallTab #id, #cou
end
end
GO
You may test the same with this
exec CallTab 1 , 0
I have to thank all of you for your precious helps
using all your tips, I found That using a combination of nested procedures + recursive procedure is my problem since as #Zohar Peled said :
The wrapper procedure adds another nesting level. In SQL Server, a procedure is considered nested when it's called by another procedure. As you can surly understand from the error message, using a stored procedure recursively is probably not the best way to handle whatever situation you need handling. If the soul purpose of this procedure is to fill a temporary table, there are probably better ways to do that then recursion. You might want to ask a different question on how to implement whatever it is that procedure does in a set based approach (which is SQL's strong suit).
I used ##NESTLEVEL that #Dale Burrell had mentioned and it turned out that my recursive procedure had to run 31 times (for given parameters) and this amount + 2 ( for 2 wrappers) led to the exception
So finally I see no way to fix it but trying to find a set based approach instead of recursion
Can we call a stored procedure from a function in SQL? What's the reason?
Yes.
You can do this with a bit of a hack involving openrowset but it's not recommended as it will open a new connection.
CREATE FUNCTION dbo.test ()
RETURNS varchar(200)
AS
BEGIN
RETURN (Select top 1 [Name] from
OPENROWSET('SQLNCLI','Server=.\SQL2008;Trusted_Connection=yes;','SET NOCOUNT ON;SET FMTONLY OFF;EXEC MASTER..SP_HELP')
)
END
GO
SELECT dbo.test()
Functions can only read data, they can't update or change anything. It follows that functions are not allowed to call stored procedures.
Quick answer: No.
Why: A stored procedure does not produce any output that can be re-used inside SQL.
To be efficient a function should be deterministic, i.e. the output should only be depending on the input, so that the result can be cached.
If you want to call a stored procedure from a function, yout have to specifically make the function non-deterministic.
I have done my stored procedure 101 recently and just wrote a little stored procedure, which looks like following:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
ALTER PROCEDURE [dbo].[SelectProUserByUsername]
#userName varchar(300)
AS
BEGIN
SET NOCOUNT ON;
SELECT * from ProUser
END
For some reason, SSMS has a reason to believe that my return type is integer. It should in object browser that my stored procedure returns integer
I am not sure what is the reason why it does that. Any ideas?
SQL Server supports both User-Defined Functions and Stored Procedures. Whereas a function takes a number of parameters as input, and returns a single value of a user-defined type as output, a stored procedure is simply a set of connected SQL statements. They can be connected to the rest of the program via input and output parameters, or they can simply modify data, produce result sets, etc, as though the Transact-SQL had been pasted directly into the query.
To quote the Books Online article, a stored procedure can:
Accept input parameters and return multiple values in the form of output parameters to the calling program.
Contain programming statements that perform operations in the database. These include calling other procedures.
Return a status value to a calling program to indicate success or failure (and the reason for failure).
That last point is the sense in which a stored procedure "returns an integer", because the return status is always an integer value (with a default of 0). This is controlled by using the RETURN statement inside the stored procedure.
For instance, if I ran your stored proc above like so:
DECLARE #return_status int;
EXEC #return_status = SelectProUserByUsername 'IMSoP';
SELECT #return_status as status;
I would get an additional result set with status of 0; if I added RETURN 1 at the end of the procedure, I would get 1 instead.
SSMS is simply displaying the "return type" to be consistent with functions, but it's always going to be an integer for a stored procedure.
Note that in some contexts, an integer-returning function and a stored procedure could be used interchangeably; for instance the EXECUTE/EXEC statement in my example above uses the same syntax for any "module" (procedure, function, etc).
I have question. That I can use transaction in function in SQL Server 2012? Because now I have error:
Invalid use of a side-effecting operator 'BEGIN TRANSACTION' within a function.
if you are writing the function to better structure a script, you can call it "procedure" instead of "function", and pass it one or more OUTPUT parameters to receive the computed result.
a "function" cannot have side effects, like inserting/updating/deleting rows or creating/altering/dropping of structures.
i had the same problem and found the solution at the sqlservertutorial , and i heartly recommend you that reading.
CREATE PROCEDURE uspFindProductByModel (
#model_year SMALLINT,
#product_count INT OUTPUT
) AS
BEGIN
SELECT
product_name,
list_price
FROM
production.products
WHERE
model_year = #model_year;
SELECT #product_count = ##ROWCOUNT;
END;
to invoke the procedure and receive the result:
DECLARE #count INT;
EXEC uspFindProductByModel
#model_year = 2018,
#product_count = #count OUTPUT;
i have to mention, that the procedure in this example does not have any side effects, as changing data in the db, so that it could be built as a function as well.
anyway, a procedure seems more versatile, and may support many output parameters, instead of only one return value.
yes i know, a function may return an aggregate.
good luck,
There are several limitations between a SQL Server stored procedure and a user defined function.
UDF's Can't
use nondeterministic functions
change the state of the database
Return messages to the caller
have any side effects
A stored procedure can return multiple record sets and they are not required to return the same fields each time.
create proc custom.sproc_CrazyFields
#ThisItem int
as
begin
if #ThisItem < 10
begin
select 'this' as ThisField, 'that' as ThatField, 'theOther' as theOtherField;
end
else
begin
Select 'theOther' as theOtherField, 'that' as thatField, 'this' as thisField;
end
end
go
exec custom.sproc_CrazyFields 4
exec custom.sproc_CrazyFields 40
An inline function is only going to return a single select statement.
A multistatement function has to declare the returned table.
Is there a way to dynamically return a result with changing columns with a UDF or is this one of the differences?
Sorry, you can't use dynamic SQL in a function. Maybe what you can do is write a stored procedure that creates a function in dynamic SQL, calls the function, then drops it. But then why not just build the query inline at that point.