SQL TO_DATE - for every single date field? - sql

After years of using MySQL, having to move a table over to Oracle SQL (am using SQL Developer). Created the table and now just wanted to check it with a single INSERT statement, getting this:
INSERT INTO table_name
VALUES ('1001','LAWRENCE-INDIANAPOLIS','01-06-02','I8112NP','05DX8105408','2013-06-03','2016-03-11','2018-04-29','2038-01-01','yes','yes','yes','2012-10-25','CCE','7360D33','R8NR6N0','70F63951959F9','2016-03-11')
Error report -
SQL Error: ORA-01861: literal does not match format string
01861. 00000 - "literal does not match format string"
*Cause: Literals in the input must be the same length as literals in
the format string (with the exception of leading whitespace).
If the "FX" modifier has been toggled on, the literal must match exactly,
with no extra whitespace.
*Action: Correct the format string to match the literal.
Do I really have to put a TO_DATE format in front of every single DATE field in the INSERT statement, even though they're already in the proper YYYY-MM-DD format?

Well, you don't have to do it every time, but good practice says that you should instruct Oracle what you have and what you expect of it to do.
It is about NLS settings. If date format is different from one you use, you'll get an error (as you already know it):
SQL> create table test (datum date);
Table created.
SQL> insert into test values ('2013-06-03');
insert into test values ('2013-06-03')
*
ERROR at line 1:
ORA-01861: literal does not match format string
But, if you modify date format so that it matches format you use, everything will be OK:
SQL> alter session set nls_date_format = 'yyyy-mm-dd';
Session altered.
SQL> insert into test values ('2013-06-03');
1 row created.
SQL>
Another option, which doesn't depend on NLS settings, is to use DATE literal. It is always in format YYYY-MM-DD and has to be preceded by the DATE keyword:
SQL> alter session set nls_date_format = 'dd.mm.yyyy';
Session altered.
SQL> insert into test values ('2013-06-03');
insert into test values ('2013-06-03')
*
ERROR at line 1:
ORA-01861: literal does not match format string
SQL> insert into test values (date '2013-06-03');
1 row created.
SQL>
Or, as you found out, use TO_DATE function with the appropriate format mask.

In Oracle, use the date keyword:
INSERT INTO table_name
VALUES ('1001', 'LAWRENCE-INDIANAPOLIS', '01-06-02', 'I8112NP', '05DX8105408',
DATE '2013-06-03', DATE '2016-03-11', DATE '2018-04-29', DATE '2038-01-01', 'yes', 'yes', 'yes', DATE '2012-10-25', 'CCE', '7360D33', 'R8NR6N0', '70F63951959F9', DATE '2016-03-11'
);

The default DATE format used depends on the setting of the NLS_DATE_FORMAT environment var. To find out what this is, use the following query:
SELECT *
FROM V$NLS_PARAMETERS
ORDER BY PARAMETER;
This will dump all of the NLS parameters as they are currently set in your database. As an example, in the database I'm working in right now the query above returns:
NLS_CALENDAR GREGORIAN
NLS_CHARACTERSET US7ASCII
NLS_COMP BINARY
NLS_CURRENCY $
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE AMERICAN
NLS_DUAL_CURRENCY $
NLS_ISO_CURRENCY AMERICA
NLS_LANGUAGE AMERICAN
NLS_LENGTH_SEMANTICS BYTE
NLS_NCHAR_CHARACTERSET AL16UTF16
NLS_NCHAR_CONV_EXCP FALSE
NLS_NUMERIC_CHARACTERS .,
NLS_SORT BINARY
NLS_TERRITORY AMERICA
NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
NLS_TIME_FORMAT HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT HH.MI.SSXFF AM TZR
So on my system, if I wanted to enter a date-as-character string and have Oracle translate it correctly I'd have to enter is as e.g. 24-Apr-18.

Related

Table Column length is 100 but View Column length is 150 in SQL Developer

I am using SQL Developer 19.1.0. and Oracle Database 12c Standard Edition Release 12.1.0.2.0 - 64bit Production.
I have created a View on a Table. In SQL Developer, when I double click the Table it is showing the DATA_TYPE as NVARCHAR2(100 CHAR) for a column but when I double click the VIEW it is showing the DATA_TYPE as NVARCHAR2(150 CHAR).
Similarly, all the NVARCHAR2 columns length in the VIEW is showing 1.5 times that of Table column's length.
What is the reason and how do I fix it?
Edit - Added he following DB Parameters
NLS_RDBMS_VERSION 12.1.0.2.0
NLS_NCHAR_CONV_EXCP FALSE
NLS_LENGTH_SEMANTICS BYTE
NLS_COMP BINARY
NLS_DUAL_CURRENCY $
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
NLS_TIME_TZ_FORMAT HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_FORMAT HH.MI.SSXFF AM
NLS_SORT BINARY
NLS_DATE_LANGUAGE AMERICAN
NLS_DATE_FORMAT DD-MON-RR
NLS_CALENDAR GREGORIAN
NLS_NUMERIC_CHARACTERS .,
NLS_NCHAR_CHARACTERSET UTF8
NLS_CHARACTERSET AL32UTF8
NLS_ISO_CURRENCY AMERICA
NLS_CURRENCY $
NLS_TERRITORY AMERICA
NLS_LANGUAGE AMERICAN
When I user DESCRIBE command to view TABLE and VIEW I get NVARCHAR2(150)

