Formatting Date Error - Oracle 11g - oracle

Trying to write a SQL query to format a date output, but I am getting an error stating, 'a non-numeric character was found where a numeric is expected.'
Below is my SQL:
SELECT e.emp_num, emp_lname, emp_fname, sal_amount
FROM LGEMPLOYEE e
JOIN LGSALARY_HISTORY sh ON e.emp_num = sh.emp_num
WHERE sal_from = (SELECT MIN (to_date(sal_from,'dd-mon-yy'))
FROM LGSALARY_HISTORY sh
WHERE sh.emp_num = e.emp_num)
ORDER BY e.emp_num;
Can anyone help to resolve this issue?

Try to replace
MIN (to_date(sal_from,'dd-mon-yy'))
with
TO_CHAR(MIN (to_date(sal_from,'dd-mon-yy')), 'dd-mon-yy')
You're trying to compare VARCHAR2 with a DATE. Oracle uses an implicit types conversation using the following rule:
When comparing a character value with a DATE value, Oracle converts
the character data to DATE.
Just an assumption: Oracle is trying to convert sal_from to a DATE using default NLS settings (session or database) and apparently fails (because the default date format is 'dd-mm-yy' for example)

This is why it's never a good idea to store date values in a varchar2 column. There is at least one row in your table where the character string in sal_from isn't in the format you expect. That's causing the to_date call to throw an error.
One way of isolating the problematic rows would be something like
CREATE OR REPLACE FUNCTION is_valid( p_str IN VARCHAR2, p_mask IN VARCHAR2 )
RETURN VARCHAR2
IS
l_date DATE;
BEGIN
l_date := to_date( p_str, p_mask );
RETURN 'Y';
EXCEPTION
WHEN others THEN
RETURN 'N';
END;
and then
SELECT *
FROM lgsalary_history
WHERE is_valid( sal_from, 'dd-mon-yy' ) = 'N'

Related

ORA-01858 while executing created procedure

I have created a procedure to find a date between today and expiry_date.
The table column format is already in date format.
While creating procedure it is created successfully without errors but during execution of procedure as below it is showing
ORA-01858: a non-numeric character was found where a numeric was expected
ALTER SESSION SET NLS_DATE_FORMAT ='dd-mm-yyyy';
CREATE OR REPLACE PROCEDURE flow (
today IN DATE,
expiry_date IN DATE
) AS
BEGIN
FOR rec in (
SELECT *
FROM flow4
WHERE englishcalendar BETWEEN 'englishcalendar.today'
AND 'englishcalendar.expiry_date')
LOOP
dbms_output.put_line(rec.englishcalendar);
END LOOP;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(sqlerrm);
END;
/
EXEC FLOW('01-02-2017','03-04-2018');
/
I had also tried adding to_date in both procedure and procedure execution but i got same error
I also tried with this reference too
Getting Error - ORA-01858: a non-numeric character was found where a numeric was expected
NOTE englishcalendar contains continuous day of 2019 in 'dd-mm-yyyy' date format
'englishcalendar.today' is a string not a date. Likewise 'englishcalendar.expiry_date'. Oracle is attempting to convert these strings to dates and failing, because they are not dates.
Simple solution: reference the parameters as identifiers not strings:
...
FOR rec in (
SELECT *
FROM flow4
WHERE englishcalendar BETWEEN today
AND expiry_date)
...

Converting an Oracle Stored Procedure DATE Input Parameter

I am very new to Oracle and have a question about input parameters to a stored procedure. Basically its a stored procedure being called from an external system passing in a date formatted as MM/DD/YYYY.
Oracle doesn't seem to like the MM/DD/YYYY format as it gives me a "not a valid month" error. (I think it wants like a DD-MMM-YYYY?) whatever the default is.
is there a way to convert the date as it comes into the procedure without getting an error?
such as:
create procedure test_proc
(
v_input_date IN DATE := to_char(v_input_date, 'MM/DD/YYYY')
)
I know the above code likely makes no actual sense but hopefully it will convey what I'd like to do. The user would call the procedure something like
BEGIN
test_proc('01/01/2018')
END
You may try with ANSI type date 'yyyy-mm-dd' formatting like in the following sample :
SQL>create or replace procedure test_proc( v_input_date date ) is
v_diff int;
begin
v_diff := trunc(sysdate)-v_input_date;
dbms_output.put_line(v_diff||' days difference...');
end;
/
SQL> set serveroutput on;
SQL> begin
test_proc(date '2018-03-21');
end;
/
2 days difference...
Your problem is not in the procedure, it is in the code calling the procedure.
'01/01/2018' is not a date it is a string but your procedure expects a date; however, Oracle tries to be helpful and will implicitly try to convert the string to a date using the TO_DATE( string_value, format_model ) function. Since it does not have a specified format model, it will use the default format for a date which is the NLS_DATE_FORMAT session parameter and if this format mask does not match the format of the string then you will get an error.
(Note: session parameters are per-user-session and can be changed by each user so you should not rely on them being the same for each user or even the same between sessions for the same user!)
You can see the format of the NLS_DATE_FORMAT session parameter using the query:
SELECT VALUE
FROM NLS_SESSION_PARAMETERS
WHERE PARAMETER = 'NLS_DATE_FORMAT';
And your code to call the procedure is implicitly being converted to something like:
BEGIN
test_proc(
TO_DATE(
'01/01/2018',
( SELECT VALUE FROM NLS_SESSION_PARAMETERS WHERE PARAMETER = 'NLS_DATE_FORMAT' )
)
);
END;
To generate a date you should explicitly convert the string to a date either by:
Using an ANSI literal
BEGIN
test_proc( DATE '2018-01-01' );
END;
Or by specifying the format mask used in the conversion
BEGIN
test_proc( TO_DATE( '01/01/2018', 'MM/DD/YYYY' ) );
END;

