SQL Case statement for checking a particular date format - sql

I have an Oracle table having col_date with different dates in it, i want to update my table based on below condition:
If col_date column has dates in 'MM/dd/yy' format then change the date to oracle date format as 'dd-MMM-yyyy' else update to null.
Tried below case condition:
select field1,
field2,
case
when Check_Date_Input like to_date(Check_Date_Input,'MM/dd/yy')
then date_format(to_date(Check_Date_Input, 'MM/dd/yy'), 'dd-MMM-yyyy')
else null
end as check_date
from Table
This query updates the date field to null in all case. Please guide to write correct case condition.

An Oracle date does not have specific format. It is stored in some internal format, that you don't really need to worry about. On the other hand, when displaying a date, Oracle builds a string representation of the date, that you are seeing in your output.
By default, the format is defined by nls parameter nls_date_format. You can change it to whatever you like by altering the database setting in your session, or by explicitely using to_char() in your query.
Say you want format dd-mmm-yyyy, then you can either do:
alter session set nls_date_format = 'dd-mm-yyyy';
And then run your query as:
select field1, field2, check_date_input from mytable
The nls setting remains acive for the life time of your session, so every date column will be displayed in that format in your resultsets.
Or, you can use to_char() within the query:
select field1, field2, to_char(check_date_input, 'dd-mm-yyyy') as check_date_input from mytable

Related

How to Update a column value with a pseudo column in SQL

I have one table in oracle 12c db where one column is varchar2 data type but the values are in DATE format. and by some mistake there are two different type of format mixed.
Basically i have to change the format there and make all values similar.
right format is "2018-11-21-02.57.26.00" but some values are like this : "11/21/2018 20:03:10.066414"
We need all values should be like right format. Need to prepare one update statement for this.
I have prepared the select statement like this. Create_TS should be updated as Create_TS_NEW only for those rows where CREATE_TS has '%/%'
I need to know if i can update those rows in table with Pseudo column like Create_TS_NEW
First Try to find out value with slash (/) then convert it into date format.
SELECT
CREATE_TS,
CASE WHEN INSTR(CREATE_TS,'/')>0 THEN TO_DATE(SUBSTR(CREATE_TS,1,19),'MM/DD/YYYY HH24:MI:SS')
ELSE TO_DATE(SUBSTR(CREATE_TS,1,19),'YYYY-MM-DD-HH24-MI-SS') end default_date_format,
to_char(CASE WHEN INSTR(CREATE_TS,'/')>0 THEN TO_DATE(SUBSTR(CREATE_TS,1,19),'MM/DD/YYYY HH24:MI:SS')
ELSE TO_DATE(SUBSTR(CREATE_TS,1,19),'YYYY-MM-DD-HH24-MI-SS') end,'YYYY-MM-DD-HH24-MI-SS') CREATE_TS_new
FROM Table_
Just put derived column in update statement that will enough to update the required format.
Update Table_ set create_ts=
to_char(CASE WHEN INSTR(CREATE_TS,'/')>0 THEN TO_DATE(SUBSTR(CREATE_TS,1,19),'MM/DD/YYYY HH24:MI:SS')
ELSE TO_DATE(SUBSTR(CREATE_TS,1,19),'YYYY-MM-DD-HH24-MI-SS') end,'YYYY-MM-DD-HH24-MI-SS') ;

How to convert date in mm/dd/yyyy format to yyyy-mm-dd hh:mi:ss.mmm