How do I fix ORA-01843: not a valid month?

So at the query level, I have it:
to_char(
(
to_date(
substr(TIMESTAMP, 1, 19),
'yyyy-mm-dd hh24:mi:ss'
)
),
'dd-mon-yyyy hh24:mi:ss'
) as DateTime,
And I've tried looking at a few articles with one most notable:
How to change the date format in Oracle BI Publisher?
I have also tried using:
and trunc(TIMESTAMP) between :FROM_DATE AND :TO_DATE
--and also
and trunc(TIMESTAMP) between to_date(:FROM_DATE, 'yyyy-MM-dd') AND to_date(:TO_DATE, 'yyyy-MM-dd')
While going through structure and XML I noticed my date is in string format:
element name="DATETIME" value="DATETIME" label="DATETIME" dataType="xsd:string" breakOrder="ascending" fieldOrder="3"
So I removed the to_char to get the date format
The error I've been getting is:
java.sql.SQLDataException: ORA-01843: not a valid month
How do I fix this issue?
EDIT:
Format for the column, TIMESTAMP, the format is CHAR(14)
Example of values is like 20200701103038
It runs perfectly in SQL Developer
Well, it is quite a bad and extended practice to store DATES as strings, either using varchar2 or char. Anyway, having say that, I think you have a problem with your settings or the way you are constructing your query:
SQL> alter session set nls_date_format='YYYYMMDDHH24MISS' ;
Session altered.
SQL> select to_date('20200726123722') from dual ;
TO_DATE('20200
--------------
20200726123722
SQL> select sysdate from dual ;
SYSDATE
--------------
20200726124622
Besides, as you said, if your data is stored as YYYYMMDDHHMISS, you are applying the wrong date mask YYYY-MM-DD HH24:MI:SS to that char. I would use CAST to define the field as DATE.
Example
SQL> create table my_test ( c1 char(20) ) ;
Table created.
SQL> insert into my_test values ('20200726123722') ;
1 row created.
SQL> insert into my_test values ('20200725123722') ;
1 row created.
SQL> commit ;
Commit complete.
SQL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';
Session altered.
SQL> select cast(c1 as date) from my_test ;
CAST(C1ASDATE)
-------------------
2020-07-26 12:37:22
2020-07-25 12:37:22
SQL>
Update
If you can't change your NLS Session settings, then you must apply a TO_CHAR to the resulting output. But in your case, you want to operate with dates, so as long as it is a date value you want to operate with, you can forget about the mask.
SQL> col value for a20
SQL> select value from nls_database_parameters where parameter = 'NLS_DATE_FORMAT' ;
VALUE
--------------------
DD-MON-RR
SQL> select cast(to_date('20200725123722','YYYYMMDDHH24MISS') as date) from dual ;
CAST(TO_D
---------
25-JUL-20
SQL> select to_char( cast(to_date('20200725123722','YYYYMMDDHH24MISS') as date) , 'YYYYMMDDHHMISS' ) from dual ;
TO_CHAR(CAST(T
--------------
20200725123722
SQL> select case when cast(to_date('20200725123722','YYYYMMDDHH24MISS') as date) > sysdate
2 then 'FALSE'
3 else
4 'TRUE'
5 end as result from dual ;
RESUL
-----
TRUE
SQL>
So, if you want to compare the date to another date, don't use to_char. If you want to show the value in a specific format, when you have no option to change the settings, then use to_char.
Just to make sure what SYSDATE (I'm going to select) represents:
SQL> alter session set nls_Date_format = 'dd.mm.yyyy';
Session altered.
Today is:
SQL> select sysdate from dual;
SYSDATE
----------
26.07.2020
This is the way to get the error you got: apply wrong format mask to a string which represents a DATE value:
SQL> select to_Date('2020-27-07', 'yyyy-mm-dd') from dual;
select to_Date('2020-27-07', 'yyyy-mm-dd') from dual
*
ERROR at line 1:
ORA-01843: not a valid month
SQL>
How to fix it? Usually, it is hard to fix it if dates are represented as strings. They (strings that represent dates) are like a box of chocolates, you never know what you're gonna get. If there's at least one wrong value, query will fail.
How to find wrong values? You could create a function which returns TRUE (or 1 or whatever you want) if a string you pass to it represents a valid date format. But, if you pass 01/02/03, which is which? Different formats match (e.g. dd/mm/yy, yy/mm/dd, mm/yy/dd ...). Worse cases are 84/25/32 or AB/23/2f. They are all strings, they "match" two characters separated by slash but certainly aren't valid dates, so you can't rely on a simple regular expression.
Shortly, there's no easy nor fast way out of it.

Inserting a TIMESTAMP value in SQL Developer

Hello I'm having a trouble inserting this value in Oracle SQL Developer Version 19.4.0.354.
'2013-01-01 00:00:00.0000'
Here is the value that I want to insert in one of my tables.
I tried DATE and TIMESTAMP data types but they don't work. I also tried altering the sessions and other possible solutions all over the internet.
Column datatype should be TIMESTAMP. Use appropriate format mask in TO_TIMESTAMP function.
SQL> create table test (col timestamp);
Table created.
SQL> insert into test (col) values (to_timestamp('2013-01-01 00:00:00.0000', 'yyyy-mm-dd hh24:mi:ss:ff6'));
1 row created.
What's in there? (alter session is here just to display the result in desired format; it doesn't affect the value stored in that column):
SQL> alter session set nls_timestamp_format = 'dd.mm.yyyy hh24:mi:ss.ff6';
Session altered.
SQL> select * From test;
COL
---------------------------------------------------------------------------
01.01.2013 00:00:00.000000
SQL>
The simplest approach is to use a literal timestamp, so you don't rely on implicit conversion:
select timestamp '2013-01-01 00:00:00.0000' from dual;
You can also use to_timestamp():
select to_timestamp('2013-01-01 00:00:00.0000', 'yyyy-mm-dd hh24:mi:ss:ff4') from dual;
On the other hand, if you really want to work with a string, then you would need to change the nls setting to your own format before:
alter session set nls_timestamp_format = 'yyyy-mm-dd hh24:mi:ss:ff4';
You can then use pass your string value directly in the query, and Oracle will implicitly convert it to the target datatype while inserting.
You have no time component, so I would just use:
date '2013-01-01'
This is the safest syntax (and clearest and standard too!) for providing a date value.
If Oracle wants a timestamp, it will convert this correctly.

SQL - literal does not match format string in INSERT INTO

I've created an empty table--in my website that holds a bunch of tables-- that has the following columns/data types:
NAME -- VARCHAR2
MRN -- NUMBER
DATE_S -- DATE
E -- DATE
DELI -- DATE
WB -- VARCHAR2
ST_ID -- VARCHAR2
COMMENTS --VARCHAR2
EI -- NUMBER
Below is one of almost 800 rows of code I am using to populate the table.
INSERT INTO SANDBOX.W_C VALUES ('S,E',11300033,'2012-02-18 00:00:00','2012-03-01 00:00:00','2013-02-18 00:00:00','N','006i',NULL,NULL);
When I run that piece of code I get the following message: literal does not match format string. What am I doing wrong?
You need to_Date
INSERT INTO SANDBOX.W_C VALUES ('S,E',11300033,
TO_DATE('2012-02-18', 'yyyy-mm-dd'),
TO_DATE('2012-03-01', 'yyyy-mm-dd'),
TO_DATE('2013-02-18', 'yyyy-mm-dd'),'N','006i',NULL,NULL);
When you provide a date as a string, the database uses it's default settings to try to convert the string. The best way to handle this is the use of to_date, as in scaisEdge's answer.
However, you can also change the default date mask using alter session before you run the insert statements:
ALTER SESSION SET NLS_DATE_FORMAT='yyyy-mm-dd hh24:mi:ss';

How to insert a time into sql table?

On Oracle 11g, I ran the following code first:
alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS';
create table table1(mytime timestamp);
Then I wanted to add a row to my table:
insert into table1(mytime)
values(TO_TIMESTAMP('2014-12-24 07:16:11'));
I also tried without TO_TIMESTAMP:
insert into table1(mytime)
values('2014-12-24 07:16:11');
both gave me the same error:
--A * here: ...values('2014...
-- *
ORA-01843: not a valid month
Why?
TO_TIMESTAMP( string1 [, fmt ] ['nlsparam'] ) The optional fmt
specifies the format of char. If you omit fmt, then char must be in
the default format of the TIMESTAMP datatype, which is determined by
the NLS_TIMESTAMP_FORMAT initialization parameter.
Here you can see that it is not nls_date_format but NLS_TIMESTAMP_FORMAT that you have to change.
Use;
alter session set NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
Then try to insert the data.
NOTE
Its always better to use TO_DATE and TO_TIMESTAMP with proper format like
TO_TIMESTAMP ('10-Sep-02 14:10:10.123000', 'DD-Mon-RR HH24:MI:SS.FF')
Or you can use the Date literals
like
TIMESTAMP '1997-01-31 09:26:50.124'
This should've been easily google-able.
But here you go:
insert into table1(mytime)
values(TO_TIMESTAMP('2014-12-24 07:16:11', 'YYYY-MM-DD HH:MI:SS'));