Querying a oracle database from .Net with date parameters - oracle

This one is destroying me....
I have an Oracle procedure as below: (this is my latest variation)
create or replace PROCEDURE MANAGEMENTFEES
(
STARTDATE IN VARCHAR2
, ENDDATE IN VARCHAR2
, cursor_ OUT sys_refcursor
) AS
BEGIN
OPEN cursor_ FOR
select PR.PRNUM
FROM MAXIMO.PR
WHERE PR.ISSUEDATE > to_date(STARTDATE) AND PR.ISSUEDATE < to_date(ENDDATE)
END MANAGEMENTFEES;
I am querying it using the following .Net code.
OracleConnection connection = getConnection();
connection.Open();
string startDate = new DateTime(2019, 1, 1).ToString("dd-MMM-yy");
string endDate = new DateTime(2019, 5, 1).ToString("dd-MMM-yy");
OracleDataAdapter da = new OracleDataAdapter();
OracleCommand cmd = new OracleCommand();
cmd.Connection = connection;
cmd.CommandText = "ORACLE.MANAGEMENTFEES";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("STARTDATE", OracleDbType.Varchar2).Value =startDate;
cmd.Parameters.Add("ENDDATE", OracleDbType.Varchar2).Value = endDate;
cmd.Parameters.Add("cursor_", OracleDbType.RefCursor).Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
da.SelectCommand = cmd;
DataTable dt = new DataTable();
da.Fill(dt);
This gives me a blank data table but it does have the headers. SO that tells me the query just isnt getting any results. I have been changing the date parameters using multiple stackoverflow answers but I am getting no where.
If I hard code the dates in the procedure it works fine but I want to be able to pass different dates in.
Help?
UPDATE - Added code in with hardcoded dates
create or replace PROCEDURE MANAGEMENTFEES
(
STARTDATE IN DATE
, ENDDATE IN DATE
, cursor_ OUT sys_refcursor
) AS
BEGIN
OPEN cursor_ FOR
select PR.PRNUM
FROM MAXIMO.PR
WHERE PR.ISSUEDATE > '01-JAN-19' AND PR.ISSUEDATE < '01-MAY-19'
ORDER BY ISSUEDATE ASC;
END MANAGEMENTFEES;

Your procedure should be like this:
create or replace PROCEDURE MANAGEMENTFEES
(
STARTDATE IN DATE
, ENDDATE IN DATE
, cursor_ OUT sys_refcursor
) AS
BEGIN
OPEN cursor_ FOR
select PR.PRNUM
FROM MAXIMO.PR
WHERE PR.ISSUEDATE > STARTDATE AND PR.ISSUEDATE < ENDDATE
END MANAGEMENTFEES;
and the call in .NET would be this:
DateTime startDate = new DateTime(2019, 1, 1);
DateTime endDate = new DateTime(2019, 5, 1);
...
cmd.Parameters.Add("STARTDATE", OracleDbType.Date).Value = startDate;
cmd.Parameters.Add("ENDDATE", OracleDbType.Date).Value = endDate;

This is now resolved and it was caused by the use of STARTDATE and ENDDATE which are reserved by Oracle (although no error was thrown).
Changing them to v_STARTDATE and v_ENDDATE resolved the issue.

Related

Oracle.DataAccess (ODP.NET) Array Binding optimal block size

Is there a way to calculate the optimal block size when using array binding to insert large amounts of data?
I do it like this: When my application runs a command the first time I call this function:
Public Function GetRowSize(ByVal cmd As OracleCommand) As Integer
Dim dr As OracleDataReader
dr = cmd.ExecuteReader()
Return CInt(dr.GetType.GetField("m_rowSize", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic).GetValue(dr))
End Function
The result I store in a class variable for further use.
It is executed like this:
Dim cmd As OracleCommand
Dim da As OracleDataAdapter, dt As New DataTable
Dim expectedNumberOfRows As Integer
cmd = New OracleCommand("BEGIN :res := GetData(:expectedRows); END;"), server.con)
cmd.Parameters.Add("res", OracleDbType.RefCursor, ParameterDirection.ReturnValue)
cmd.Parameters.Add("expectedRows", OracleDbType.Int32, ParameterDirection.Output)
cmd.Parameters("expectedRows").DbType = DbType.Int32
If rowSize = 0 Then rowSizes = GetRowSize(cmd)
cmd.ExecuteNonQuery()
expectedNumberOfRows = CInt(cmd.Parameters("expectedRows").Value)
cmd.FetchSize = rowSize * expectedNumberOfRows
da = New OracleDataAdapter(cmd)
da.Fill(dt)
In my PL/SQL I run EXPLAIN PLAN in order to get the estimated number of rows, it looks like this:
FUNCTION GetData(estimatedRows OUT NUMBER) RETURN SYS_REFCURSOR IS
res SYS_REFCURSOR;
BEGIN
OPEN res FOR SELECT * FROM MY_TABLE;
DELETE FROM PLAN_TABLE;
EXECUTE IMMEDIATE 'EXPLAIN PLAN FOR SELECT * FROM MY_TABLE';
SELECT CARDINALITY
INTO estimatedRows
FROM PLAN_TABLE
WHERE ID = 0;
RETURN res;
END;