PL/SQL insert date with procedure

I want to insert date in my dates table by passing date as ('19-JUN-1997') parameter to procedure. Could anyone give me an example how to do it? It seems that I am doing something wrong with trying to insert date by putting variable in TO_DATE(my_var).
SET SERVEROUTPUT ON
BEGIN
p_date('14-MAR-2017');
END;
CREATE OR REPLACE PROCEDURE p_date(
v_date IN Dates.date1%type) IS
BEGIN
INSERT INTO Dates
(date1)
VALUES
(TO_DATE(v_date ));
END;
If you know the format of the date (e.g., dd-mon-yyyy) then the safest thing to do is make your insert statement like thus:
INSERT INTO Dates (date1)
VALUES (TO_DATE(v_date, 'DD-MON-YYYY');
In order for your example to work, the character string date format must be in the default date format in the database. You can get the value of the database default format using this:
SELECT value
FROM nls_session_parameters
WHERE parameter = 'NLS_DATE_FORMAT'
However, if the default format is changed and you are relying on it, your code will break. It also tells the reader of the code what the date format you're expecting is.

Oracle compare two date

I have oracle query I want to compare two date it work fin but when I put it inside oracle function and pass a date as parameter I get this error:
ORA-01843: not a valid month
ORA-06512: at line 8
Process exited.
and this my function:
Create or Replace
FUNCTION GET_MAX_VALUE
(
PLAN_DATE IN DATE
, LOC IN NUMBER
, RES IN NUMBER
, TIS IN NUMBER
) RETURN NUMBER AS
units number;
return_val number;
BEGIN
select ts.booked_units into units from tsm_transaction_tbl ts
where ts.location_id=loc and ts.resource_id=res and ts.ts_id=tis and ts.trans_date=to_date(plan_date,'mm/dd/yyyy');
RETURN units;
END GET_MAX_VALUE;
Remove the to_date function that surrounds your plan_date variable.
You are already passing plan_date as DATE type variable. There is no need to convert it to date using to_date function.
Speaking about to_date function, it is used to convert a string (varchar2 type) to date type according to the format that we want. You can read more about to_date function on Oracle's site here.
Your code can be as following:
Create or Replace
FUNCTION GET_MAX_VALUE
(
PLAN_DATE IN DATE
, LOC IN NUMBER
, RES IN NUMBER
, TIS IN NUMBER
) RETURN NUMBER AS
units number;
return_val number;
BEGIN
select ts.booked_units into units from tsm_transaction_tbl ts
where ts.location_id=loc
and ts.resource_id=res
and ts.ts_id=tis
and ts.trans_date = plan_date;
RETURN units;
END GET_MAX_VALUE;

ORA-12714: invalid national character set specified

I got a problem with oracle database ,i created a stored procedure and i wanted to pass an array of items' ids to this procedure to select the data according to array of items using "in" clause,the available solution to this as i found was to create a function and pass a string value with all item's ids seperated by a comma ,and this function will return a datatble with a row for each item id.this approach works fine when i try it in toad in a select statement,,but when i use it in the stored procedure i get a strange error
"ORA-12714: invalid national character set specified"
after searching about the reason of that error i found that it is a bug in that version of oracle according to this page and it was fixed in a 10.2.0.4 oracle patch and the exact reason is to declare a cursor for the function that returns a data table
As it is impossible to me to let the users who work on a live production environment to stop the servers to apply the update patch ,I was wondering if any Oracle expert can help me to declare a cursor and return that cursor instead of returning the table.
my Oracle function,Thanks in Advance
create or replace
FUNCTION SplitIDs(
v_List IN VARCHAR2)
RETURN RtnValue_Set PIPELINED
AS
SWV_List VARCHAR2(2000);
v_RtnValue Dt_RtnValue := Dt_RtnValue(NULL);
BEGIN
SWV_List := v_List;
WHILE (instr(SWV_List,',') > 0)
LOOP
FOR RetRow IN
(SELECT ltrim(rtrim(SUBSTR(SWV_List,1,instr(SWV_List,',') -1))) SelectedValue
FROM dual
)
LOOP
v_RtnValue.SelectedValue := RetRow.SelectedValue;
PIPE ROW(v_RtnValue);
END LOOP;
SWV_List := SUBSTR(SWV_List,instr(SWV_List,',')+LENGTH(','),LENGTH(SWV_List));
END LOOP;
FOR RetRow IN
(SELECT ltrim(rtrim(SWV_List)) SelectedValue FROM dual
)
LOOP
v_RtnValue.SelectedValue := RetRow.SelectedValue;
PIPE ROW(v_RtnValue);
END LOOP;
RETURN;
END;
Oracle says this about the error:
Error: ORA-12714 (ORA-12714)
Text: invalid national character set specified
Cause: Only UTF8 and AL16UTF16 are allowed to be used as the national character set
Action: Ensure that the specified national character set is valid
Check your NLS_NCHAR_CHARACTERSET which is set using:
select value from NLS_DATABASE_PARAMETERS where parameter = 'NLS_NCHAR_CHARACTERSET';
Try using NCHAR, NVARCHAR2 or NCLOB

Resources