PL/SQL insert date with procedure - oracle

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.

Related

ORA-01861: literal does not match format string?

I have this trigger
CREATE OR REPLACE TRIGGER TRIGGER_MAYOR
BEFORE INSERT OR UPDATE ON VENTAS_MENSUALES
FOR EACH ROW
DECLARE
V_PRODUCTO VARCHAR2(30);
V_FECHA DATE;
V_USUARIO VARCHAR2(50);
BEGIN
SELECT DESCRIPCION INTO V_PRODUCTO FROM PRODUCTO;
SELECT SYSDATE INTO V_FECHA FROM DUAL;
SELECT USER INTO V_USUARIO FROM DUAL;
INSERT INTO VENTAS_MENSUALES(PRODUCTO,FECHA,USUARIO) VALUES (V_PRODUCTO,' '||V_FECHA,V_USUARIO);
END;
I compile and i don't get errors but when i'm going to test by inserting values i get this
INSERT INTO VENTAS_MENSUALES(PRODUCTO,FECHA,USUARIO) VALUES ('testing','2019-05-02',user);
ERROR
ORA-01861: literal does not match format string
This is my table and columns ... I'm just trying to insert values there to check if it's works or not ! producto can be anything , fecha is supposed to be the sysdate and usuario is supposed to be the user who is doing the query (in this case PRUEBA2)
The error doesn't have anything to do with the trigger; the insert is erroring before it gets as far as firing that.
'2019-05-02' is a string, not a date. You should use a date literal like date '2019-05-02', or to_date().
INSERT INTO VENTAS_MENSUALES(PRODUCTO,FECHA,USUARIO)
VALUES ('testing', date '2019-05-02', user);
or if you prefer:
INSERT INTO VENTAS_MENSUALES(PRODUCTO,FECHA,USUARIO)
VALUES ('testing', to_date('2019-05-02', 'YYYY-MM-DD'), user);
but unless you need a non-midnight time, that's just more typing.
Your trigger does have some issues though. Sticking with dates, in this part:
INSERT INTO VENTAS_MENSUALES(PRODUCTO,FECHA,USUARIO)
VALUES (V_PRODUCTO,' '||V_FECHA,V_USUARIO);
The ' '||V_FECHA will implicitly convert the date value to a string using the current session's NLS settings, then prepend a space, then implicitly convert it back to a date. The only reason I can imagine to want to do that is to strip off the time portion, but that relies on NLS, which is never safe; and can be much more easily achieved with trunc(V_FECHA). If that is what you want; if this is for auditing/history then you probably want the full time to be preserved.
Then, SELECT DESCRIPCION INTO V_PRODUCTO FROM PRODUCTO; will try to return all rows from the PRODUCTO table into a single string value. If the table only has one row that will work, but that seems unlikely. If the table is empty you'll get a no-data-found error. If it has more than one row you'll get too-many-rows ("ORA-01422: exact fetch returns more than requested number of rows").
Possibly you intended to look up a single product, but if so it isn't clear how you would identify it. Perhaps the table has another column you haven't shown, and you meant to use the :new pseudorecord.
Both of these queries:
SELECT SYSDATE INTO V_FECHA FROM DUAL;
SELECT USER INTO V_USUARIO FROM DUAL;
can be done with assignments:
V_FECHA := SYSDATE;
V_USUARIO := USER;
though you don't need the variables at all as you can refer to them directly in the insert:
INSERT INTO VENTAS_MENSUALES(PRODUCTO,FECHA,USUARIO)
VALUES (V_PRODUCTO, SYSDATE, USER);
But there is the biggest problem - you are trying to insert into the same table the trigger is against, which will either throw a mutating-table error or, more likely, loop until Oracle kills it.
I suspect you're actually trying to modify the row that is being updated, with the product info from a look-up (though that implies denormalised data?) and the user taking the action. Your initial, erroring, insert statement is only referring to those same rows though, so it's not clear how it should be corrected.
You probably want something more like:
CREATE OR REPLACE TRIGGER TRIGGER_MAYOR
BEFORE INSERT OR UPDATE ON VENTAS_MENSUALES
FOR EACH ROW
BEGIN
SELECT DESCRIPCION INTO :new.PRODUCTO FROM PRODUCTO
WHERE some_column = :new.some_column;
:new.FECHA := SYSDATE;
:new.USUARIO := USER;
END;
If you include the table definition (DDL) and a more realistic insert statement, it may become clearer.

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;

