Monday, March 24, 2008

oracle cast function in stored procedure

There is a thing can be called stupid in oracle. I can't understand the reason!
This is a piece of code in a Oracle Trigger. Decimal numbers are compared roundly by double precision.

if (cast(to_char(:new.unit_price) as number(14,2)) = cast(to_char(v_ppl_unit_price) as number(14,2))) then
:new.unit_price := v_temp_new_unit_price;
end if;

But after executed this code, an error is occurred:

Error: PLS-00103: Encountered the symbol "(" when expecting one of the following:
. ) @ %
The symbol ")" was substituted for "(" to continue.
Line: 122
Text: if ( cast(:new.unit_price as number(14, 5)) =

And i found out how to fix it.
that is declare a subtype, and use it on cast:

declare
subtype number_14_2 is number(14, 2);
...
begin
...
if (cast(to_char(:new.unit_price) as number_14_2) = cast(to_char(v_ppl_unit_price) as number_14_2)) then
:new.unit_price := v_temp_new_unit_price;
end if;
...
end

It's done! How strange!

Thursday, March 20, 2008

What's the difference between varchar, varchar2?

Монгол хэл дээр бичигдсэнийг харахыг хүсвэл:
http://mongolcoder.blogspot.com/2008/03/varchar-varchar2.html

Varchar and varchar2 are data types of Oracle DB and what's the difference between them?
First: Size, varchar can store 2000 bytes information, but varchar2 can store 4000 bytes information.
Second: Encoding or language chooser(:D), varchar supports ascii, but varchar2 supports unicode.
In addition to this, mongolian character's take 2 bytes space, but english characters take 1 bytes space.

Tuesday, March 11, 2008

ORA-06502 error occurred while calling stored procedure from C#

Here is a Oracle stored procedure.

create or replace procedure GETVPNOFROMPNO(p_pno in varchar2, ret out varchar2) is
r SYS_REFCURSOR;
npno1 varchar2(255);
retval varchar2(255);
begin
retval:= p_pno;
open r for
select npno from parts_for_update_npno where parts_for_update_npno.pno= p_pno and npno is not null;
fetch r into npno1;
if r%NOTFOUND then
ret:= retval;
return;
end if;
retval:= p_pno||' /'||npno1;
ret:= retval;
end GETVPNOFROMPNO;

As you see, there is no need of REF CURSOR. I declared it just for further use.
And here is a function that calls the stored procedure above.

public static string getVPNOfromPNO(OracleConnection c, string pno)
{
OracleCommand cmd = null;
try
{
c.Open();
cmd = c.CreateCommand();
cmd.CommandText = "GETVPNOFROMPNO";
cmd.CommandType = CommandType.StoredProcedure;

cmd.Parameters.Add("p_pno", OracleType.VarChar);
cmd.Parameters["p_pno"].Value = pno;
cmd.Parameters["p_pno"].Direction = ParameterDirection.Input;

cmd.Parameters.Add("ret", OracleType.VarChar);
cmd.Parameters["ret"].Value = "";
cmd.Parameters["ret"].Direction = ParameterDirection.Output;

cmd.ExecuteNonQuery();
c.Close();
//MessageBox.Show("Suces");
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
Program.setStatus("Error while getting ...!", ex);
}
return cmd.Parameters["ret"].Value.ToString();
}

Do you think there is any error? I thought not, but there was.
While executing, this code throws "ORA-06502: numeric or value error: character string buffer too small" exception.

The error is corrected by changing cmd.Parameters["ret"].Value = ""; to cmd.Parameters["ret"].Value = "__________________";

Why? I used parameter for getting output value. The too small string buffer in the error description is cmd.Parameters["ret"].Value that is length of zero. After setting enough space for this variable, it was OK. If i used oracle function, it would be OK without any problem.