I have a simple Oracle procedure as below. I am trying to call the procedure using VB6 and extract the output from the procedure.
CREATE OR REPLACE PROCEDURE EXTRACTTXN (reportdate IN DATE, p_recordset OUT SYS_REFCURSOR) AS
BEGIN
OPEN p_recordset FOR
SELECT
TXN_ID,
TXN_ACTION,
TXN_STATUS,
TXN_DATE,
TXN_AMOUNT
FROM TRANSACTIONS
WHERE
TRUNC(TXN_DATE) = TRUNC(reportdate)
END EXTRACTTXN;
The VB Code goes like this;
Sub FetchTransactions(ByVal ReportDate As Date, cnnMine as ADODB.Connection)
On Error GoTo TrapErr
Dim cmdMine As ADODB.Command, rsMine As ADODB.Recordset
cmdMine.ActiveConnection = cnnMine
cmdMine.CommandTimeout = 300
cmdMine.CommandType = adCmdStoredProc
cmdMine.CommandText = "EXTRACTTXN"
cmdMine.Parameters.Append cmdMine.CreateParameter("reportdate", adDate, adParamInput, , Format(ReportDate, "DD-MMM-YYYY"))
cmdMine.Parameters.Append cmdMine.CreateParameter("p_recordset", adVariant, adParamOutput)
Set rsMine = cmdMine.Execute
Do While rsMine.EOF
Debug.Print rsMine!TXN_ID, rsMine!TXN_ACTION, rsMine!TXN_STATUS, rsMine!TXN_DATE, rsMine!TXN_AMOUNT
rsMine.MoveNext
Loop
rsMine.Close
Exit Sub
TrapErr:
MsgBox Err.Number & " - " & Err.Description, vbExclamation, App.ProductName
End Sub
While running the code, I get the following Error:
ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'EXTRACTTXN'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
Anything wrong in my code? Appreciate help.
Niz
The problem is that the types of your arguments as specified in your VB code don't match the types of the arguments as specified in your PL/SQL code. The most likely reason for your problem is that the Format function in VB6 returns a Variant type, not a Date type, and that Variant type is set to be a String type. See this for more information on the Format function.
In case you don't know, the way that Variant variables are set up is that they reserve 8 bytes to tell the world what the actual variable type is. So, if you pass your ReportDate in after applying the Format function to it, it will be a Variant that's telling the world it's a string. It's possible that the ADO Parameter object is happy with that (SQL Server is happy to parse properly-formatted strings into Date fields, after all) and Oracle isn't. In my limited experience with Oracle, I've found that it's fussier about that sort of thing than SQL Server.
Try losing the Format function and see if you at least get a different error.
I have managed to get this sorted. It's mainly due to me being new to Oracle and its complexity.
Here are the changes I made;
Stored Procedure Changes. Note that I have changed TRUNC(reportdate, 'DD') on the Where clause.
CREATE OR REPLACE PROCEDURE EXTRACTTXN (reportdate IN DATE, p_recordset OUT SYS_REFCURSOR) AS
BEGIN
OPEN p_recordset FOR
SELECT
TXN_ID,
TXN_ACTION,
TXN_STATUS,
TXN_DATE,
TXN_AMOUNT
FROM TRANSACTIONS
WHERE
TRUNC(TXN_DATE) = TRUNC(reportdate, 'DD')
END EXTRACTTXN;
VB Code Changes (Note that I have change the CommandText within parenthesis with a Call, removed the parameter name, changed the date format to DD/MMM/YYYY and removed the output parameter)
Sub FetchTransactions(ByVal ReportDate As Date, cnnMine as ADODB.Connection)
On Error GoTo TrapErr
Dim cmdMine As ADODB.Command, rsMine As ADODB.Recordset
cmdMine.ActiveConnection = cnnMine
cmdMine.CommandTimeout = 300
cmdMine.CommandType = adCmdStoredProc
cmdMine.CommandText = "{ call EXTRACTTXN}"
cmdMine.Parameters.Append cmdMine.CreateParameter(, adDate, adParamInput, , Format(ReportDate, "DD/MMM/YYYY"))
Set rsMine = cmdMine.Execute
Do While rsMine.EOF
Debug.Print rsMine!TXN_ID, rsMine!TXN_ACTION, rsMine!TXN_STATUS, rsMine!TXN_DATE, rsMine!TXN_AMOUNT
rsMine.MoveNext
Loop
rsMine.Close
Exit Sub
TrapErr:
MsgBox Err.Number & " - " & Err.Description, vbExclamation, App.ProductName
End Sub
The above worked perfectly.
Regards, Niz
Related
Trying to insert simple xml file with one row in IIB with simple message flow into Oracle XE DB. Message flow works fine and inserts data into database, but data written in db is different from starting data. For example, as I'm trying to insert my name "Dino" I'd get Korean/Japanese/Chinese signs in return.
I've tried changing XML formats thinking there might be problem, but I suppose it has to do with encoding.
Input:
Output in DB:
This is how my compute node looks like:
CREATE COMPUTE MODULE SimpleDB_mf_Compute
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
CALL CopyMessageHeaders();
-- CALL CopyEntireMessage();
INSERT INTO Database.dkralj.emp VALUES(InputRoot.XMLNSC.emp.name);
SET OutputRoot.XMLNSC.DBINSERT.STATUS='SUCCESS';
RETURN TRUE;
END;
CREATE PROCEDURE CopyMessageHeaders() BEGIN
DECLARE I INTEGER 1;
DECLARE J INTEGER;
SET J = CARDINALITY(InputRoot.*[]);
WHILE I < J DO
SET OutputRoot.*[I] = InputRoot.*[I];
SET I = I + 1;
END WHILE;
END;
CREATE PROCEDURE CopyEntireMessage() BEGIN
SET OutputRoot = InputRoot;
END;
END MODULE;
Looking at the IBM documentation for the INSERT statement in ESQL it might be worth trying.
INSERT INTO Database.dkralj(NAME) VALUES(InputRoot.XMLNSC.emp.name);
If weird things are still happening then I'd try a string constant to avoid any issues with character coding in the input message.
INSERT INTO Database.dkralj(NAME) VALUES('TheEmpValue');
Before this statement in your code
SET OutputRoot.XMLNSC.DBINSERT.STATUS='SUCCESS';
You should check for success or otherwise by using the inbuilt SQLSTATE, SQLCODE, SQLERRORTEXT to check the result of your call.
IF NOT ((SQLCODE = 0) OR (SQLSTATE = '01000' AND SQLNATIVEERROR = 8153)) THEN
-- Do something about the error.
-- The check of SQLSTATE and SQLNATIVEERROR covers warnings
-- The 8153 is for Microsoft SQL Server other databases may use a different value
END IF;
Also check the codepages aka CodedCharSetId of the source system data, the message in IIB and the default codepage of the database.
Use mqsicvp MYBROKER -n ODBC_DB_NAME to get other details about the connection you need to use -n to get the details.
Use something like DBeaver to add some data. Have a look at the datatype specified for the field.
As per your comment below and my response here is an example of a PASSTHRU statement. Note the use of the ? to avoid SQL Injection.
PASSTHRU('SELECT RTRIM(A.EMPLID) AS EMPLID,
RTRIM(A.ADDRESS_TYPE) AS ADDRESS_TYPE,
RTRIM(A.ADDR_TYPE_DESCR) AS ADDR_TYPE_DESCR,
CAST(RTRIM(A.EFFDT) AS DATE) AS EFFDT,
RTRIM(A.EFF_STATUS) AS EFF_STATUS,
RTRIM(A.ADDRESS1) AS ADDRESS1,
RTRIM(A.ADDRESS2) AS ADDRESS2,
RTRIM(A.ADDRESS3) AS ADDRESS3,
RTRIM(A.ADDRESS4) AS ADDRESS4,
RTRIM(A.CITY) AS CITY,
RTRIM(A.STATE) AS STATE,
RTRIM(A.POSTAL) AS POSTAL
FROM ADDRESS_VW AS A
WHERE UPPER(A.EMPLID) = ?') VALUES(AggrRef.EmployeeID)
I tried implementing a call to Stored proc and the proc returns ID which will used later.
Everytime I execute I get the out parameter as -1. Below is my sample code:
OleDbCommand sqlStrProc = new OleDbCommand();
sqlStrProc.Connection = dbConn;
sqlStrProc.CommandText = "dbo.insert_test";
sqlStrProc.CommandType = CommandType.StoredProcedure;
sqlStrProc.Parameters.Add("#p_TestID", OleDbType.Integer, 255).Direction = ParameterDirection.Output;
sqlStrProc.Parameters.Add("#p_TestName", OleDbType.VarChar).Value = "Test";
sqlStrProc.Parameters.Add("#p_CreatedBy", OleDbType.VarChar).Value = "Test";
int personID = sqlStrProc.ExecuteNonQuery();
Row.outPersonID = personID;
personID is always -1. What am I doing wrong here. Please help..!!
Below is the stored proc code
CREATE PROCEDURE [dbo].[INSERT_TEST]
#p_TestID int OUTPUT,
#p_TestName varchar (50),
#p_CreatedBy varchar (100)
AS
SET NOCOUNT ON
INSERT INTO Test(
TestName,
CreatedBy)
VALUES
( #p_TestName,
#p_CreatedBy)
SELECT #p_TestID = SCOPE_IDENTITY()
-1 could mean that the stored procedure failed to execute as desired and the transaction was rolled back. You may want to look for any truncation issues since you have different sizes for the 2 input parameters but are using the same input. Also I assume you have proper code to open and close connections etc?
-1 returned value is an error produced during the execution of your SP, this is due to the following reasons:
SP Structure: everytime you are executing the SP it tries to create it again while it already exists. so you have to either make it an ALTER PROCEDURE instead of CREATE PROCEDURE or do the following:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[INSERT_TEST]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[INSERT_TEST]
GO
CREATE PROCEDURE [dbo].[INSERT_TEST]
#p_TestID int OUTPUT,
#p_TestName varchar (50),
#p_CreatedBy varchar (100)
AS
Database Connection (Table Name and Location): you have to specify withe the OLEDB the ConnectionString that connects you to the write DB. try to test the full Table path; like the following;
INSERT INTO [DATABASENAME].[SHCEMA].[TABELNAME](
Name,
CreatedBy)
VALUES
( #p_TestName,
#p_CreatedBy)
Define your SP as :
CREATE PROCEDURE [NAME]
AS
BEGIN
END
thought it is not a problem, but it is a proper way to write your SPs in terms of connection transactions,
Let me know if it works fine with you :)
Regrads,
S.ANDOURA
Here is the classic ASP code
Set objCommandSec = CreateObject("ADODB.Command")
With objCommandSec
Set .ActiveConnection = MyConn
.CommandType = adCmdStoredProc
.CommandText = "ReportsPDFInsert"
.CreateParameter "#StatsID", adInteger, adParamInput
.Parameters("#StatsID") = xStats_ID
.CreateParameter "#MemberID", adInteger, adParamInput
.Parameters("#MemberID") = xMemberID
.CreateParameter "#LanguageID", adInteger, adParamInput
.Parameters("#LanguageID") = 1 '1=EN
.CreateParameter "#PDFFilename", adVarWChar , adParamInput
.Parameters("#PDFFilename") = PDFFilename
.Execute
End With
Here is the stored procedure code
ALTER PROCEDURE [dbo].[ReportsPDFInsert]
-- Add the parameters for the stored procedure here
#StatsID INT
,#MemberID INT
,#LanguageID INT
,#PDFFilename NVARCHAR(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
INSERT INTO [dbo].[ReportsPDF]
([StatsID]
,MemberID
,[LanguageID]
,[PDFFilename]
,[DateCreated])
VALUES
(#StatsID
,#MemberID
,#LanguageID
,#PDFFilename
,GETDATE())
END
I get error as
Error number: -2147217904
Error description: Procedure 'ReportsPDFInsert' expects parameter '#StatsID', which was not supplied.
Source: Microsoft OLE DB Provider for SQL Server
If I execute the stored procedure itself, then it is working fine. I have similar classic asp code in other page, and that works fine as well. yes, I made sure xStats_ID does have value. I printed just before the .Execute and I see the value.
Please somebody shed some light. Thanks
Try appending the parameters explicitly using something like this:
cmd.Parameters.Append cmd.CreateParameter("#StatsID",adInteger, adParamInput,xStats_ID)
instead of .Parameters("")
Here is another post that might help:
How to make a parametrized SQL Query on Classic ASP?
Only today I figured what was the problem.
I haven't included the adovbs.inc file for the constants to work.
And I don't know why it was throwing some other error message.
good reason to move away from Classic ASP [only if my boss listens]
Try dropping the "#" in your parameter names.
I cannot run the following SP
CREATE PROCEDURE SP_NYANSAT(
FORNAVN VARCHAR(30),
EFTERNAVN VARCHAR(30),
ADRESSE VARCHAR(50),
POSTNUMMER CHAR(4),
TELEFONNUMMER CHAR(8),
EMAIL VARCHAR(50))
AS
DECLARE VARIABLE ID INTEGER;
BEGIN
ID = GEN_ID(GEN_ANSAT_ID,1);
INSERT INTO MYTABLE (ID, FORNAVN, EFTERNAVN, ADRESSE, POSTNUMMER, TELEFONNUMMER, EMAIL) VALUES (:ID, :FORNAVN, :EFTERNAVN, :ADRESSE, :POSTNUMMER, :TELEFONNUMMER, :EMAIL);
END
The error I get is the following:
can't format message 13:896 -- message file C:\Windows\firebird.msg not found.
Dynamic SQL Error.
SQL error code = -104.
Token unknown - line 3, column 1.
CREATE.
Have you used Set Term before and after this code?
All commands in Firebird must be terminated with a semi-colon. If you want to create a stored procedure you need to be able to distinguish between the terminating semi-colon from the semi-colons inside the stored procedure.
Something like this:
SET TERM ^ ;
CREATE PROCEDURE SP_NYANSAT(
FORNAVN VARCHAR(30),
EFTERNAVN VARCHAR(30),
ADRESSE VARCHAR(50),
POSTNUMMER CHAR(4),
TELEFONNUMMER CHAR(8),
EMAIL VARCHAR(50))
AS
DECLARE VARIABLE ID INTEGER;
BEGIN
ID = GEN_ID(GEN_ANSAT_ID,1);
INSERT INTO MYTABLE (ID, FORNAVN, EFTERNAVN, ADRESSE, POSTNUMMER, TELEFONNUMMER, EMAIL) VALUES (:ID, :FORNAVN, :EFTERNAVN, :ADRESSE, :POSTNUMMER, :TELEFONNUMMER, :EMAIL);
END
^
SET TERM ; ^
Please notice how the declaration of the stored procedure is terminated with ^, thus ending the statement. After the declaration you also restore the terminating semi-colon.
On a side note, I would recommend to copy firebird.msg to the location the error you get tells you so you can see what is really happening.
EDIT:
If you wish you can check this link. There you can find a lot of information regarding Firebird + IBExpress, including SET TERM (page 81).
EDIT 2:
Just tried at home with IBExperts + Firebird and I had no problem creating the stored procedure. My guess is you are trying to do one of the following things:
You have opened an SQL editor and are trying to compile the code directly. That will not work because IBExperts thinks you are trying to run DSQL sentences. Stored procedures are created with PSQL sentences.
You are trying to use the "New procedure" utility (check buttons in the upper right side of the main menu) and pasted the whole code into the editor. That will not work because in that editor you only have to put the body code. Stored procedure name is set in a field on the upper right side of the window you opened. Parameters and variables are introduced by using the "Insert Parameter/Variable" button on the left side above the code editor. The SET TERM sentences are created automatically by IBExperts. You can check the resulting code in the DDL tab.
HTH
I really like SQuirreL SQL as a SQL query tool, but I've never been able to get it to call stored procedures in our AS/400 DB2 database. I always get the error "The number of parameter values set or registered does not match the number of parameters." I've double-checked the number of params and had no luck. This is the syntax I've tried for a procedure that takes one IN and one OUT:
call SOMESPROC(12345, ?);
It seems that SQuirrel currently is not capable of doing that on AS/400 DB2.
Using the open source "SQL Workbench/J" (http://www.sql-workbench.net/) I was able to call a procedure:
wbcall SOMESPROC(12345, ?);
It has its own command for calling a procedure "wbcall". Use ? for out parameters.
Note: While installing SQL Workbench/J make sure to download the right DB2 driver from IBM and also add the licence file while adding the driver inside SQL Workbench/J.
In Squirrel you can use something like this. You'll want to make sure the type of the declared variable matches the type of your out parameter in the stored procedure.
BEGIN
DECLARE outParam INT;
STORED_PROC_NAME(outParam);
END
If you also need to provide input for the procedure you could do this.
BEGIN
DECLARE outParam INT;
STORED_PROC_NAME('input', outParam);
END
You also need to change the statement separator to something other than ;. Otherwise it will break up the statement and try to send each piece individually.
In the pro version of DbVisualizer, with the "Process Parameter Markers in SQL" under the SQL Commander menu option enabled, it will allow the "?" param
call SOMESPROC(12345, ?);
through trial and error, I was able to see the results in Squirrel.
create or replace variable var4 char(1);
create or replace variable var5 decimal(3,0);
create or replace variable var6 char(60);
call getthedata('XXX',123456789,'1234567',var4,var5,var6);
select var4,var5,var6 from sysibm.sysdummy1; -- displays OUT parms
I would think that if there is one in then the call should be:
CALL SomeSProc(12345)
to get a result maybe try:
SELECT * FROM SomeSProc(12345)
Here is an tested example which works on Squirrel 3.7 with a db2 stored procedure . The trick is to passe with an transitional stored procedure MY_PROC_TEST to call the real stored procedure PROC_TEST.
change statement separator in squirrel > session > session properties > SQL : #
DROP PROCEDURE MY_PROC_TEST()#
CREATE PROCEDURE MY_PROC_TEST()
RESULT SETS 1 -- out resultset (call product)
LANGUAGE SQL
BEGIN
DECLARE flag SMALLINT; -- out parameter
CALL MY_PROC('2015', flag);
END #
CALL MY_PROC_TEST()#
END #
Then you can call the sored procedure like this :
CALL MY_PROC_TEST()#
This will work in Squirrel if you change the delimiter (as specified above). However, to see what the variable is, you need to do the following...
In my example, I will set the delimiter to a tildy (~). Include after last "end", before "select". Code begins here...
begin
declare inoutParm numeric(2,0);
call spMyStoredProcedure(
1234567
, inoutParm
);
declare global temporary table session.myTempTbl
(MyResult char(1024) )
with replace ;
insert into session.myTempTbl
(myResult)
values(inoutParm) ;
end
~
select myResult from session.myTempTbl
Mic Keeley
as400(db2) SQL Developer
I was able to cobble together some amalgamation of all of the above answers and came up with this which worked for me. I'm using Squirrel SQL 2018 connecting to an IBM AS/400 DB2 database. I did have to declare a statement separator, I used "#".
BEGIN
DECLARE success CHAR(1); -- output parameters
DECLARE message CHAR(300);
SET success = ' ';
SET message = ' ';
CALL myProc('some', 'params', 4, success, message);
DECLARE GLOBAL TEMPORARY TABLE session.myTmp(s_res CHAR(1), m_res CHAR(300)) WITH REPLACE;
INSERT INTO session.myTmp(s_res, m_res) VALUES(success, message);
END
# -- <- statement separator needs to be set to something other than ";" in this case it's set to "#"
SELECT * FROM session.myTmp;
change statement separator in squirrel > session > session properties > SQL : '#'
BEGIN
DECLARE inOutParam varchar(200);
set inOutParam = 'a value';
STORED_PROC_NAME(outParam);
END;
#