Showing posts with label ORA-01830. Show all posts
Showing posts with label ORA-01830. Show all posts

Wednesday, September 19, 2007

ORA-01830, Apex and custom date formats

One of the frequent mistakes that one can make in Apex, especially when one is a beginner, is to forget the fact that page items in the session cache are stored as strings.

As a consequence, sometimes you see processes where PL/SQL code does not contain a proper function for converting the values from the displayed format to the required oracle type before storing them into a table or into variable.

Storing numbers and dates as strings brings about some consequences that you must bear in mind when implementing the underlying db procedures, especially if the application is aimed at a multinational public, where numeric and time/date separators can vary with each user.

A classic error message raised in such situations is:
ORA-01830: date format picture ends before converting entire input string
For a generic explanation of this error at the db server level, see my previous posting.

It's easy to explain why it occurs.
Create a page item of type date as a pop-up calendar.
Pick a long date format like "DD-MON-YYYY HH:MI".
Create an after submit page process bound to some button that inserts the page item into a table without explicitly converting the value, something like:
insert into test (date_inserted) values (:P1_DATE);
finally run the page and voilà:
ORA-01830: date format picture ends before converting entire input string
The fact is that Apex is internally using the default NLS_DATE_FORMAT, "DD-MON-RR", whereas the string stored in P1_DATE is in the format specified in the page item attribute.

When you handle P1_DATE as a bind variable you are handling just a string value, not a date value, so if you don't specify an explicit conversion in the insert statement, Oracle is assuming that it is formatted as DD-MON-RR, hence the error message.

However there are situations where Apex is much smarter and there also techniques that allow you to write code that is not bound to a format hard-coded into the page definition, which results in a reduced risk of getting ORA-01830.

Let's examine them.

Forms written using Apex DML processes perform an automatic conversion, basing on the format mask specified in the Tabular Form Element Date Picker Format Mask.



You can spot the underlying NLS_DATE_FORMAT (DD-MON-RR) located in the upper part of this test page.

If you turn off debugging and try to add a row containing a date formatted as DD/MM/YYYY, Apex will perform the required conversion automatically and without writing a line of code.

Note also that as of Apex 3.0, it is possible to define a custom date format mask for a pop-up calendar item and this parameterized value can be set in different ways.

A first way is to define an application substitution string and call it PICK_DATE_FORMAT_MASK then select "Date Picker (use application format mask)" as Date Picker Format Mask. Please note that this applies to both page items and column attributes in reports.

This method is very static and is good for ensuring consistency throughout all the application on all pop-up items defined in the same way. It only need to be defined centrally, in the Shared Components/Application Definition substitution strings.

A more flexibile way is to define an application item called PICK_DATE_FORMAT_MASK.
This will enable a dynamic setting of the date format in contrast with the static value shown earlier. Indeed you can create a page with a LOV based select list where you allow a user to pick the desired format or even write it manually, exactly as it happens in the Application Builder itself. Whatever you decide to with the users, you'll need to initialize the value of the item in some way before using it.

A third way, described rather hastily in the on-line help, is to choose "Date Picker (use item format mask)". This method is the most flexible as the "date picker will take the date format from the Format Mask attribute on the Edit Page Item page".
The first time i read this topic, it sounded rather confusing because it doesn't explain well what's the difference with the method shown earlier, moreover it doesn't mention how to do that in reports.

Let's try to fill out the gap.

First of all the difference lies in the fact that you can use page items to store the date format mask and this means allowing multiple formats at the same time for the same user within the same page (which can sound a rather odd requirement, but it does have sense actually).

Secondly it allows to specify this page item as a substitution string in the Format Mask attribute in the Source section of the Edit Page Item page:



or in the Column Formatting Date Format attribute of the Report Attibutes page:



Please note that in the latter case the attribute Number/Date Format in the Report Attributes page will be initially grayed out. It will become editable as soon as you pick "Date Picker (use item format mask)" in the Date Picker, which is located further down in the page.