Passing a parameter to a stored procedure

I would like to pass a parameter to this stored procedure:
ALTER PROCEDURE [USP_SelectProject]
-- Add the parameters for the stored procedure here
#ProjectNumber as int
AS
BEGIN
if #ProjectNumber is null
begin
select * from tbl_projects
end
else
begin
SELECT * from tbl_projects where ProjectID = #ProjectNumber
end
End
Here is the .net code
SqlConnection PTConn = new SqlConnection(ConfigurationManager.ConnectionStrings["Project_Tracker"].ConnectionString);
SqlCommand PTCmd = new SqlCommand("USP_SelectProject", PTConn);
PTCmd.CommandType = CommandType.StoredProcedure;
SqlDataAdapter PTda = new SqlDataAdapter(PTCmd);
PTda.SelectCommand.Parameters["#ProjectNumber"].Value = DBNull.Value;
DataSet PTds = new DataSet();
PTda.Fill(PTds);
GridView1.DataSource = PTds;
GridView1.DataBind();
I am receiving the following error: An SqlParameter with ParameterName '#ProjectNumber' is not contained by this
You must Add() the parameter first.
SqlParameter p = PTda.SelectCommand.Parameters.Add("#ProjectNumber", DbType.Int);
p.Value = DBNull.Value;

call oracle function with oracle date parameter in classic asp

I'm getting an error in Classic ASP when give oracle date to oracle function in asp. My code:
dim startDate, endDate
startDate = rs1.fields("oraDate1") 'field is oracle field. Gets with oracle to_char('30.10.203','dd/mm/yyyy')
endDate = rs1.fields("oraDate2") 'oraDate2 is like oraDate1
if IsDate(startDate) Then
Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = conn
cmd.CommandText = "find_business_day" 'oracle function
cmd.CommandType = 4
dim date1, date2
set date1 = cmd.CreateParameter("start_date",135,1)
cmd.Parameters.Append date1
date1.value = startDate
set date2 = cmd.CreateParameter("end_Date", 135, 1)
cmd.Parameters.Append date2
date2.value = endDate
cmd.Execute
The error is on the cmd.Execute line, the error message is:
Microsoft OLE DB Provider for ODBC Drivers hata '80004005'
[Microsoft][ODBC driver for Oracle]Invalid parameter type
My oracle function:
CREATE OR REPLACE FUNCTION find_business_day (my_trh1 date,my_trh2 date) return number is
my_isgunu number(2);
begin
select count(*) into my_isgunu from takvim where tatil=1 and tarih between my_trh1 and my_trh2;
Return(my_isgunu);
exception
When others then return(0);
end find_business_day;
/
I solve this problem with change oracle function parameter types.
Here is my solution:
dim startDate, endDate
startDate = rs1.fields("mail_gon_trh")
endDate = rs1.fields("olur_trh")
if IsDate(startDate)
Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = conn
cmd.CommandText = "find_business_day"
cmd.CommandType = 4
set returnval = cmd.CreateParameter("my_isgunu",131,4,100)
cmd.Parameters.Append returnval
set date1 = cmd.CreateParameter("my_trh1",201,1,100)
cmd.Parameters.Append date1
cmd.parameters(1).value = startDate
set date2 = cmd.CreateParameter("my_trh2", 201, 1,100)
cmd.Parameters.Append date2
cmd.parameters(2).value = endDate
cmd.Execute
result = cmd.Parameters(0)
end if
My oracle function:
CREATE OR REPLACE FUNCTION TUBORTAK.ISGUNU_BUL_TRH2 (my_trh1 varchar,my_trh2 varchar) return number is
my_isgunu number(3);
my_trh1_date date;
my_trh2_date date;
begin
my_trh1_date:=to_date(my_trh1,'dd/mm/yyyy');
my_trh2_date:=to_date(my_trh2,'dd/mm/yyyy');
select count(*) into my_isgunu from takvim where tatil=1 and tarih between my_trh1_date and my_trh2_date;
Return(my_isgunu);
exception
When others then return(0);
end ISGUNU_BUL_TRH2;
/

Using ODP.NET to get a RECORD from PL/SQL function, without touching PL/SQL code

