Why can't I enter this date into a table using sql? - sql

Structure of the employee table:
Name Null? Type
------------- -------- ------------
EMPLOYEE_ID NOT NULL NUMBER(38)
FIRST_NAME VARCHAR2(50)
LAST_NAME VARCHAR2(50)
EMAIL VARCHAR2(50)
DEPT_ID NUMBER(38)
SALARY NUMBER(38)
COMMISION_PCT FLOAT(126)
HIREDATE DATE
INSERT statement :
insert into employees_table
values (05,'Sophie','Kuchinskey','sophiekuchinskey#yahoo.com',105,5000000,60,'20-sept-1994');
ERROR at line 1:
ORA-01841: (full) year must be between -4713 and +9999, and not be 0

Oracle will do an implicit TO_DATE on non-date literals when inserting them into a DATE column using the value of NLS_DATE_FORMAT as the format mask. If the non-date literal matches this format then it will work (and if it doesn't then it won't) - however, if the NLS_DATE_FORMAT is ever changed then it will immediately break (any be a huge pain to debug as the code that was working won't but no-one will have changed the code).
You can find out your current NLS_DATE_FORMAT with the query:
SELECT VALUE
FROM NLS_SESSION_PARAMETERS
WHERE PARAMETER = 'NLS_DATE_FORMAT';
It is better to explicitly use TO_DATE with the correct format mask or to use an ANSI date literal (i.e. DATE '2014-12-01').
insert into employees_table
values(
05,
'Sophie',
'Kuchinskey',
'sophiekuchinskey#yahoo.com',
105,
5000000,
60,
TO_DATE( '20-sep-1994', 'DD-Mon-YYYY' )
);
Or, using locale/language agnostic ANSI format:
insert into employees_table
values(
05,
'Sophie',
'Kuchinskey',
'sophiekuchinskey#yahoo.com',
105,
5000000,
60,
DATE '1994-09-20'
);

Please convert the date into correct date format
insert into employees_table values(05,'Sophie','Kuchinskey','sophiekuchinskey#yahoo.com',105,5000000,60,to_date('20-sep-1994','dd-Mon-YYYY'));
Also you can't give month as sept . it should be sep.

Related

data type in Oracle

how to resolve this?
INSERT INTO logiciel VALUES ('log1','Oracle 6',13-05-1995,'6.2','UNIX','3000');
INSERT INTO logiciel VALUES ('log1','Oracle 6',13-05-1995,'6.2','UNIX','3000')
*
ERROR at line 1:
ORA-00932: inconsistent datatypes: expected DATE got NUMBER
the error
here's the table
the table
create table logiciel (
nLog varchar2 (5) primary key,
nomLog varchar (20) not null,
dateAchat date,
version varchar2 (7),
typeLog varchar2 (9),
prix number (6,2)
);
Use date literal or TO_DATE function with appropriate format mask. Do not insert strings into date datatype columns, hoping that Oracle will guess format you used.
SQL> -- date literal is always DATE 'yyyy-mm-dd'
SQL> INSERT INTO logiciel (nlog, nomlog, dateachat, version, typelog, prix)
2 VALUES ('log1', 'Oracle 6', date '1995-05-13', '6.2', 'UNIX', '3000');
1 row created.
SQL> -- TO_DATE lets you choose format, but then the format mask must follow it
SQL> INSERT INTO logiciel (nlog, nomlog, dateachat, version, typelog, prix)
2 VALUES ('log2', 'Oracle 6', to_date('13-05-1995', 'dd-mm-yyyy'), '6.2', 'UNIX', '3000');
1 row created.
SQL>
You have to use quotes around your date value as dates are treated as string -
INSERT INTO logiciel VALUES ('log1','Oracle 6','13-05-1995','6.2','UNIX','3000');
But only using string will tell the DB to store it as string not as date. The difference between them is, You can not do any date manipulation on strings. So you have 2 option now.
Use To_Date function with date format -
INSERT INTO logiciel VALUES ('log1','Oracle 6',TO_DATE('13-05-1995', 'DD-MM-YYYY'),'6.2','UNIX','3000');
Use DATE keyword which is supported by ANSI standard but with that, you have to use the date format as 'YYYY-MM-DD'-
INSERT INTO logiciel VALUES ('log1','Oracle 6',DATE '1995-05-13','6.2','UNIX','3000');

Set NLS_DATE_FORMAT in oracle 11g to truncate time if it is not present

I have a SELECT query in PLSQL that contains multiple DATE columns and some of them also include TIME in it. The date and time must be displayed in standard format i.e; DD/MM/YYYY HH:MI:SS AM So before executing the query I set NLS_DATE_FORMAT parameter:
ALTER SESSION SET NLS_DATE_FORMAT = 'DD/MM/YYYY HH:MI:SS AM';
The problem here is that those columns which only have a DATE in it (without TIME) also shows a default time in result set i.e; 12:00:00 AM
Is there a way in oracle to setup NLS_DATE_FORMAT param in way that it truncates default time if it isn't present in DATE filed?
Note that I am aware of methods like TO_CHAR and TRUNC to achieve the desired results but in my case I can't use these because it will affect data sorting in my application.
There is no way to achieve this by NLS_SETTINGS. NLS_DATE_FORMAT specifies the default date format to use with the TO_CHAR and TO_DATE functions and applies to each and every single column. The default value of this parameter is determined by NLS_TERRITORY.
The value of this parameter can be any valid date format mask, and the value must be surrounded by double quotation marks.
Oracle always stores the time, but it will show it as long as the date format specified provides a date/time mask
Example
SQL> create table mytest ( c1 date ) ;
Table created.
SQL> insert into mytest values ( to_date ( '22/07/2020 11:25:00 AM' , 'DD/MM/YYYY HH:MI:SS AM' ) ) ;
1 row created.
SQL> insert into mytest values ( to_date ( '22/07/2020' , 'DD/MM/YYYY' ) ) ;
1 row created.
SQL> select * from mytest ;
C1
---------
22-JUL-20
22-JUL-20
SQL> select value from nls_database_parameters where parameter = 'NLS_DATE_FORMAT' ;
VALUE
--------------------------------------------------------------------------------
DD-MON-RR
SQL> alter session set nls_date_format = 'DD/MM/YYYY HH:MI:SS AM';
Session altered.
SQL> select * from mytest ;
C1
----------------------
22/07/2020 11:25:00 AM
22/07/2020 12:00:00 AM
SQL>
You have to apply some function ( TRUNC or TO_CHAR ) in order to achieve what you want. Oracle always store the time.
Oracle dates (as long as we're talking about actual dates and not just text) always have a time component.
I suspect the confusion arouses because you can feed DATE columns with texts that contain dates but not time. What really happens here is that ANSI date literals and the TO_DATE() function will just store a default value for missing components. In this case, midnight:
create table test (
id int not null,
value date not null,
primary key (id)
);
insert into test (id, value) values (1, date'2020-07-22');
insert into test (id, value) values (2, to_date('2020-07-22', 'YYYY-MM-DD'));
select id, value as default_format, to_char(value, 'YYYY-MM-DD HH24:MI:SS') as custom_format
from test;
(Demo)
If you really need it you can write a custom formatting function that checks if time is midnight and omits it, but of course there's just no way to tell whether the value was the default one or it's part of actual data explicitly entered that way.
This is easily obtained by specifying the the desired date format and NOT relying on nls_date_format. Further you can conditionally format the result yes sort date/time correctly.
with x (date_col) as
( select trunc(sysdate) from dual union all
select sysdate - 1 from dual
)
select
case when to_char(date_col, 'hh24:mi:ss') = '00:00:00'
then to_char(date_col, 'yyyy-mm-dd')
else to_char(date_col, 'yyyy-mm-dd hh:mi:ss am')
end date_col
from x
order by date_col;

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.

Issue using SQLLDR unable to pass in date 'YYYYMMDD' from CVS to oracle DB

Hi I am new to using sqlldr. I am trying to send the data from a csv file into DB.
csv file looks like this employee.dat:
id,code,dNum,name,last,StartDate,EndDate
MA2001,gg,0011,John,Smith,20020127,20020127
I have a control file that I am passing to sqlldr that looks like this:
OPTIONS(skip=1,bindsize=20000000,readsize=20000000,rows=1024)
LOAD DATA
APPEND
INTO TABLE SOMETHING_ADMIN.EMPLOYEE
FIELDS TERMINATED BY ','
TRAILING NULLCOLS
(
"id"
,"code"
,"dNum" FLOAT
,"name"
,"last"
,"StartDate" DATE "YYYYMMDD"
,"EndDate" DATE "YYYYMMDD"
)
When I execute to load I get the following error:
Record 1: Rejected - Error on table Record 1: Rejected - Error on table SOMETHING_ADMIN.EMPLOYEE, column "StartDate".
ORA-01841: (full) year must be between -4713 and +9999, and not be 0
Table definition:
CREATE TABLE "EMPLOYEE" (
"id" VARCHAR2(30 BYTE),
"code" VARCHAR2(10 BYTE),
"dNum" NUMBER(8,0),
"name" VARCHAR2(20 BYTE),
"last" VARCHAR2(20 BYTE),
"StartDate" DATE,
"EndDate" DATE,
);
What am I doing wrong? I know it seems like a simple question but I just cant figure out.
thank you
If you recreate the table (oh, yes - please, avoid enclosing anything into double quotes in Oracle; no luck with that, ever) so that "date" columns are VARCHAR2 (why? So that we'd make sure that they will be loaded, for debugging purposes) and load data, this is what you get:
ID CODE DNUM NAME LAST STARTDATE ENDDATE
------ ---------- ---------- ------- ------- ---------- ----------
ma2001 gg 0 john smith 20020127
See the DNUM and NAME columns? Everything is shifted right, so date value - which was supposed to be stored into the STARTDATE column - now is in ENDDATE, while enddate's value is lost.
Back to the original table:
SQL> desc employee
Name Null? Type
----------------------------------------- -------- --------------
ID VARCHAR2(30)
CODE VARCHAR2(10)
DNUM NUMBER(8)
NAME VARCHAR2(20)
LAST VARCHAR2(20)
STARTDATE DATE
ENDDATE DATE
SQL>
Control file; the only "specification" is left to date format, i.e. remove FLOAT (why did you use it at all?):
OPTIONS(skip=1)
LOAD DATA
infile *
truncate
INTO TABLE EMPLOYEE
FIELDS TERMINATED BY ','
TRAILING NULLCOLS
(
id
,code
,dNum
,name
,last
,StartDate date 'yyyymmdd'
,EndDate date 'yyyymmdd'
)
begindata
id,code,dnum,name,last,startdate,enddate
ma2001,gg,0011,john,smith,20020127,20020127
Loading session & result:
SQL> $sqlldr scott/tiger control=test11.ctl log=test11.log
SQL*Loader: Release 11.2.0.2.0 - Production on ╚et Lis 24 22:07:47 2019
Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.
Commit point reached - logical record count 1
SQL> select * From employee;
ID CODE DNUM NAME LAST STARTDATE ENDDATE
------ ---------- ---------- ------- ------- ---------- ----------
ma2001 gg 11 john smith 27.01.02 27.01.02
Oracle parser is sometimes quite stupid with the errors it returns. I don't think it liked the FLOAT keyword. Removed that and unneeded quotes, and seems to work for me.
OPTIONS(skip=1,bindsize=20000000,readsize=20000000,rows=1024)
LOAD DATA
infile 'test.csv'
APPEND
INTO TABLE EMPLOYEE
FIELDS TERMINATED BY ','
TRAILING NULLCOLS
(
id
,code
,dNum
,name
,last
,StartDate DATE 'YYYYMMDD'
,EndDate DATE 'YYYYMMDD'
)

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';