SQL Procedure has no parameters and arguments were supplied - sql-server

So here is the code for the stored procedure and my execution. I keep getting this message when I try to execute my command:
Msg 8146, Level 16, State 2, Procedure sp_LabelFilm, Line 0
Procedure sp_LabelFilm has no parameters and arguments were supplied.
Any idea why? I am trying to update a column in the table tblfilm to say if a movie is short, medium, or long based on its run time.
ALTER PROCEDURE [dbo].[sp_LabelFilm]
AS
BEGIN
DECLARE #Minutes INT, #duration char(10)
DECLARE Filmcursor CURSOR FOR
(SELECT filmruntimeminutes, Duration FROM tblFilm)
OPEN filmcursor
FETCH NEXT FROM filmcursor INTO #duration
WHILE (##FETCH_STATUS = 0)
BEGIN
SELECT #Minutes = FilmRunTimeMinutes FROM tblFilm
IF #Minutes < 120
SET #duration = 'short'
ELSE IF #Minutes < 150
SET #duration = 'medium'
ELSE
SET #duration = 'long'
FETCH NEXT FROM filmcursor INTO #duration
UPDATE tblFilm
SET Duration = #duration
END
CLOSE filmcursor
DEALLOCATE filmcursor
END
DECLARE #Minutes INT, #duration CHAR(10)
EXECUTE [dbo].[sp_LabelFilm] #minutes, #duration

the error means exactly what it says. That you are passing arguments (variables #minutes and #duration) but there are no parameters defined on the stored procedure.
To declare parameters (input variables) you actually declare them before the AS like so:
use Movies
go
alter PROC [dbo].[sp_LabelFilm]
#Minutes INT
,#duration CHAR(10)
AS
BEGIN
DECLARE Filmcursor CURSOR
......
Notice you don't need to use the key word DECLARE and once they are a declared as parameters you don't actually need to declare them again.
Next I am not totally sure what you are attempting to accomplish with the parameters in the stored procedure but it actually looks like you don't want to pass them but rather you want to get them as out put which would be like this:
use Movies
go
alter PROC [dbo].[sp_LabelFilm]
#Minutes INT OUTPUT
,#duration CHAR(10) OUTPUT
AS
BEGIN
DECLARE Filmcursor CURSOR
....
And your execution statement would look like this:
declare #Minutes INT, #duration char(10)
execute [dbo].[sp_LabelFilm] #minutes = #Minutes OUTPUT, #duration = #duration OUTPUT

I had defined the parameters on the stored procedure, before the AS, but still I was facing the same problem until I realized that the procedure had 'create' instead of 'alter'. Changing it to alter procedure worked for me.(Faced this issue while I was trying to debug).

Apart from the first answer which is apt - In my case I did not have any parameters and while EXEC was getting a similar error.
However the difference being - I was putting a "go" below the EXEC statement.
After removing the go it was executed properly.

Related

Return and Store string from an execute statement to be used later

I've got a procedure call that is used by several groups/processes etc.
The call works as follows:
EXEC LWP_PAYMENT_URL #order_no, #dept
and it returns a string like this
NzI2NzU4NabNzEyMj24Ny1zYQ=
I'm given the assignment to create a url path as follows
DECLARE #url_path VARCHAR(4000)
SET #url_path = 'https://www.website.com/payment?code='
DECLARE #ReturnValue VARCHAR(4000) = ''
EXEC #ReturnValue = LWP_PAYMENT_URL #order_no, #dept
SET #url_path = #url_path + #ReturnValue
SELECT #ReturnValue, #url_path
My goal is to take the hard coded url_path and get the encoded string from the execute and save it in a variable and concatenate it to the url_path.
What I'm seeing is that the string is returned part of the execute call instead of setting it to #ReturnValue and then looks like I get a zero value being saved and concatenated.
Added these are the final two lines of the LWP_PAYMENT_URL procedure.
DECLARE #Encoded VARCHAR(500) = CONVERT(VARCHAR(500), (SELECT CONVERT(VARBINARY, #string) FOR XML PATH(''), BINARY BASE64))
SELECT #Encoded AS [Encoded]
Thank you
Your stored procedure should be doing this instead:
CREATE OR ALTER PROCEDURE dbo.LWP_PAYMENT_URL
...#input parameters...,
#encoded varchar(500) = NULL OUTPUT
AS
BEGIN
SET NOCOUNT ON;
...
SET #Encoded = CONVERT(varchar(500),
(SELECT CONVERT(VARBINARY, #string) FOR XML PATH(''), BINARY BASE64));
END
And then the caller says:
DECLARE #ReturnValue varchar(500);
EXEC dbo.LWP_PAYMENT_URL #order_no, #dept,
#Encoded = #ReturnValue output;
If you can't change the stored procedure, create a separate one, or a table-valued UDF as suggested in the comments, or (assuming there are no other SELECTs in the procedure we can't see):
CREATE TABLE #foo(ReturnValue varchar(500));
INSERT #foo EXEC dbo.LWP_PAYMENT_URL ...;
DECLARE #ReturnValue varchar(500);
SELECT #ReturnValue = ReturnValue FROM #foo;
That's gross, though, and basically an abuse of how data sharing should work in SQL Server.
Ideally what you should do is, if the logic is the same for all uses, put that logic in some type of module that is much easier to reuse (e.g. a table-valued function). Then this existing stored procedure can maintain the current behavior (except it would call the function instead of performing the calculation locally), and you can create a different stored procedure (or just call the function directly, if this is all your code is doing), and the logic doesn't have to be duplicated, and you don't have to trample on their stored procedure.

how to use declare variable in select query in stored procedure using sql server

Hello I want to concate two things one is string and other is int variable. Now, these thing I want to store in one variable and use that variable in select query as a into type to create a temptable in stored procedure using sql server.
Here is my query
USE [FlightExamSoftware]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- For Storing Question in Temp table
-- EXEC [GetQuestionListPerSubjectRatioWise] 1,11
ALTER PROCEDURE [dbo].[GetQuestionListPerSubjectRatioWise]
#SubjectID INT,
#NumberOfQue INT,
#UserID int
AS
BEGIN
DECLARE #strQuery VARCHAR(MAX);
DECLARE #PerChapQue INT;
DECLARE #tempTable VARCHAR(MAX) = 'tempTestUser' + #UserID;
SELECT #PerChapQue = COUNT(appQueID)/#NumberOfQue FROM tblQuestion WHERE appQueSubID=#SubjectID
SELECT COUNT(appQueID)/#PerChapQue ChapwiseQue
,CASE WHEN COUNT(appQueID)>=#PerChapQue THEN COUNT(appQueID)/#PerChapQue ELSE 1 END ChapWiseQuePlusOne
,appQueChapID into #tempTable
FROM tblQuestion
WHERE appQueSubID=#SubjectID
GROUP BY appQueChapID
END
Now, I am talking about these line
DECLARE #tempTable VARCHAR(MAX) = 'tempTestUser' + #UserID;
In these line two things are concate one is string and other is int. And store in varchar variable.
And use in following select query i.e.
SELECT COUNT(appQueID)/#PerChapQue ChapwiseQue
,CASE WHEN COUNT(appQueID)>=#PerChapQue THEN COUNT(appQueID)/#PerChapQue ELSE 1 END ChapWiseQuePlusOne
,appQueChapID into #tempTable
FROM tblQuestion
WHERE appQueSubID=#SubjectID
GROUP BY appQueChapID
END
Now, in these query I want to create a temptable named #tempTable.
But, in these line it showing error i.e. Incorrect syntax near '#tempTable'.
Confuse that where is the syntax is wrong.
Thank You.
There are a number of things wrong with your code.
When concatenating an int to a string, you must first cast the int to varchar. Otherwise, SQL Server will try to implicitly convert the string to int, that will result with an error.
So this: DECLARE #tempTable VARCHAR(MAX) = 'tempTestUser' + #UserID; should become this:
DECLARE #tempTable VARCHAR(MAX) = 'tempTestUser' + CAST(#UserID AS VARCHAR(11)); (you need 11 chars to be able to fit the minimum value of int: -2,147,483,648)
You can't use select...into with a table variable.
You can only use it for actual tables (temporary or regular).
your #tempTable isn't even a table variable (not that it will help with a select...into).
Even if you would use select...into the correct way, unless you are going to use a global temporary table (and that doesn't come without it's risks), Unless your stored procedure uses this temporary table later on, it will be useless, since temporary tables are bound to scope.
Taking all of that into consideration I'm not sure what output you are actually looking for. If you could edit your question to include the desired output of your stored procedure as well as some sample data as DDL+DML, it would be easier to help you write better code.
Hope this Dynamic Query helps you:
Try like this:
USE [FlightExamSoftware]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- For Storing Question in Temp table
-- EXEC [GetQuestionListPerSubjectRatioWise] 1,11
ALTER PROCEDURE [dbo].[GetQuestionListPerSubjectRatioWise]
#SubjectID INT,
#NumberOfQue INT,
#UserID int
AS
BEGIN
DECLARE #strQuery VARCHAR(MAX);
DECLARE #PerChapQue INT;
DECLARE #tempTable VARCHAR(MAX) = 'tempTestUser' + CAST(#UserID AS VARCHAR);
SELECT #PerChapQue = COUNT(appQueID)/#NumberOfQue FROM tblQuestion WHERE appQueSubID=#SubjectID
SET #strQuery='
SELECT COUNT(appQueID)/'+CAST(#PerChapQue AS VARCHAR)+' ChapwiseQue
,CASE WHEN COUNT(appQueID)>='+CAST(#PerChapQue AS VARCHAR)+' THEN COUNT(appQueID)/'+CAST(#PerChapQue AS VARCHAR)+' ELSE 1 END ChapWiseQuePlusOne
,appQueChapID
INTO '+#tempTable+'
FROM tblQuestion
WHERE appQueSubID='+CAST(#SubjectID AS VARCHAR)+'
GROUP BY appQueChapID
/*.................................
And you have to use the temp table inside the String only
.................................*/
'
EXEC (#strQuery)
END

Pass a Variable to SQL Stored Procedure ByRef?

Is it possible to assign a value to a variable, pass it to a stored proc, and then within the stored proc: 1.) use the value passed in, 2.) change the value assigned to the variable, and 3.) pass the variable back out?
I am attempting to setup a "Time Hack" that I can intersperse throughout procedures to check which statements are running slowly. Below is an example of the procedure and a call to it.
CREATE PROC [dbo].[usp_TIME_HACK_TEST]
#TITLE VARCHAR(255),
#START_TIME DATETIME OUT
AS
BEGIN
PRINT #TITLE + ': ' + RIGHT(CONVERT(VARCHAR(50),GETDATE() - #START_TIME,13),12)
SET #START_TIME = GETDATE()
END
GO
DECLARE #x int = 0
DECLARE #T DATETIME = GETDATE()
Print '#T Value at Beginning: ' + convert(VARCHAR(50),#T,21)
WHILE #x < 1000000
SET #x += 1
EXEC usp_TIME_HACK_TEST
#TITLE = 'Test Run',
#START_TIME = #T
Print '#T Value at End: ' + convert(VARCHAR(50),#T,21)
Here's what the result looks like. It looks like #START_TIME got treated as an input variable, and the procedure did not change the value of #T. Why did this happen if the variable was declared as an output variable?
#T Value at Beginning: 2016-07-27 11:21:19.720
Test Run: 00:00:00:607
#T Value at End: 2016-07-27 11:21:19.720
Thanks in advance for any help.
You need OUT[PUT] in the calling code too.
EXEC dbo.usp_TIME_HACK_TEST
#TITLE = 'Test Run',
#START_TIME = #T OUTPUT
BTW: Regarding your stated goal there are built in DMVs that can be queried to get information about long running statements already, no need to reinvent the wheel...

Issue converting varchar to INT in sql server

I have seen this question all over stackoverflow, but it seems that there are a wide number of solutions tailored to the situation. It seems I have a unique situation as far as I can tell. I am running this sql statement
use IST_CA_2_Batch_Conversion
GO
--T-SQL script to populate the Match type column
declare #MatchType varchar(16),
#PK varchar(500),
#CAReturnCode VARCHAR(255),
#CAErrorCodes VARCHAR(255)
declare cursor1 cursor fast_forward for
select
["Ref#"],
["Return Code"],
["Error Codes"]
from CACodes2MatchType
open cursor1
fetch next from cursor1 into #PK,#CAReturnCode,#CAErrorCodes
while ##fetch_status = 0
begin
set #MatchType = dbo.GetMatchType(#CAReturnCode,#CAErrorCodes)
update CACodes2MatchType
set [Match Type] = #MatchType
where ["Ref#"] = #PK
fetch next from cursor1 into #PK,#CAReturnCode,#CAErrorCodes
end
close cursor1
deallocate cursor1
It will fail at
set #MatchType = dbo.GetMatchType(#CAReturnCode,#CAErrorCodes)
Here is the beginning code for the GetMatchType function:
-- Batch submitted through debugger:
SQLQuery14.sql|6|0|C:\Users\b01642a\AppData\Local\Temp\~vs1C8E.sql
CREATE FUNCTION [dbo].[GetMatchType](#CAReturnCode VARCHAR(255), #CAErrorCodes
VARCHAR(255))
RETURNS VARCHAR(16)
BEGIN
DECLARE #MatchType VARCHAR(16);
DECLARE #errorCodes TABLE(Pos INT, Code CHAR(2));
DECLARE #country INT; -- 1 is US, 2 is Canada
DECLARE #numMinorChanges INT;
DECLARE #numMajorChanges INT;
DECLARE #numSingleCodes INT;
DECLARE #returnCode INT;
DECLARE #verified VARCHAR(16);
DECLARE #goodFull VARCHAR(16);
DECLARE #tentativeFull VARCHAR(16);
DECLARE #poorFull VARCHAR(16);
DECLARE #multipleMatch VARCHAR(16);
DECLARE #unmatched VARCHAR(16);
SET #verified = 'Verified';
SET #goodFull = 'Good Full';
SET #tentativeFull = 'Tentative Full';
SET #poorFull = 'Poor Full';
SET #multipleMatch = 'Multiple Match';
SET #unmatched = 'Unmatched';
SET #returnCode = CAST(#CAReturnCode AS INT);
I will get the error: Msg 245, Level 16, State 1, Line 21
Conversion failed when converting the varchar value '"1"' to data type int.
This error occurs at the last line of the code segment I have shown:
SET #returnCode = CAST(#CAReturnCode AS INT);
This is code that was written by a colleague and supposedly had worked for him. I have had to troubleshoot some errors but I cannot debug this one. I understand alot of people will create a dbo.split function? I don't know if this option will help me in this scenario. I have tried setting #returnCode to a varchar and getting rid of the CAST on #CAReturnCode. As a result, the debugger will make it past that line but raises issues with the rest of the code. I am assuming there is an issue with how I am casting #CAReturnCode? Any help would be much appreciated.
The problem is that #CAReturnCode contains non-numeric characters.
-- Msg 245, Level 16, State 1, Line 21 Conversion failed when converting the varchar value '"1"' to data type int.
See, the outer single quotes are the error message's formatting, but the inner double quotes are in the #CAReturnCode value. So the solution here is to ensure that the variable contains only numeric characters prior to converting. If double quotes are the only possibility, you can do a quick and dirty fix like this:
set #returnCode = cast(replace(#CAReturnCode, '"', '') as int)
If there are more possibilities, you could do multiple REPLACE calls, or you could build a better character-trimming function that will remove all the characters you specify at once yourself.

Calling dynamic SQL Server stored procedure - expects parameter which was not supplied

I'm trying to call a stored procedure, the name of which is provided by looping through a table. The stored procedure is in another database.
However, I keep getting the message
Procedure or function 'sp_KPI_People_Added_Count' expects parameter
'#Period', which was not supplied.
But it is being supplied.
I have set the statement and parameter definition to NVarChar and prefixed them with N. I've also tried this on the parameters themselves but apparently that's not required.
All the print output is as expected and if I call an execute with the text, it works fine.
So I'm stuck. Any pointers would be warmly welcomed.
Thanks,
Chris.
Declare #KPI_Value Decimal(14,4)
Declare #StoredProcedure NVarChar(200)
Declare #Periodic Char(1)
Declare #ExecSql NVarChar(200)
Declare #ParameterDefinition AS NVarChar(200)
Declare KPI_Cursor CURSOR LOCAL FOR
SELECT SProc, Periodic from KPI where Section = 2
FOR UPDATE OF Current_Value
Open KPI_Cursor
Fetch Next From KPI_Cursor into #StoredProcedure, #Periodic
Declare #Required_Period VARCHAR(5)
SET #Required_Period='MTD'
While ##FETCH_STATUS = 0 BEGIN
Set #KPI_Value = 0 -- Have tried with and without this
If #Periodic = 'Z' BEGIN
SET #ExecSQL = N'Prod.dbo.' + #StoredProcedure;
/* Specify Parameter Format */
SET #ParameterDefinition = N'#Period VarChar(5), #Result_Type VarChar(10), #Result Decimal(14,4) OUTPUT';
/* Execute Transact-SQL String */
print #ExecSQL
print #ParameterDefinition
print #Required_Period
print #KPI_Value
EXECUTE sp_executesql #ExecSQL, #ParameterDefinition, #Required_Period, 'Result', #KPI_Value Output
END
Fetch Next from KPI_Cursor into #StoredProcedure, #Periodic
END
Close KPI_Cursor
Deallocate KPI_Cursor
The stored procedures have parameters as follows:
ALTER PROCEDURE [dbo].[sp_KPI_People_Added_Count]
#Period VarChar(5), -- MTD or YTD
#Result_Type VarChar(10), -- Summary, Result or Detail
#Result Decimal(14,4) OUTPUT -- The returned result
AS
....
The output is as follows:
Prod.dbo.sp_KPI_People_Added_Count
#Period VarChar(5), #Result_Type VarChar(10), #Result Decimal(14,4) OUTPUT
MTD
0.0000
Msg 201, Level 16, State 4, Procedure sp_KPI_Cust_Added_Count, Line 0
Procedure or function 'sp_KPI_People_Added_Count' expects parameter '#Period', which was not supplied.
An alternative way...
EXEC has the little used form EXEC #module_name_var
So you can do this
If #Periodic = 'Z' BEGIN
SET #module_name_var = N'Prod.dbo.' + #StoredProcedure;
EXEC #module_name_var #Required_Period, 'Result', #KPI_Value Output
END
One observation about your original code...
Use N'Result' for the 2nd parameter. sp_executesql says (my bold)
[ #param1= ] 'value1'
Is a value for the first parameter that is defined in the parameter string. The value can be a Unicode constant or a Unicode variable. There must be a parameter value supplied for every parameter included in stmt.

Resources