How to rewrite Oracle specific function TO_NUMBER to ANSI SQL - oracle

There is a legacy software running against an Oracle database. I'm trying to generalize it for Docker tests, so I prepared a PostgreSQL image with the database schema. Now I'm trying to run that application against the Postgres DB, but there is the following error:
org.postgresql.util.PSQLException: ERROR: function to_number(text) does not exist
So I looked into the code and found the following construct in some selects:
to_number(to_char({0},'HH24MI')) <= to_number(to_char({1},'HH24MI'))
to_number(to_char({0},'HH24MI')) > to_number(to_char({1},'HH24MI'))
Since I'm not a database specialist, I assume that this TO_NUMBER is an Oracle-specific function. In this case it works as a filter to return records for the specified time range.
Is there a way how could I simply replace this TO_NUMBER function with some similar function in ANSI SQL?

Instead of the Oraclism
to_number(to_char(current_timestamp, 'HH24MI'))
you could use this standard SQL construct:
100 * EXTRACT(HOUR FROM current_timestamp)
+ EXTRACT(MINUTE FROM current_timestamp)

Related

Jasper report with 2 differents databases (Oracle and postgresql)

I'm here to ask for your help, so my probleme is:
I have created report with jasperrerport 3.7.6 (queries based on oracle).
and now I'm trying to use the same report with PostgreSql Database and I'm getting errors for specific oracle functions like (NVL, sysdate ...), and I don't want to change the query for now (unless I have to).
Is there any thing to use to make autoconversion when executed on a postgresql database?
If there are no matching functions in both databases, consider creating your own functions which will "simulate" the originals.
For example, for Oracle's SYSDATE:
create or replace function f_sysdate return date is
begin
return sysdate;
end;
I don't know PostgreSQL, but - you'd do the same in that database. Function's name must be the same: F_SYSDATE.
Then, in JasperReports, instead of calling "originals", you'd call your own functions, e.g.
select ename, job, sal,
f_sysdate --> this
from emp
where deptno = 10
Doing so, report would work in both databases. True, you'd have to put some initial effort, but - it might pay off in the future.

Make Oracle last_day function be compatible with H2 database

I am writing integration testing and I want to test my sql queries by using a H2 database. In production these queries are running against an Oracle database.
I have to run this query
I have tries to use the compatibility mode
SELECT last_day(MY_CURRENT_DATE) from MY_TIME
by using the oracle compatibility mode jdbc:h2:mem:default;MODE=Oracle;DB_CLOSE_DELAY=-1 but I receive this error:
org.h2.jdbc.JdbcSQLException: Function "LAST_DAY" not found; SQL statement:
SELECT last_day(MY_CURRENT_DATE) from MY_TIME [90022-176]
It just seems that the compatibility mode does not cover the vendor-specific functions.
I have an idea how to solve this in testing. Just override the Oracle last_day function with a H2 user-defined function:
DROP ALIAS IF EXISTS last_day;
CREATE ALIAS last_day AS $$
String last_day(java.sql.Connection con, Date date) throws Exception {
//get the last day of month
}
}
$$;
But I am wondering if it is the best idea?
Is there a way to re-write the Oracle LAST_DAY function (that calculates the last day of month) in a way which is compatible with all other databases (including H2)?
It is clear for me that for acceptance/system tests you should use a database very similar to the one in production.
For the integration and unit testing you can mock the database server component entirely.

Getting results from an Oracle package function returning a table

Our database has a package that returns a type t_daily_array_table.
This type is defined as:
TYPE t_daily_array_table IS TABLE OF r_daily_array_rec
and r_daily_array_rec is defined as a record with a number of fields.
We have a package called schedule_pkg with the function f_daily_array_table which returns the t_daily_array_table. The function takes a single Number parameter.
I've tried calling it a number of ways, but I can't seem to get it to work (I know this function works. It's called from an COBOL app that functions just fine).
I've tried:
select schedule_pkg.f_daily_array_table(74501) from dual;
When I do that, I get
SQL Error: ORA-00902: invalid datatype
I've tried:
select * from schedule_pkg.f_daily_array_table(74501)
That gives me:
SQL Error: ORA-00933: SQL command not properly ended
I've tried using code (C#) and calling in various ways using OleDb, OracleClient, and ODBC and I have yet to find a way I can call this, other than using COBOL.
If you want to query the values from an SQL context but have a PL/SQL collection type, you can create a pipelined wrapper function, either within the package or as a standalone object for testing/debuggging. Something like this should work:
create function f_daily_array_pipe(p_id IN number)
return schedule_pkg.t_daily_array_table pipelined is
l_daily_array_table schedule_pkg.t_daily_array_table;
begin
l_daily_array_table := schedule_pkg.f_daily_array_table(p_id);
for i in 1..l_daily_array_table.count loop
pipe row (l_daily_array_table(i));
end loop;
end f_daily_array_pipe;
/
select * from table(f_daily_array_pipe(74501));
This calls your original function, assigns the result to a local collection, iterates over it, and pipes each record in turn back to the caller; which uses the SQL table() collection expression to convert it to something you can query from.
SQL Fiddle demo.
If you are using an OCI or JDBC client you can use an array descriptor and retrieve the data as an array, but that won't work from plain SQL.
I think the syntax you're looking for is:
select * from table(schedule_pkg.f_daily_array_table(74501));

How to use SQL syntax in Oracle fast formula

I want to use extract(DAY from date) function in Oracle FastFormula. However I am getting error when I used above. Is there a similar seeded functionality that I can use for this purpose?
By looking at the function reference for OracleFormula, it seems that you have no other option than calling TO_CHAR with the appropriate format to achieve the desired result. based on the doc's example:
mesg = 'Birthday is: ' + TO_CHAR (birthdate,
'DD')

Oracle - applying the to_number function to a varchar column

I want to convert a varchar column into a number using the to_number function however I have some trouble understanding the order in which Oracle attempts to execute my SQL.
The statement looks like this;
select * from table where column is not null and to_number(column, '999.9') > 20
When Oracle executes this it throws an invalid number exception. I understand that Oracle optimized the SQL statement using some kind of relational algebraic formula however can someone tell me how I can safely use the to_number operator to achieve my goal?
can someone tell me how I can safely use the to_number operator to achieve my goal?
Unfortunately, you'll have to first filter out the rows with non-numerical data somehow before you apply to_number. The conversion function itself is "not safe", if you will, it will crash the whole query on a single invalid input.

Resources