The Formal Parameter #QueryComplete was not declared as output. What might be the problem. The entire stored procedure is attached. Thanks - sql

I have built the following stored procedure. It seems to be working fine and the data is going into the table. However, the Programmable Logic Controller is not able to pick the #QueryComplete value to be 1. What might be the issue here. The only error warning is as follows:
The Formal Parameter #QueryComplete was not declared as output.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[SP_Genealogy_WIP]
-- Add the parameters for the stored procedure here
#engine_number as nvarchar(50),
#line_id as int,
#stage_id as int,
#activity_id as int,
#activity_value as nvarchar(50),
#quantity as int,
#status as int,
#plc_YYYY as int,
#plc_MM as int,
#plc_DD as int,
#plc_HR as int,
#plc_MIN as int,
#plc_SEC as int,
-- [Sending Output]
#QueryComplete int OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from;
-- interfering with SELECT statements.
--SET NOCOUNT ON;
Declare #plc_timestamp nvarchar(20);
SET #plc_timestamp = cast(#plc_YYYY as nvarchar(4)) + '-' + Cast(#plc_MM as nvarchar(2)) + '-' + Cast(#plc_DD as nvarchar(2)) + ' ' + Cast(#plc_HR as nvarchar(2)) + ':' + Cast(#plc_MIN as nvarchar(2)) + ':' + Cast(#plc_SEC as nvarchar(2));
SELECT #plc_timestamp as 'PLC TIMESTAMP';
-- Building the Create Statement
BEGIN TRY
INSERT INTO [dbo].[Genealogy_WIP] (
[engine_number]
,[line_id]
,[stage_id]
,[activity_id]
,[activity_value]
,[quantity]
,[status]
,[plc_timestamp]
) VALUES (
#engine_number,
#line_id,
#stage_id,
#activity_id,
#activity_value,
#quantity,
#status,
CAST(#plc_timestamp as datetime)
);
SET #QueryComplete = 1;
SELECT #QueryComplete OUTPUT;
SELECT ' Inserted successfully.' AS Response;
END TRY
BEGIN CATCH
-- statement to handle errors
IF ERROR_NUMBER()=2627
SELECT '[Error]-You cannot insert this value into the table as there is a primary key violation (in the Line ID field) or one of the inputs is incorrect.' AS Response
END CATCH
END

When you have to OUTPUT a value from a parameter you must
specify the parameter with the keyword OUTPUT in the parameter list (you have done it)
set a value to any OUTPUT parameter with SET or SELECT and nothing else (your line "SELECT #QueryComplete OUTPUT;" is wrong. Just write SELECT #QueryComplete = ???" where ??? is a value;
To execute a procedure with a parameter in OUTPUT you must :
Declare a variabale that will accept the returned value
Write the exec command and specify OUTPUT for the returned value
Read the returned value
Example :
DDL :
CREATE PROC P #DT DATETIME2 OUTPUT
AS
SET #DT = SYSUTCDATETIME();
GO
EXEC :
DECLARE #DATETIME2_READ DATETIME2;
EXEC P #DATETIME2_READ OUTPUT;
SELECT #DATETIME2_READ;

Related

Stored Procedure Error Arithmetic overflow error converting numeric to data type varchar

I know this question has been asked so many times.
But I googled a lot and also went through the answers over here but couldn't able to understand why my stored Procedure is giving this error repeatedly since little while ago the same code was perfectly working fine.
Please any one can help my identify that why this error is coming.
Also Even if when this was working I was not getting my desired output as I want to generate the order numbers in sequence but I'm getting the same number as the number of count.
USE [Sost_Dev]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [sost].[GetExternalOrderNumbers]
#Count int
AS
BEGIN
SET NOCOUNT ON;
DECLARE #year VARCHAR(2)
DECLARE #ExternalOrderNumbers nvarchar(50)
SET #year = RIGHT(CAST(DATEPART(yy, GETUTCDATE()) AS VARCHAR(4)),2)
-- Insert statements for procedure here
BEGIN TRAN
SAVE TRAN seq
--Creating Temp Table for every isolated connection
CREATE TABLE #NewOrders(ExtOrderNumber nvarchar(50));
WHILE #Count > 0
BEGIN
INSERT INTO [sost].ServiceOrderNumberSequence DEFAULT VALUES
SET #ExternalOrderNumbers = 'ESON' + #year + RIGHT(REPLICATE('0',10) + CAST(SCOPE_IDENTITY() AS NVARCHAR(7)) ,7);
print 'External' + #ExternalOrderNumbers;
--Insert New Order Number to Temporary Tables
INSERT INTO #NewOrders values(#ExternalOrderNumbers)
SET #Count -=1
END
COMMIT
--Fetching Order Numbers from Temporary Table.
SELECT #ExternalOrderNumbers as ExternalOrderNumber from #NewOrders
END
Please see the below image for the error in my SQLServer
Please find the result All the order numbers are same but I want in consecutive manner.
Just change this line
SET #ExternalOrderNumbers = 'ESON' + #year + RIGHT(REPLICATE('0',10) + CAST(SCOPE_IDENTITY() AS NVARCHAR(100)) ,7);
Edit: AS per your requirement.
SET #ExternalOrderNumbers = 'ESON' + #year + RIGHT(REPLICATE('0',10) + CAST(RIGHT(SCOPE_IDENTITY(),7) AS NVARCHAR(7)) ,7);

Stored procedure returns 0 instead of value

There is a stored procedure that can return top 1 result as
USE [DB]
GO
.....
CREATE PROCEDURE [dbo].[GET]
(#in VARCHAR(10), #Out VARCHAR(10) OUTPUT)
AS
SELECT top 1 #Out = tab.Col
FROM table tab
RETURN
GO
When I call it in main query
DECLARE #output VARCHAR(10)
DECLARE #in VARCHAR(10)
DECLARE #Out VARCHAR(10)
EXECUTE dbo.GET #in = 'table', #Out = #output
It prints #output as 0;
but if I do
EXECUTE dbo.GET #in = 'table', #Out = #Out
And print #out, I get the correct value.
Why could this happen?
I did pass output #Out to pre-defined variable #output
Assuming SQLS due to presence of 'dbo' and sqlserver tag
Your query in the procedure doesn't assign a value to the out parameter (called #out) it assigns to some other variable called #outpk. Resolve the naming mismatch and make them the same
Sqlserver does not support LIMIT. To limit result set size use SELECT TOP 1 *. Using TOP (or any similar result set restrictor) without ORDER BY is illogical. Specify an ORDER BY
In sqlserver, output parameters must be passed with the OUTPUT keyword when calling the procedure:
EXEC sprocname #inputparameter ='value', #outputparameter = #variableToSet OUTPUT;
Use semicolons; omitting them is deprecated
Example
USE [DB]
GO
CREATE PROCEDURE [dbo].[GET]
(#in VARCHAR(10), #OutPk VARCHAR(10) OUTPUT)
AS
SELECT #OutPK = tab.Col
FROM table tab
ORDER BY tab.Col;
GO
DECLARE #output VARCHAR(10);
EXECUTE dbo.GET #in = 'table', #OutPK = #output OUTPUT
SELECT #output;
If its MySql (Limit is in mySql), you can simply call:
Call dbo.GET('table', #out);
No need to have separate variable #output.

Stored procedure get parameter list and current values

Not sure how to implement this, but I need a way to get the current list of parameters for a stored procedure as well as their passed in values (this code will be executed in the stored procedure itself).
I know I can use sys.parameters to get the parameter names, but how to get the actual values?
What I need to do with this is to make a char string of the form
#param_name1=#value1,#param_name2=#value2,...,#param_namen=#valuen
I have tried to use dynamic sql, but not having much joy with that.
Any ideas??
Edit:
Currently I am just going through all the parameters one-by-one to build the string. However I want a "better" way to do it, since there are quite a few parameters. And incase parameters are added later on (but the code to generate the string is not updated).
I tried using dynamic sql but gave up, since the sp_executesql sp requires parameters be passed into it...
You state '(this code will be executed in the stored procedure itself).' so assuming you are in the procedure you will already know the parameter names as you have to declare them when creating your procedure. Just do a select and put the names inside text fields
ALTER PROCEDURE procname
(
#param1 NVARCHAR(255)
,#param2 INT
...
)
SELECT [Parameters] = '#param1=' + #param1
+ ',#param2=' + CONVERT(NVARCHAR(MAX),#param2)...
The CONVERT is there as an example for non-char datatypes.
update
You will need to create a linked server that points to itself to use the OPENQUERY function.
USE [master]
GO
/****** Object: LinkedServer [.] Script Date: 04/03/2013 16:22:13 ******/
EXEC master.dbo.sp_addlinkedserver #server = N'.', #srvproduct=N'', #provider=N'SQLNCLI', #datasrc=N'.', #provstr=N'Integrated Security=SSPI'
/* For security reasons the linked server remote logins password is changed with ######## */
EXEC master.dbo.sp_addlinkedsrvlogin #rmtsrvname=N'.',#useself=N'True',#locallogin=NULL,#rmtuser=NULL,#rmtpassword=NULL
GO
Now you can do something like this cursor to get each parameter name and then use dynamic sql in OPENQUERY to get the value:
DECLARE curParms CURSOR FOR
SELECT
name
FROM sys.parameters
WHERE OBJECT_ID = OBJECT_ID('schema.procedurename')
ORDER BY parameter_id
OPEN curParms
FETCH curParms INTO #parmName
WHILE ##FETCH_STATUS <> -1
BEGIN
SELECT #parmName + '=' + (SELECT * FROM OPENQUERY('linkedservername','SELECT ' + #parmName))
FETCH curParms INTO #parmName
END
CLOSE curParms
DEALLOCATE curParms
Since SQL Server 2014 we have sys.dm_exec_input_buffer, it is a table valued function with an output column event_info that gives the full execution statement (including parameters).
We can parse the param values from sys.dm_exec_input_buffer and get the param names from sys.parameters and join them together to get the string you want.
For example:
create procedure [dbo].[get_proc_params_demo]
(
#number1 int,
#string1 varchar(50),
#calendar datetime,
#number2 int,
#string2 nvarchar(max)
)
as
begin
-- get the full execution statement
declare #statement nvarchar(max)
select #statement = event_info
from sys.dm_exec_input_buffer(##spid, current_request_id())
-- parse param values from the statement
declare #proc_name varchar(128) = object_name(##procid)
declare #param_idx int = charindex(#proc_name, #statement) + len(#proc_name)
declare #param_len int = len(#statement) - #param_idx
declare #params nvarchar(max) = right(#statement, #param_len)
-- create param values table
select value, row_number() over (order by current_timestamp) seq
into #params
from string_split(#params, ',')
-- get final string
declare #final nvarchar(max)
select #final = isnull(#final + ',','') + p1.name + '=' + ltrim(p2.value)
from sys.parameters p1
left join #params p2 on p2.seq = parameter_id
where object_id = ##procid
select #final params
end
To test it:
exec get_proc_params_demo 42, 'is the answer', '2019-06-19', 123456789, 'another string'
Returns the string you want:
#number1=42,#string1='is the answer',#calendar='2019-06-19',#number2=123456789,#string2='another string'
I have something similar wrapped as a UDF. I use it for error logging in catch blocks.

"Subsequent parameters" error in SSRS?

I'm getting a strange error in SSRS, in a report (which gets put into a sproc) with many drop-down parameters:
Query execution failed for dataset 'DataSet1'.
Must pass parameter number 3 and subsequent parameters as '#name = value'. After the form '#name = value' has been used, all subsequent parameters must be passed in the form '#name = value'
I'm lost on what's going on here - what is meant by #name = value .
I searched online, someone mentioned that you should alter the stored-procedure?
Here is how the top half of my stored-proc looks:
USE [FederatedSample]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[prc_RPT_Select_BI_Completes_Data_View_2]
#FromDate DATETIME,
#ToDate DATETIME,
#AccountIDs VARCHAR(max) = null,
#ClientIDs VARCHAR(max) = null,
#SupplierIDs VARCHAR(max) = null,
#CompleteType INT = NULL,
/*
* 0 - Routed
* 1 - Targeted
* 2 - Offerwall
*/
#SourceType BIT = NULL,
/*
* Works if #AccountID is not null
* (should only be used if #AccountID has a single value)
*
* 0 - Owned by #AccountID
* 1 - External (not owned by #AccountID)
*/
#SurveyStatus INT = NULL,
/*
* NULL - All Surveys
* 0 - Completes Approved Surveys
* 1 - Invoiced Surveys
*/
#IsSupplierUser BIT = 0
/*
* used to decide whether to display FEDSurveyName or SupplierSurveyName
*/
AS
BEGIN
SET NOCOUNT ON
DECLARE #SQL NVARCHAR(MAX) = N'',
#Params NVARCHAR(MAX)
IF #AccountIDs is not null
BEGIN
SET #SQL += N'DECLARE #AccountIDs VARCHAR(MAX) = #pAccountIDs; '
END
IF #ClientIDs is not null
BEGIN
SET #SQL += N'DECLARE #ClientIDs VARCHAR(MAX) = #pClientIDs; '
END
IF #SupplierIDs is not null
BEGIN
SET #SQL += N'DECLARE #SupplierIDs VARCHAR(MAX) = #pSupplierIDs; '
END
SET #SQL += N'
SELECT bi.SupplierID as ''Supplier ID''
,bi.SupplierName as ''Supplier Name''
,bi.PID as ''PID''
,bi.RespondentID as ''Respondent ID''
,lk_slt.Name as ''Entry Link Type''
,ts.SurveyNumber as ''Initial Survey ID'''
And later in the stored proc. it does stuff like this to split strings:
IF #AccountIDs is not null
BEGIN
SET #SQL += CHAR(13) + CHAR(9)
SET #SQL += N' and bi.AccountID in (SELECT CAST(val as INT) FROM dbo.Split(#AccountIDs, '','
When invoking a stored procedure, you either can pass the parameters by position (not a good idea) or by Name (a better approach IMHO).
EXEC dbo.MyStoredProcedure '12/31/2012', 1; -- Not a great way to pass parameters
EXEC dbo.MyStoredProcedure #AsOfDate = '12/31/2012', #AccountID = 1; -- A better way
From the error message you are receiving, I suspect that SSRS is using the second approach and is running into an issue with the third parameter being provided to the stored procedure.
Without more information to go off of it is difficult to provide you with an exact explanation for the error (the stored procedure would perhaps help), an educated guess is that the way the parameters are being provided for Account IDs, Client IDs and Supplier IDs isn't quite correct. Specifically, I think the problem might be that you are providing multiple identifiers delimited by a comma.
You might try passing a single Account ID, Client ID and Supplier ID to see if you still receive the error. I would also try to look at the stored procedure (or talk to the DBA \ Developer who wrote it) to ascertain the intended usage of the stored procedure.
I got a similar message when passing a comma instead of a full stop for a decimal value in one of the parameters of a stored procedure.
Here is a simplified example of what happened.
The following command string was erroneously generated with the value of #param2 with a comma instead of a full stop, causing a misunderstanding of the number of parameters.
EXEC myStoredProc #param1 = 1, #param2 = 0,5 ,#param3 = 'something'

How Can i Let Stored Procedure Returns Varchar Value?

Here is my sample:
ALTER PROCEDURE EmpFirstName
#myParam int,
#empFName varchar(20) output
AS
BEGIN
SET NOCOUNT ON;
SELECT #empFName = empfname
FROM FE_QEMP
WHERE empno = #myParam
END
GO
myParam is the input and empFName will carry the output, so the procedure
should only take 1 parameter since empFName is the output, but in my case
i get this error:
Msg 201, Level 16, State 4, Procedure
EmpFirstName, Line 0 Procedure or
function 'EmpFirstName' expects
parameter '#empFName', which was not
supplied.
This is the way i called the procedure:
DECLARE #returnValue varchar(20)
EXEC #returnValue = EmpFirstName 10
SELECT 'Return Value ' = #returnValue
Return values and output parameters are two different things. If you want to call it with an output parameter, you'd do it like this:
EXEC EmpFirstName 10, #returnValue OUTPUT
SELECT 'Return Value ' + #returnValue
If you want to call it in the manner that you described in your example, then you need to alter the stored procedure to state RETURNS VARCHAR(20) and remove the output parameter. To return a value, you have to explicitly call return. In your example, you'd declare a variable, assign it in the select statement, then call return #varName.
Thanks. My aha moment came with this post. Did not realise that output parameters need to be qualified with the "output" identifier too when executed, not just in the procedure!
Here are my test workings for my fellow sql server noobs. I am using sqlcmd with sql server 2005.
The stored procedure:
/* :r procTest.sql */
if exists (select name from sysobjects where name="procTest" and type="P")
drop procedure procTest;
go
create procedure procTest
/* Test stored procedure elements. */
(#i_pt_varchar varchar(20),
#o_pt_varchar varchar(20) output)
as
begin
print "procTest";
set #o_pt_varchar = "string coming out";
print "#i_pt_varchar " + #i_pt_varchar;
print "#o_pt_varchar " + #o_pt_varchar;
return (0);
end
go
The test call:
/* :r procTest.test.sql */
declare #returnFlag int;
declare #i_varchar varchar(20);
declare #o_varchar varchar(20);
set #i_varchar = "string going in";
set #o_varchar = null;
execute #returnFlag = procTest #i_varchar, #o_varchar output
print "#returnFlag " + cast(#returnFlag as varchar(20));
print "after call";
print "#i_varchar " + #i_varchar;
print "#o_varchar " + #o_varchar;
go