oracle stored procedure using date parameter

Is it possible to use a date parameter for a stored procedure?
for example, date 20171201 I need to execute a case A in a dateparameter.prc
and date 20171202 execute a case B in a dateparameter.prc which is the same procedure above.
I am googling and investigating some books but I still haven't found a solution.
Can anyone know about it?
Thanks
Yes, it is possible.
SQL> set serveroutput on
SQL> create procedure dt_demo(p_d date) as
2 begin
3 dbms_output.put_line('p_d = ' || p_d);
4 end;
5 /
Procedure created
SQL> exec dt_demo(date '2017-12-02');
p_d = 02.12.17
PL/SQL procedure successfully completed
Is it possible to use a date parameter for a stored procedure?
Yes. A simple example that takes a date as an IN date parameter and passes it directly to an OUT date parameter is:
CREATE PROCEDURE your_procedure(
in_value IN DATE,
out_return OUT DATE
)
IS
BEGIN
out_return := in_value;
END;
/
Your procedure is functioning correctly. But
The expression "DATE '2017-12-02'" represents the ISO date standard.
The expression "dbms_output.put_line('p_d = ' || p_d)" represents the regular Oracle date processing, which precedes the ISO specification.
How the date is formatted (displayed) during dbms_ouput converts the date to a string. Since in this case there is an implicit conversion the resulting format is controlled by the NLS_DATA_FORMAT setting. It looks like yours is set to "dd-mm-yy". To see the difference insert/run the following before your exec statement:
alter session set nls_date_format = 'yyyy-mm-dd" ;
Also see Oracle Date Format for Oracle 11g or as appropriate for your version.

Formatting Date Error - Oracle 11g

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'

How to format a Date variable in PLSQL

I am new to PL/SQL and have this question.
I created a procedure with the following specification:
PROCEDURE runschedule (i_RunDate IN DATE)
this i_RunDate comes in a specific format, and I need to change it to this format:
'MM/dd/yyyy hh:mi:ss PM'
I couldn't find how to re-format a Date variable.
You need to use the TO_CHAR function. Here's an example:
SELECT TO_CHAR(CURRENT_TIMESTAMP, 'MM/DD/YYYY HH12:MI:SS AM') FROM dual;
The DATE has not especific format, a DATE is a DATE. When stored in the database column, date values include the time of day in seconds since midnight, and a DATE variable has the same, only that when in some point you show the variable is formatted. PL/SQL can convert the datatype of a value implicitly, for example, can convert the CHAR value '02-JUN-92' to a DATE value.. but I don't recommend you rely on this implicit conversiosn. I always use the explicit conversion.
For more on this topic, you could read this:
http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28370/datatypes.htm#i9118
In your case, if you want to format your DATE to log something, or to show in your UI or wathever in a different format, you need to assig it to a varchar variable as Justin said, something like this:
....
v_generated_run_date DATE;
v_var_date VARCHAR2(30);
BEGIN -- generate sysdate if required
IF (i_RunDate is null)
THEN
v_var_date:=TO_CHAR(sysdate, 'MM/DD/YYYY HH12:MI:SS AM');
ELSE
v_var_date:=TO_CHAR(i_RunDate,'MM/DD/YYYY HH12:MI:SS AM');
END IF;
pkgschedule.createschedule (v_var_date);
commit;
END runschedule;
END
Your createschedule procedure, in this case, will have a varchar2 parameter...

Resources