OUTPUT variables to sp_executesql - stored-procedures

Background: SQL Server 2008 R2
Having issues with the following. Been given a usp to "finish off", author is unavailable. It extracts data from source table, copies to target table of same name + datetime stamp in an archive db then truncates source table. Want to confirm that no errors have occurred & row counts are the same before I truncate source. As I'm using DDL a TRY CATCH combo won't work.
Following code works:
DECLARE #HostName VARCHAR(30) -- Name of server running script
DECLARE #dbName VARCHAR(30) -- Database currently connected to
DECLARE #LogText VARCHAR(255) -- Text to be logged to ArchLog table
DECLARE #NewUTMetaData VARCHAR(255) -- New tablename for UTMetaData
DECLARE #NewOutboundMessagePending VARCHAR(255) -- New tablename for OutboundMessagePending
DECLARE #NewOutboundMessageStatus VARCHAR(255) -- New tablename for OutboundMessageStatus
DECLARE #NewOutboundMessageResult VARCHAR(255) -- New tablename for OutboundMessageResult
DECLARE #NewFileMessageNonSequence VARCHAR(255) -- New tablename for FileMessageNonSequence
DECLARE #NewOutboundMessageRequest VARCHAR(255) -- New tablename for OutboundMessageRequest
DECLARE #NewOutboundMessage VARCHAR(255) -- New tablename for OutboundMessage
DECLARE #SQLQuery NVARCHAR(500)
DECLARE #return_value INT
DECLARE #Err INT = 0
DECLARE #ErrFin INT = 0
DECLARE #SQLCount NVARCHAR(255) = 'SELECT #TargetCountOUT = COUNT(*) FROM '
DECLARE #ParmDefinition nvarchar(50) = N'#TargetCountOUT int OUTPUT';;
DECLARE #SourceCount INT = 0
DECLARE #TargetCount INT = 0
-- Log message that delete is starting
SELECT #HostName = host_name()
SELECT #dbName = db_name()
SELECT #LogText = 'Procedure ArchiveMuleDBMetrix_NEW starting database= ' + #dbname + ' host= ' + #HostName
EXEC xp_logevent 50001, #LogText, 'INFORMATIONAL'
INSERT INTO [MuleDBArch].[dbo].[ArchLog]
([LogEntryDateTime]
,[LogEntry])
VALUES (GETDATE()
,#LogText)
BEGIN
SELECT #NewUTMetaData = (SELECT '[MuleDBArch].[dbo].UTMetaDataA' + convert(varchar(50),GetDate(),112) + replace(convert(varchar, GetDate(),108),':',''))
SET #err = ##error;
SET #SQLQuery = 'select * into ' + #NewUTMetaData + ' from [MuleDB].[dbo].[SASITUTMetaData]'
EXECUTE sp_executesql #SQLQuery
SET #SourceCount = ##ROWCOUNT
SELECT #LogText = 'Rows archived into ' + #NewUTMetaData + ' by Procedure ArchiveMuleDBMetrix_NEW = ' + CAST(#SourceCount as VARCHAR(6))
EXEC xp_logevent 50002, #LogText, 'INFORMATIONAL'
INSERT INTO [MuleDBArch].[dbo].[ArchLog]
([LogEntryDateTime]
,[LogEntry])
VALUES (GETDATE()
,#LogText)
IF #err = 0
BEGIN
SET #sqlcount = #sqlcount + #NewUTMetaData
EXECUTE sp_executesql #sqlcount, #ParmDefinition, #TargetCountOUT=#TargetCount OUTPUT;
IF #SourceCount = #TargetCount
TRUNCATE TABLE [MuleDB].[dbo].[SASITUTMetaData]
ELSE
SELECT #LogText = 'Post archive, row counts differ between [MuleDB].[dbo].[SASITUTMetaData] and' + #NewUTMetaData
EXEC xp_logevent 50003, #LogText, 'Error'
Set #errfin = 1
SET #err = 0
END
ELSE
BEGIN
SELECT #LogText = 'Procedure ArchiveMuleDBMetrix_NEW failed archiving into ' + #NewUTMetaData
EXEC xp_logevent 50004, #LogText, 'Error'
Set #errfin = 1
SET #err = 0
END
END
However, if I repeat the block to work on another table (or indeed the same one) query completes with error and I get the message:
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '.'.
I think I've narrowed it down to the line:
EXECUTE sp_executesql #sqlcount, #ParmDefinition, #TargetCountOUT=#TargetCount OUTPUT;
Any help appreciated

In the below code
EXECUTE sp_executesql #sqlcount, #ParmDefinition, #TargetCountOUT=#TargetCount OUTPUT;
You are trying to pass parameter values without specifying the parameter names except the output parameter while calling the stored procedure. Either specify the parameter name for all or none. Try to execute the code as follows
EXECUTE sp_executesql #sqlcount, #ParmDefinition, #TargetCount OUTPUT;

Related

Variable Assignment Issue for Multiple dynamic SQL in DB2 Iseries

We are using DB2 Iseries V7R3 on AS400 system.
In one of the stored procedure, we are preparing dynamic SQL queries. Each SQL query is assigned to different variables. When we execute the stored procedure sometimes it fails but when retry with same parameters it works.
Upon putting logs in the stored procedure, we have observed that during the failed cases value used for variable 2 is from variable 1.
Attached is the stored procedure and screenshot of the logs.
Appreciate any help on this, running out of the thinking options for this.
However, sometimes it uses select * for variable1 as well. After retry it works ok.
create stored procedure (
)DYNAMIC RESULT SETS 1
LANGUAGE SQL
SPECIFIC SYMDTA.PRC_RETRIEVE_CLAIM_LIST
NOT DETERMINISTIC
MODIFIES SQL DATA
CALLED ON NULL INPUT
COMMIT ON RETURN YES
CONCURRENT ACCESS RESOLUTION USE CURRENTLY COMMITTED
SET OPTION ALWBLK = *ALLREAD ,
ALWCPYDTA = *OPTIMIZE ,
COMMIT = *NONE ,
DECRESULT = (31, 31, 00) ,
DYNDFTCOL = *NO ,
DYNUSRPRF = *USER ,
SRTSEQ = *HEX
BEGIN
DECLARE DATACLAIM CLOB ( 1048576 ) DEFAULT ' ' ;
DECLARE GCLAIMCOUNT CLOB ( 1048576 ) DEFAULT ' ' ;
DECLARE CR_CLAIM_LIST_STMT CURSOR WITH HOLD FOR CLM_DATA_STMT ;
DECLARE CR_CLAIM_COUNT_STMT CURSOR WITH HOLD FOR CLM_COUNT_STMT ;
SET DATACLAIM = 'SELECT * FROM table ';
SET GCLAIMCOUNT = 'select count(*) from table';
INSERT INTO DEBUGGING_DYNAMIC_QUERIES VALUES ( POLICY_NO , DATACLAIM , CURRENT TIMESTAMP , 'DATACLAIM' ) ;
INSERT INTO DEBUGGING_DYNAMIC_QUERIES VALUES ( GCLAIMCOUNT , CURRENT TIMESTAMP , 'GCLAIMCOUNT' ) ;
PREPARE CLM_DATA_STMT FROM DATACLAIM ;
OPEN CR_CLAIM_LIST_STMT ;
PREPARE CLM_COUNT_STMT FROM GCLAIMCOUNT ;
OPEN CR_CLAIM_COUNT_STMT ;
FETCH CR_CLAIM_COUNT_STMT INTO TOTAL_RECORDS_G4 ;
CLOSE CR_CLAIM_COUNT_STMT ;
Output the debug table :-
Wrong :-
DATACLAIM = "select * " - 2020-01-01 11:00 AM
GCLAIMCOUNT = "Select * " - 2020-01-01 11:01 AM
After retry :-
DATACLAIM = "select * " - 2020-01-01 12:00 pm
GCLAIMCOUNT = "Select count(*) " - 2020-01-01 12:01 Pm

ASP Classic Recordset In Stored Procedure -1 Recordcount

I'm working with a SQL Server stored procedure in Classic ASP with 3 parameters. I am attempting to find the recordcount, but it returns '-1'.
I saw a similar post, did what it suggested (check cursortype, and add 'set nocount on' in the stored procedure), but those changes did not impact the -1 recordcount.
Here is my code in the Classic ASP page, below.
strInterestName = request("InterestName")
strActiveDate = request("activedate")
strExpireDate = request("expiredate")
Set objCommandSec = CreateObject("ADODB.Command")
Set objRS = CreateObject("ADODB.RecordSet")
objRS.cursorlocation = 3
objRS.cursortype = adOpenStatic
With objCommandSec
Set .ActiveConnection = objConnection
.CommandText = "[01_cms_search_pg_select_news_items_4]"
.CommandType = 4
.Parameters.Append .CreateParameter("#InterestName",adVarChar,
adParamInput, 25)
.Parameters.Append .CreateParameter("#ActiveDate",adDate, adParamInput)
.Parameters.Append .CreateParameter("#ExpireDate",adDate,
adParamInput)
.Parameters("#InterestName") = strInterestName
.Parameters("#ActiveDate") = strActiveDate
.Parameters("#ExpireDate") = strExpireDate
set objRS =.Execute()
End With
Here is the code for the stored procedure, below:
ALTER PROCEDURE [dbo].[01_cms_search_pg_select_news_items_4]
#InterestName varchar(50),
#ActiveDate datetime,
#ExpireDate datetime
AS DECLARE #sql nvarchar(4000)
SELECT #sql = ' SELECT * ' +
' FROM news ' +
' WHERE ' +
' bulletin_display_indicator = ''true'' '+
' AND ' +
' website_homepg_display_indicator= ''false'' '
IF #InterestName is not null
SELECT #sql = #sql + ' AND (InterestName = #InterestName)
IF #ExpireDate is not null and #ExpireDate IS NOT NULL
SELECT #sql = #sql + ' AND (expiredate between #ActiveDate and #ExpireDate)
SELECT #sql = #sql + '; '
EXEC sp_executesql #sql, N'#InterestName varchar(50), #ActiveDate
DateTime, #ExpireDate DateTime',#InterestName, #ActiveDate,
#ExpireDate
I struggled with that for a while, then found something that works for me.
It's not pretty but it does the job.
Have your Stored Procedure return 2 recordsets: one with the table data you need followed by one with the recordcount:
SELECT <all_you_need> FROM <your_table> WHERE <your_arguments>
SELECT [myCount] = ##ROWCOUNT
Then, in your ASP file:
dim objRS, dataRS, countRS
Set objRS = CreateObject("ADODB.RecordSet")
Set dataRS = CreateObject("ADODB.RecordSet")
Set countRS = CreateObject("ADODB.RecordSet")
[your original call to the stored procedure]
set objRS =.Execute()
set dataRS = objRS
set countRS = objRS.nextrecordset()
countRS now contains a recordset with a single row and a single column named 'myCount' that you can query to get the recordcount.
dataRS contains your original dataset.
NOTE: if you don't need to know the recordcount BEFORE you process the dataset, you can simplify like this:
dim objRS, countRS
Set objRS = CreateObject("ADODB.RecordSet")
Set countRS = CreateObject("ADODB.RecordSet")
[your original call to the stored procedure]
set objRS =.Execute()
[process your dataset as you need to]
set countRS = objRS.nextrecordset()

Error handling in Teradata Stored Procedure

I am trying to develop a stored procedure within TERADATA to handle and manage exceptions.
The stored procedure should raise the error to the caller, which is an SSIS Package.
I am trying to illustrate this by creating a stored procedure for illustration only.
I have these tables:
Table_A:
- ID INT
- ITEM_NUM INT
- DESC VARCHAR(20)
- CREATE_DTTM VARCHAR(2O)
Table_B:
- ID INT
- ITEM_NUM INT
- DESC VARCHAR(20)
- CREATE_DTTM VARCHAR(2O)
I have two tables that will be inserting data from two SELECT statements.
REPLACE PROCEDURE csTest2()
SQL SECURITY OWNER
BEGIN
DECLARE varErrorMessage char(256);
DECLARE varSQLState char(5);
DECLARE varReturnCode char(5);
DECLARE varRollbackNeededInd char(1); /* transaction mgt */
SET varRollbackNeededInd = 'N';
SET varReturnCode = '00000';
SET varErrorMessage = '';
BEGIN TRANSACTION;
-- USING A SINGLE HANDLER WITH MULTIPLE STATEMENTS
-- PLANING TO CHANGE ERROR MESSAGE IN EACH STATEMENT.
ins6: BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
H99:Begin
set varSQLState = SQLSTATE;
set varErrorMessage= 'This message should not be displayed'; --
end H99;
-- IMAGINE THAT I AM GETTING THE VALUES AS INPUT PARAMERS IN THE PROCEDURE
INSERT INTO "Table_A"
(ID , ITEM_NUM, DESC, CREATE_DTTM)
SELECT 1, '222', 'SOME DESC',CURRENT_TIMESTAMP;
H98:Begin
set varSQLState = SQLSTATE;
set varErrorMessage= 'This message is displayed, ITEM_NUM invalid characters';
end H98;
-- NOW I AM DOING A SECOND INSERT TO table b WITH INVALID DATA
-- THE VALUE FOR THE ITEM NUMBER CONTAINS ALPHANUMERICE CHARACTERS
INSERT INTO "Table_b"
(ID , ITEM_NUM, DESC, CREATE_DTTM)
SELECT 1, '333F', 'SOME DESC',CURRENT_TIMESTAMP;
END ins6;
EndTrans: BEGIN
IF varSQLState <> '0' THEN
SET varRollbackNeededInd = 'Y';
SET varReturnCode = '9999';
END IF;
IF varRollbackNeededInd = 'Y' THEN
ROLLBACK; -- ROLLBACK AND SEND ERROR TO CALLER
SIGNAL SQLSTATE 'U0123' SET MESSAGE_TEXT = 'SQlState is - ' || varSQLSTATE || ' - and error is - ' || varErrorMessage;
ELSE
END TRANSACTION; -- COMMIT TRANSACTION
END IF;
END EndTrans;
END;
The problem that I am facing with the above stored procedure is that error message that I get is not the one that I am expecting. Since error is intentionally created in my second statement I am expecting to get: This message is displayed, ITEM_NUM invalid characters but I am getting This message should not be displayed
Now if I modify the PROCEDURE to have multiple handlers, one for each statement, I do get the correct error message, but now since I am intentionally generating the error in the first statement it does not terminate the procedure, it handles the error and sets the proper message but continues to process the next statement which I am not expecting to do this, so how can I terminate this procedure?
REPLACE PROCEDURE csTest2()
SQL SECURITY OWNER
BEGIN
DECLARE varErrorMessage char(256);
DECLARE varSQLState char(5);
DECLARE varReturnCode char(5);
DECLARE varRollbackNeededInd char(1); /* transaction mgt */
SET varRollbackNeededInd = 'N';
SET varReturnCode = '00000';
SET varErrorMessage = '';
BEGIN TRANSACTION;
ins6: BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
H99:Begin
set varSQLState = SQLSTATE;
set varErrorMessage= 'Error is displayed in this case because ITEM_NUM';
-- ERROR IS PRESENT IN THIS STATEMENT AND SHOULD TERMINATE THE PROCEDURE.
INSERT INTO "Table_A"
(ID , ITEM_NUM, DESC, CREATE_DTTM)
SELECT 1, '222F', 'SOME DESC',CURRENT_TIMESTAMP;
END ins6;
ins7: BEGIN
H98:Begin
set varSQLState = SQLSTATE;
set varErrorMessage= 'no error is displayed in this case';
end H98;
-- NO ERROR IS EXPECTED, BUT IT SHOULD NOT REACH HERE SINCE WE HAD ERROR ON FIRST STATEMENT.
INSERT INTO "Table_b"
(ID , ITEM_NUM, DESC, CREATE_DTTM)
SELECT 1, '333', 'SOME DESC',CURRENT_TIMESTAMP;
END ins7;
EndTrans: BEGIN
IF varSQLState <> '0' THEN
SET varRollbackNeededInd = 'Y';
SET varReturnCode = '9999';
END IF;
IF varRollbackNeededInd = 'Y' THEN
ROLLBACK; -- ROLLBACK AND SEND ERROR TO CALLER
SIGNAL SQLSTATE 'U0123' SET MESSAGE_TEXT = 'SQlState is - ' || varSQLSTATE || ' - and error is - ' || varErrorMessage;
ELSE
END TRANSACTION; -- COMMIT TRANSACTION
END IF;
END EndTrans;
END;

Stored Procedure not updating database

Issue:
The database is not updating but I'm unsure where it drops.
I've used numerous ones in the past but I can't see why this is not working. If I could see how to run an error test on the stored procedure I suspect that would help.
Tests:
I pass the variables to a label, after the stored procedure request in the .aspx code to check the values exist (left in code)
Change int to varchar in the stored procedure
Query:
How do I fix this and then how can I run tests to find the issues in the future
Stored Procedure:
USE [DATABASE]
GO
/****** Object: StoredProcedure [dbo].[spChangeValue] Script Date: 11/08/2015 12:02:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
ALTER PROCEDURE [dbo].[spRiskRatingChange]
#ActionID int,
#EmployeeID int,
#NewRating varchar(10)
AS
DECLARE #DateChanged AS nvarchar(max)
SET #DateChanged = GETDATE()
DECLARE #OldRating AS nvarchar(max)
DECLARE #OldComments AS nvarchar(max)
DECLARE #EmployeeName AS nvarchar(max)
SET #OldRating =
(
SELECT OverallRiskCategory FROM TblAsbestos WHERE ID = #ActionID
)
SET #OldComments =
(
SELECT Comments FROM TblAsbestos WHERE ID = #ActionID
)
SET #EmployeeName =
(
SELECT UserFirstName + ' ' + UserSurname FROM SystemUsers WHERE ID = #EmployeeID
)
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
UPDATE TblAsbestos SET OverallRiskCategory = #NewRating, RiskCategory = #NewRating,
Comments= ('Rating changed from ' + RTRIM(#OldRating) + ' to '
+ RTRIM(#NewRating) + 'By ' + #EmployeeName + ' on ' + #DateChanged + ' -- ' + #OldComments)
WHERE ID = #ActionID
END
Code in .aspx.vb
Dim connection As SqlConnection
Dim command As New SqlCommand
Dim ds As New DataSet
Dim ConnectionString1 As String = System.Configuration.ConfigurationManager.ConnectionStrings("VINCI_SQL").ToString()
connection = New SqlConnection(ConnectionString1)
connection.Open()
With command
.Connection = connection
.CommandText = "spRiskRatingChange" 'include audit names
.CommandType = CommandType.StoredProcedure
.Parameters.Clear()
.Parameters.AddWithValue("#ActionID", Session("ActionID").ToString)
.Parameters.AddWithValue("#EmployeeID", Session.Item("EmployeeID").ToString)
.Parameters.AddWithValue("#NewRating", ddOverallRiskCategoryEdit.SelectedValue)
.ExecuteNonQuery()
lblErrorMessageRatings.Visible = True
lblErrorMessageRatings.Text = "Action ID: " & Session("ActionID").ToString
lblErrorMessageRatings.Text = lblErrorMessageRatings.Text & " EmployeeID: " & Session("EmployeeID").ToString
lblErrorMessageRatings.Text = lblErrorMessageRatings.Text & " NewRating: " & ddOverallRiskCategoryEdit.SelectedValue
Read items such as:
UPDATE Stored Procedure not Updating
Instead of
.Parameters.AddWithValue("#ActionID", Session("ActionID").ToString)
try
.Parameters.Add("#ActionId",SqlDbType.Int)
.Parameters("#ActionId").Value = CInt(Session("ActionId"))
I am assuming it is an int value you are passing
.Parameters.AddWithValue does an implicit type conversion and perhaps this is what is causing your problem

ADODB.Recordset error '800a0e78' - Error when I pass 2 parameters (ASP/MSSQL)

My classic ASP page thorws up an error when I pass 2 paremeters to the Exec code for my
stored procedure. Basically I want to send 1 paremeter to cover the column I am looking for
and one for the search-term. For example imSchool, New York University. I have data checks on the data sent as well as Record Set.State code showing that everytime i choose SQL Query with the two paramerts the error "Operation is not allowed when the object is closed." always shows.
I tried to open the object at " While Not rs.EOF" line of code where it error out bit no luck.
I am thinking my SQLQuery is bad because when I run the Stored Procedure in MSSQL with the same input I get a return table everytime. SQL Server 2008 R2 and Classic ASP.
HERE IS MY IF STATMENT WITH SQLQUERY CODE (keep in mind the 1st one works fine and data is selected from the DB)
SQLQuery = "Exec sp_vw_InternImport"
Set rs = Server.CreateObject("ADODB.Recordset")
rs.CursorType = 3
rs.Open SQLQuery, OBJdbConnection
If filterColmn <> "" Then
SQlQuery = "Exec sp_vw_InternImport_ColID #LookUpID=N'" + filterID + "'" + ", #LookUpCol=N'" + filterID + "'"
Set rs = Server.CreateObject("ADODB.Recordset")
rs.CursorType = 3
rs.Open SQLQuery, OBJdbConnection
End If
HERE IS MY STORED PROCEDURE CODE
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_vw_InternImport_ColID]
(
#LookUpID nvarchar (255),
#LookUpCol nvarchar (50)
)
AS
SET NOCOUNT ON
BEGIN
IF #LookUpCol = 'imYear'
SELECT * FROM v_InternImport WHERE imYear = #LookUpID
ELSE
IF #LookUpCol = 'imSchool'
SELECT * FROM v_InternImport WHERE imSchool = #LookUpID
ELSE
IF #LookUpCol = 'imDiscipline'
SELECT * FROM v_InternImport WHERE imDiscipline = #LookUpID
IF #LookUpCol = 'imDegree'
SELECT * FROM v_InternImport WHERE imDegree = #LookUpID
END
When passing arguments to stored procedure directly, you don't have to "assign" the parameters. Doing this probably results in the whole value passed (e.g. #LookUpCol will have the value of #LookUpCol ='imYear') thus your SP won't select anything and you have empty and closed recordset.
Try having such code instead:
SQlQuery = "Exec sp_vw_InternImport_ColID '" & filterID & "', '" & filterID & "'"
You can't use the same object twice at the same time (like rs), you have to make it another name or you have to close it and start over.. This should work:
SQLQuery = "Exec sp_vw_InternImport"
If filterColmn <> "" Then SQLQuery = "Exec sp_vw_InternImport_ColID #LookUpID=N'" + filterID + "'" + ", #LookUpCol=N'" + filterID + "'"
Set rs = Server.CreateObject("ADODB.Recordset")
rs.CursorType = 3
rs.Open SQLQuery, OBJdbConnection
rs.Close
Or in your example, if you close the first rs object before you go on to the next, it may help.
set rs = nothing ... then .... set rs = server.createobject
So like this:
SQLQuery = "Exec sp_vw_InternImport"
Set rs = Server.CreateObject("ADODB.Recordset")
rs.CursorType = 3
rs.Open SQLQuery, OBJdbConnection
rs.Close ------ Close it before you re-open it
If filterColmn <> "" Then
SQlQuery = "Exec sp_vw_InternImport_ColID #LookUpID=N'" + filterID + "'" + ", #LookUpCol=N'" + filterID + "'"
rs.Open SQLQuery, OBJdbConnection
rs.Close ------ Always Close your Objects!
End If

Resources