Finding parameter names for binding stored procedure parameters
-
09-12-2020 - |
Question
For unit testing purposes I am attempting to call the DBMS_OUTPUT.PUT_LINE
procedure from c#
using parameters that are bound by name. Since this DBMS_OUTPUT
package seems to be a standard on Oracle databases, I am using it to test the code that I have written.
I have been able to successfully call DBMS_OUTPUT.ENABLE
with the OraleCommand.BindByName
flag set to true
. However, that is being called without passing any parameters. I have also been able to call a stored procedure that I made myself by passing a reference cursor bound by name.
When I attempt to call DBMS_OUTPUT.PUT_LINE
in a similar fashion I get the following message:
Error Details
ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'PUT_LINE'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
I am specifying the bind name for the parameter as item
according to how the procedure is defined in the 10g documentation for DBMS_OUTPUT. The parameter type for item
is defined as VARCHAR2
and that is the type that is being passed to the procedure. When I set the OracleCommand.BindByName
flag to false, I am able to call DBMS_OUTPUT.PUT_LINE
with no problems.
Here is the code that I am using to run the query:
public bool ExecuteQuery(string procedureName, string[,] queryParameters, bool useReferenceCursor = false)
{
bool returnStatus = false;
if (ConnectionStatus() == false)
{
//message database connection was interrupted
return false;
}
OracleCommand cmd = new OracleCommand();
cmd.CommandText = procedureName;
cmd.CommandType = CommandType.StoredProcedure;
cmd.BindByName = true;
cmd.Connection = databaseConnection;
if (useReferenceCursor)
{
cmd.Parameters.Add("output_reference_cursor", OracleDbType.RefCursor).Direction = ParameterDirection.Output;
}
for (int parameterSet = 0; parameterSet < queryParameters.GetLength(0); parameterSet++)
{
cmd.Parameters.Add(
queryParameters[parameterSet, 0],
OracleDbType.Varchar2,
256,
queryParameters[parameterSet, 1],
ParameterDirection.Input
);
}
if (ConnectionStatus() == false)
{
//message database connection was interrupted
return false;
}
try
{
queryDataReader = cmd.ExecuteReader();
queryHasRows = queryDataReader.HasRows;
returnStatus = true;
}
catch (Oracle.DataAccess.Client.OracleException error)
{
switch (error.Number)
{
case 6550:
Console.WriteLine("The stored procedure specified doesn't exist.");
DatabaseErrorMessage("The stored procedure doesn't exist. Make sure that the procedure has been properly compiled and that the names match.");
break;
default:
throw error;
}
Console.WriteLine(error.ToString());
queryHasRows = false;
returnStatus = false;
}
return returnStatus;
}
Just for reference, we have decided to pass all parameters to the procedures that we write as OracleDbType.Varchar2
and perform the type casting in the stored procedures that we define. The only exception to this would be reference cursors. I am also using Oracle's ODP.net
for access since the Microsoft equivalent is obsolete.
Any feedback or suggestions would be greatly appreciated.
Solution
I did a little bit more research and found the answer to the problem.
Even though the first parameter for DBMS_OUTPUT.PUT_LINE
is listed as item
in the 10g documentation for DBMS_OUTPUT. The actual name for the parameter is A
. You need to bind the name using DBMS_OUTPUT.PUT_LINE(A => 'random text')
.
The actual parameter names for stored procedures can be discovered using the following query:
SELECT
argument_name,
in_out,
data_type
FROM
all_arguments
WHERE
owner = 'SYS' --owner for said procedure
AND package_name = 'DBMS_OUTPUT' --if procedure is in a package that name, null otherwise
AND object_name = 'PUT_LINE' --procedure name
The values SYS
, DBMS_OUTPUT
, and PUT_LINE
can be replaced with the values of the the stored procedure that you would like to look up.