I'm inserting data into a table and before inserting I need to check if data exists.
I have a composite key consisted of two columns of datetime and int.
Before inserting I need to check if the data with the same time and id exists in the table.
The date that user is inserting is in 'mm/dd/yyyy'.
The datetime data in the table looks like this: '2016-01-12 00:00:00.000'.
The id field is int.
So, I have a query:
if not exists(select count(*) from table_1 where MyDate = #myDate and id = #id)
insert into table_1 .....
What is the right way to format the date user sends to match the datetime format in the table?
Check this sqlfiddle about how to use different date formats in your query. Might help you to solve it.
http://www.sqlfiddle.com/#!2/fd0b7/5
I am guessing that the question is about SQL Server, based on the syntax. The issues in the code snippet far transcend date formats.
First, the expression:
if not exists(select count(*) from table_1 where MyDate = #myDate and id = #id)
will never return true, because the subquery always returns one row with one column. If nothing matches, the column contains 0, which does exist.
You intend:
if not exists(select 1 from table_1 where MyDate = #myDate and id = #id)
Second, this check is not necessary if you wisely choose to have the database enforce the uniqueness constraint. So, define a unique index or constraint on the two columns:
create unique index unq_table_1_id_mydate on table_1(id, MyDate);
Now, the database won't let you insert duplicate values and no if is necessary.
Next, I would suggest that you fix the date format at the application layer. YYYY-MM-DD is an ISO standard date format and quite reasonable. However, if you don't want to do that, use convert():
insert into table_1(id, MyDate, .....)
select #id, convert(datetime, #MyDate, 101), . . .
The value in the database looks to be correct stored as a date/time value, so this should work fine.
You can use following line to convert date to required format in SQL server:
select FORMAT(#your_date, 'yyyy-MM-dd HH:mm:ss', 'en-US') from Your_Table

Does the trim function in Oracle have limitations based on the datatype it handles?

I tried selecting records from a table using the query:
select *
from TableA
where trim(DateField)='31-Dec-2015'
which returned 0 rows.
However, leaving put the trim function gave me records matching my where condition. Can't point put the error.
I think you are confusing the trim and trunc functions. You also have data conversion issues. Dates should be compared to dates. By using trim you are forcing oracle to turn the date field into a string.
select * from TableA where trunc(DateField) = to_date('31-Dec-2015','dd-Mon-yyyy');
Better would be:
select *
from TableA
where DateField between to_date('31-Dec-2015','dd-Mon-yyyy')
and to_date('31-Dec-2015 23:59:59', 'dd-Mon-yyyy hh24:mi:ss');

ORA-01843: not a valid month error

I have a column in Oracle DB which is varchar2 data type. Typical value stored in this column is like 06/16/2015 02:14:18 AM.
I am trying to get all records wherein this column is having records after 1st August 2015.
select *
from MYTABLE
where to_date(substr(MYCOLUMN,1,10),'dd-mm-yyyy') > to_date('01-08-2015','dd-mm-yyyy');
But, I am getting ORA-01843. Where am I doing wrong?
Respect the format in your VARCHAR
....where to_date(substr(MYCOLUMN,1,10),'mm/dd/yyyy')
I have a column in Oracle DB which is varchar2 data type. Typical value stored in this column is like 06/16/2015 02:14:18 AM.
The first question is why do you store DATE as string? Using appropriate data type is one of the most important part of database design and performance.
Understand that DATE doesn't have the format you see, it is internally stored in 7 bytes which is Oracle's proprietary format. Storing date as a string to have a fixed format is not recommended.
I would suggest first fix the design so that you don't have to do this overhead activity while comparing dates. In the longer run it will help you.
1. Add a new column as DATE data type.
ALTER TABLE table_name
ADD new_column DATE;
2. Update the new column.
UPDATE table_name
SET new_column = TO_DATE(old_column, 'mm/dd/yyyy hh:mi:ss pm');
3. DROP the old column.
ALTER TABLE table_name
DROP COLUMN old_column;
4. Rename the new column to old column name.
ALTER TABLE table_name
RENAME COLUMN old_name to new_name;
Now, you could compare dates easily:
SELECT * FROM MYTABLE WHERE mycolumn > to_date('01-08-2015','dd-mm-yyyy');
This will also use any regular index on the date column.
From performance point of view:
If you don't fix it now, you will keep facing performance issues. Because the immediate fix of SUBSTR will not let you use any regular index, you need to create a function-based index.
If in your table all values like 06/16/2015 02:14:18 AM then you can use trunc(to_date(MYCOLUMN,'mm/dd/yyyy HH:mi:SS PM'),'dd') against to_date(substr(MYCOLUMN,1,10),'dd-mm-yyyy').

SQL oracle beginner questions

Question1:
Do i have to use to_date while inserting date?
INSERT INTO some_table (date1, date2)
VALUES (to_date('2012-10-24','YYYY-MM-DD'), to_date('2012-10-24','YYYY-MM-DD'));
Or can just insert as string? Will everything be OK this way too? I've tried and it worked.
INSERT INTO some_table (date1, date2)
VALUES ('2012-10-24',2012-10-24');
Question2:
What happens if i won't name columns that i'm inserting into? It works, but my question is if it inserts randomly now or it takes order of columns during creation of table?
INSERT INTO some_table
VALUES ('2012-10-24',2012-10-24');
1 seems to only work with the 'YYYY-MM-DD' format:
http://docs.oracle.com/cd/B28359_01/server.111/b28286/sql_elements003.htm#SQLRF51049 says
You can specify a DATE value as a string literal ... to specify a DATE value as a literal, you must use the Gregorian calendar. You can specify an ANSI literal... The ANSI date literal contains no time portion, and must be specified in the format 'YYYY-MM-DD'.
However, it might work with time if you use the
Alternatively you can specify an Oracle date value... The default date format for an Oracle DATE value is specified by the initialization parameter NLS_DATE_FORMAT.
For question 2, it uses the order at definition of the table. However you have to give values for all columns in that case.
Oracle supports Standard SQL date literals (since 9i).
It's DATE followed by a string with 'yyyy-mm-dd' format
DATE '2014-05-10'
It's much shorter than TO_DATE and it's independent of any NLS settings.
Similar for timestamps:
TIMESTAMP '2014-05-10 09:52:35'
Regarding your 2nd question: It's the order of columns as defined within the CREATE TABLE.
You could even do it like this one:
ALTER SESSION SET NLS_DATE_FORMAT = 'MM:YYYY:DD';
INSERT INTO some_table (date1) VALUES ('05:2014:10');
...but doing it like this is not recommended. Use TO_DATE or DATE Literal, e.g. DATE '2014-05-10' instead. It makes your life easier.