I built a database application in Visual Studio. When I run, I get this error:
System.Data.SqlClient.SqlException: procedure sp_select_number_of_films has no parameters and arguments were supplied.
I know what the error means, but I am not sure how to fix it in my SQL code. I have tried a bunch of small tweaks, but I still get the same error.
Stored procedure:
CREATE PROCEDURE [dbo].[sp_select_number_of_films]
(#REC_ID_OUTPUT int OUTPUT)
AS
SELECT COUNT(*)
FROM Film.Title;
EXEC dbo.sp_select_number_of_films
GO
It should be called as:
DECLARE #sth INT;
Exec dbo.sp_select_number_of_films #sth OUTPUT;
But then inside stored procedure you need to assign output variable:
CREATE PROCEDURE [dbo].[sp_select_number_of_films]( #REC_ID_OUTPUT int OUTPUT)
AS SELECT #REC_ID_OUTPUT = COUNT(*)
FROM Film.Title;
And you should avoid naming stored procedures with "sp_" prefix.
I'm trying to write a stored procedure to add data to three tables at once. The stored procedure calls three other stored procedures. I have data for each parameter, but I keep getting a missing parameter error in SQL Server. The problem is that the parameter given in the error message isn't a part of the EXECUTE statement of the main stored procedure. Running sp_help shows I'm passing all the parameters needed to the main procedure. The code is below.
Error message: Msg 201, Level 16, State 4, Procedure uspAddCustomerJob, Line 0 [Batch Start Line 157]
Procedure or function 'uspAddCustomerJob' expects parameter '#intJobID', which was not supplied.
-- =========================================
-- stored procedure to add customer record to customer table
GO
CREATE PROCEDURE uspAddCustomer
#intCustomerID AS INTEGER = 0 OUTPUT
,#strName AS VARCHAR(250)
,#strPhone AS VARCHAR(250)
,#strEmail AS VARCHAR(250)
AS
SET XACT_ABORT ON
BEGIN TRANSACTION
INSERT INTO TCustomers(strName, strPhone, strEmail)
VALUES (#strname, #strPhone, #strEmail)
COMMIT TRANSACTION
GO
-- =================================================
-- stored procedure to add job to job table
GO
CREATE PROCEDURE uspAddJob
#intJobID AS INTEGER = 0 OUTPUT
,#strJobDescription AS VARCHAR(250)
,#dtmStartDate AS DATETIME
,#dtmEndDate AS DATETIME
AS
SET XACT_ABORT ON
BEGIN TRANSACTION
INSERT INTO TJobs(strJobDescription, dtmStartDate, dtmEndDate)
VALUES (#strJobDescription, #dtmStartDate, #dtmEndDate)
COMMIT TRANSACTION
GO
-- ===================================================
-- stored procedure to add PK's from previous tables to a third table (many-to-many relationship)
GO
CREATE PROCEDURE uspAddCustomerJob
#intCustomerJobID AS INTEGER OUTPUT
,#intCustomerID AS INTEGER
,#intJobID AS INTEGER
AS
SET XACT_ABORT ON
BEGIN TRANSACTION
INSERT INTO TCustomerJobs(intCustomerID, intJobID)
VALUES (#intCustomerID, #intJobID)
COMMIT TRANSACTION
GO
-- =====================================================
-- main stored procedure that calls each component stored procedure, with execution code at the bottom. Running the EXECUTE statement yields the error mentioned above.
GO
CREATE PROCEDURE uspAddCustomerAndJob --main procedure
#intCustomerJobID AS INTEGER = 0 OUTPUT
,#strName AS VARCHAR(250)
,#strPhone AS VARCHAR(250)
,#strEmail AS VARCHAR(250)
,#strJobDescription AS VARCHAR(250)
,#dtmStartDate AS DATETIME
,#dtmEndDate AS DATETIME
AS
SET XACT_ABORT ON
BEGIN TRANSACTION
DECLARE #intCustomerID AS INTEGER = 0
DECLARE #intJobID AS INTEGER = 0
EXECUTE uspAddCustomer #intCustomerID OUTPUT, #strName, #strPhone, #strEmail;
EXECUTE uspAddJob #intJobID OUTPUT, #strJobDescription, #dtmStartDate, #dtmEndDate;
EXECUTE uspAddCustomerJob #intCustomerJobID OUTPUT, #intJobID;
COMMIT TRANSACTION
GO
--TEST CODE
DECLARE #intCustomerJobID AS INTEGER;
EXECUTE uspAddCustomerAndJob #intCustomerJobID OUTPUT, 'Joe Smith', '513-555-9644', 'Jsmith#yahoo.com', 'Fix cracked sewer pipe', '6/1/2019', '6/5/2019'
Error is happening within the procedure you executed.
Procedure definition for "uspAddCustomerJob" has 3 parameters:
CREATE PROCEDURE uspAddCustomerJob
#intCustomerJobID AS INTEGER OUTPUT
,#intCustomerID AS INTEGER
,#intJobID AS INTEGER
but it is called with 2, "#intCustomerID" is missing:
EXECUTE uspAddCustomerJob #intCustomerJobID OUTPUT, #intJobID;
The error message is misleading. In uspAddCustomerAndJob you're missing a parameter.
Your call looks like this:
EXECUTE uspAddCustomerJob #intCustomerJobID OUTPUT, #intJobID;
SQL Server is taking your first integer parameter and mapping it to the first integer parameter of the child proc, so it thinks it's getting #intCustomerID.
You can avoid this sort of confusion by explicitly naming your parameters in your call, which you should do anyway for the sake of whoever (including yourself) who might need to troubleshoot the code at 3:00AM some day. So that would look like this:
EXECUTE uspAddCustomerJob
#intCustomerJobID = #intCustomerJobID OUTPUT,
#intCustomerID = #intCustomerID
#intJobID = #intJobID;
It looks funny when your local variables are named the same thing as the parameters, but gives you the flexibility to name them differently when the situation is appropriate. Plus, no missing param surprises, or, at least, better messaging around which one is missing.
Consider the following stored procedure:
ALTER PROCEDURE Administration.SetAndRetrieveNewPurchaseOrderNumber
#PurchaseOrderNumber INT OUTPUT
AS
BEGIN
SET NOCOUNT ON
UPDATE Administration.KeyNumbers
SET PurchaseOrderNumber += 1
WHERE RowId = 1
SET #PurchaseOrderNumber = (SELECT kn.PurchaseOrderNumber
FROM Administration.KeyNumbers kn
WHERE kn.RowId = 1)
END
GO
I can use this easily from within my application by simply executing the procedure and passing in by reference a suitably named parameter.
I now find myself wanting to execute the procedure listed above in another stored procedure. I tried the following, but it doesn't appear to work (either with or without the # symbol in the parameter part of the stored procedure being called;
DECLARE #PurchaseOrderNumber INT
EXEC Administration.SetAndRetrieveNewPurchaseOrderNumber(#PurchaseOrderNumber)
What is the correct way to do this, or in reality should there be a separate procedure for use in circumstances like this that only produces a scalar result?
You need to add the output keyword when passing in the parameter.
For example:
Declare #output int;
Exec storedproc(#parameter output)
I have a procedure which takes as argument the function name and then finds out the full body of that function and stores it in a local variable V_FullString.
I need this output not to show in screen rather to put it in text file.
Is it possible ?
ALTER PROCEDURE [dbo].[SP_DictionaryFunction]
#P_FunctionName VARCHAR(100)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #V_ObjectName varchar(100) = #P_FunctionName;
DECLARE #V_FULLSTRING VARCHAR(5000) = ''
IF EXISTS (SELECT object_id FROM SYS.objects
WHERE object_id = OBJECT_ID(#V_ObjectName))
BEGIN
DECLARE #V_TABLE TABLE (Line VARCHAR(500))
INSERT INTO #V_TABLE
EXECUTE SP_HELPTEXT #V_ObjectName
SELECT #V_FULLSTRING = #V_FULLSTRING + Line
FROM #V_TABLE
PRINT #V_FULLSTRING
END
END
Writing a file from the server would be a very bad idea. Ideally you'd be writing it at the client. So... how are you executing the SQL? If this is SSMS, just press ctrl+shift+f. If you are using sqlcmd, then the -o {filename} switch should work. If you're executing it via ADO.NET, then File.WriteAllText. Otherwise, you'll have to tell us what client tool you are using.
Note: I expect that the main problem you're seeing is that print is often ignored. You might prefer select, which all tools will respect.
I think I have the same problem as kcrumley describes in the question "Problem calling stored procedure from another stored procedure via classic ASP". However his question does not really include an solution, so I'll give it another shot, adding my own observations:
I have two stored procedures:
CREATE PROCEDURE return_1 AS BEGIN
SET NOCOUNT ON;
SELECT 1
END
CREATE PROCEDURE call_return_1_and_return_2 AS BEGIN
SET NOCOUNT ON;
EXEC return_1
SELECT 2
END
Note that both procedures contain "SET NOCOUNT ON". When I execute "call_return_1_and_return_2" I still get two record sets. First the value 1, then the value 2.
That throws ASP (classic VBScript ASP) off the tracks.
Any hints on how I can suppress the first result set? Why is it there even with NOCOUNT?
Skipping the first record set in ASP is not an option. I need a "database only" solution.
As Matt points out in his comment, neither solution really 'swallow' the first resultset.
I don't know why you'd want this but you can 'swallow' the result of the first exec by using a table variable. It must match the exact amount and type of the result set's columns. Like so:
CREATE PROCEDURE return_1 AS
SET NOCOUNT ON;
SELECT 1
GO
CREATE PROCEDURE call_return_1_and_return_2 AS
SET NOCOUNT ON;
DECLARE #Result TABLE (res int)
insert into #Result EXEC return_1
SELECT 2
GO
Its not the NOCOUNT thats causing this, your stored procedures have a select each so each one is coming in its own result set. This could be avoided by changing your first stored procedure to use output parameters to pass the number 1 back rather than doing a select. The second stored procedure could then examine the output parameter to get the data it needs to run.
Try something like this
CREATE PROCEDURE Proc1
(
#RetVal INT OUTPUT
)
AS
SET NOCOUNT ON
SET #RetVal = 1
CREATE PROCEDURE Proc2
AS
SET NOCOUNT ON
DECLARE #RetVal int
EXEC [dbo].[Proc1]
#RetVal = #RetVal OUTPUT
SELECT #RetVal as N'#RetVal'
Those are not return variables, but output record sets. I guess that as soon as SQL server flushes output to client, you're screwed and can't take it back.
I would solve this by adding a parameter to SP return_1, that would control if return_1 would select records or just do stuff and silently exit.