Also in the case of the page item, don't forget to specify the default value or initialize the item with a computation.

You can see here the three different methods at work.
In order to achieve a dynamic effect, one could use an AJAX process to update the report after changing the format mask.

As a final note, keep in mind that when defining a default value for a page item of type date picker (like TRUNC(SYSDATE) for instance), which requires also changing the source type from Static Assignment to PL/SQL Expression by the way, requires an explicit conversion because the format mask is applied when picking the value from the pop-up window, not when retrieving the default value. So, instead of writing just TRUNC(SYDATE), you are better off writing TO_CHAR(SYSDATE,:P12_DATE_FORMAT) or whatever is the name of the item holding the date format in your case.

ORA-01830: date format picture ends before converting entire input string

If you are getting this error in Oracle Application Express, see this other topic otherwise, carry on.

This type of error can be easily demonstrated:
select TO_DATE('2007/09/19 10:00', 'YYYY/MM/DD')  date_fmt
from dual;

ORA-01830: date format picture ends before converting entire input string

In this scenario it's very easy to spot the problem, because it's clearly caused by an input string longer than the date format mask (16 char string instead of the expected 10 char string), however it may be less obvious when an implicit conversion is occurring.

for instance:

CREATE TABLE TEST1 (d DATE)
/
ALTER SESSION SET NLS_DATE_FORMAT = 'DD/MM/YYYY'
/
declare
a varchar2(20) := '19/09/2007 12:00:00';
begin
INSERT INTO TEST1 (d) VALUES (a);
end;
/
ORA-01830: date format picture ends before converting entire input string

So, when you get ORA-01830, you must always determine what the current NLS_DATE_FORMAT is and see if there is some implicit conversion going on.

See message translations for ORA-01830 and search additional resources

----------------------------
ORA-01830: Il formato data termina prima di convertire l'intera stringa in input
ORA-01830: la máscara de formato de fecha termina antes de convertir toda la cadena de entrada
ORA-01830: el format de la data no coincideix amb la cadena a convertir que s'ha entrat
ORA-01830: données surnuméraires après la conversion correcte d'une chaîne en entrée
ORA-01830: Datumsformatstruktur endet vor Umwandlung der gesamten Eingabezeichenfolge
ORA-01830: πρότυπο μορφής ημερομηνίας τελειώνει πριν να γίνει μετατροπή όλου του αλφαριθμητικού εισόδου
ORA-01830: datoformatbillede slutter før konvertering af hele inputstrengen
ORA-01830: datumformatmasken slutar före hela inmatningssträngen omvandlats
ORA-01830: datoformatbildet slutter før hele inndatastrengen er konvertert
ORA-01830: päivämäärämuodon kuvain päättyy ennen koko syötemerkkijonon muunnosta
ORA-01830: a dátumformátum véget ért a teljes bemeneti karakterlánc konverziója előtt
ORA-01830: imaginea formatului de dată se termină înaintea conversiei şirului de intrare
ORA-01830: Datumnotatieafbeelding eindigt voordat de gehele invoerstring is geconverteerd.
ORA-01830: a imagem do formato da data termina antes de converter a string de entrada inteira
ORA-01830: imagem de formato de data termina antes de converter toda a cadeia de caracteres
ORA-01830: шаблон формата даты завершается перед преобразованием всей строки ввода
ORA-01830: obraz formátu pro daum končí před převodem celého vstupního řetězce
ORA-01830: zadaný formát dátumu nepostačuje pre úplné konvertovanie vstupného reťazca
ORA-01830: wzorzec formatu daty kończy się przed konwersją całego ciągu wejściowego
ORA-01830: tarih formatı resmi tüm girdi dizesi dönüştürülmeden önce son buldu
ORA-01830: date format picture ends before converting entire input string

yes you can!

Two great ways to help us out with a minimal effort. Click on the Google Plus +1 button above or...
We appreciate your support!

latest articles