The title is pretty-self-explanatory: from a C# application, using ODP.NET, I'm trying to call a PL/SQL function that returns not a simple value, but a record.
Unfortunately, I'm not authorized to add or change the PL/SQL code, so attempting to wrap the function in another function that returns a different type is not an option for me.
Here is a simplified example...
PL/SQL:
CREATE OR REPLACE PACKAGE FOO_PACKAGE AS
TYPE FOO_RECORD IS RECORD (
BAR VARCHAR2(50),
BAZ VARCHAR2(50)
);
FUNCTION FOO_FUNCTION RETURN FOO_RECORD;
END;
/
CREATE OR REPLACE PACKAGE BODY FOO_PACKAGE AS
FUNCTION FOO_FUNCTION RETURN FOO_RECORD AS
R FOO_RECORD;
BEGIN
R.BAR := 'Hello bar!';
R.BAZ := 'Hello baz!';
RETURN R;
END;
END;
/
C#:
The first thing I tried was the most direct approach, but I'm at a loss how to bind the return parameter...
using (var conn = new OracleConnection(connection_string)) {
conn.Open();
using (var tran = conn.BeginTransaction()) {
using (var cmd = conn.CreateCommand()) {
cmd.CommandText = "FOO_PACKAGE.FOO_FUNCTION";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(
null,
/* What to use here? */,
ParameterDirection.ReturnValue
);
cmd.ExecuteNonQuery();
}
}
}
I have also tried some "roundabout" approaches, but they all throw exceptions:
cmd.CommandText = "SELECT * FROM FOO_PACKAGE.FOO_FUNCTION";
cmd.ExecuteReader(); // ORA-00942: table or view does not exist
cmd.CommandText = "SELECT FOO_PACKAGE.FOO_FUNCTION FROM DUAL";
cmd.ExecuteReader(); // ORA-00902: invalid datatype
cmd.CommandText = "SELECT BAR, BAZ FROM (SELECT FOO_PACKAGE.FOO_FUNCTION FROM DUAL)";
cmd.ExecuteReader(); // ORA-00904: "BAZ": invalid identifier
You need anonymous PL/SQL block to convert function result to another representation:
declare
vFooRes FOO_PACKAGE.FOO_RECORD;
vRes sys_refcursor;
begin
vFooRes := FOO_PACKAGE.FOO_FUNCTION;
open vRes for select vFooRes.BAR, vFooRes.BAZ from dual;
--:result := vRes;
end;
SQLfiddle
And execute it instead of calling stored procedure:
cmd.CommandText = "declare\n" +
" vFooRes FOO_PACKAGE.FOO_RECORD;\n" +
"begin\n" +
" vFooRes := FOO_PACKAGE.FOO_FUNCTION;\n" +
" open :result for select vFooRes.BAR, vFooRes.BAZ from dual;\n" +
"end;";
OracleParameter p = cmd.Parameters.Add(
"result",
OracleDbType.RefCursor,
DBNull.Value,
ParameterDirection.Output
);
cmd.ExecuteNonQuery();
After executing cmd you get cursor in result parameter which can be used to fill dataset:
var adapter = new OracleDataAdapter(cmd);
var data = new DataSet("FooDataSet");
adapter.Fill(data, "result", (OracleRefCursor)(p.Value));

PL/SQL Statement ignored error occurs

in bellow code PL/SQL Statement ignored error occurs error accurs line is in bold and italic fonts
create or replace
TRIGGER TRGBILLINGADDRESS
AFTER UPDATE ON TBLMACCOUNTADDRESS
FOR EACH ROW
DECLARE
add1 VARCHAR2(100);
add2 VARCHAR2(100);
cityid VARCHAR2(75);
stateid VARCHAR2(75);
pincd VARCHAR2(10);
BEGIN
SELECT address1,address2,city_id,state_id,pincode
INTO add1,add2,cityid,stateid,pincd FROM wom.tbltaddress ta WHERE ta.ID IN (
SELECT vbac.billing_address_id
FROM wom.vw_billaddresschange vbac, wom.tbltaddress ita
WHERE vbac.billing_address_id = ita.ID
AND vbac.lcid = parlcid);
***IF add1 = :NEW.address1 AND add2 = :NEW.address2 AND cityid = :NEW.cityid AND stateid = :NEW.stateid AND pincode = :NEW.zip THEN***
dbms_output.put_line('Address Already Exist in tbltaddress table');
ELSE
UPDATE wom.tbltaddress ta
SET ta.address1 = :NEW.address1,
ta.address2 = :NEW.address2,
***ta.city_id = :NEW.cityid*,**
ta.country_id = 'CTR0001',
ta.state_id = :NEW.stateid,
ta.pincode = :NEW.zip
WHERE ta.ID IN (
SELECT vbac.billing_address_id
FROM wom.vw_billaddresschange vbac, wom.tbltaddress ita
WHERE vbac.billing_address_id = ita.ID
AND vbac.lcid = parlcid);
END IF;
END;
Your variable is declared as pincd, not pincode. pincode is the field in the table.

Resources