Reputation: 4047
I have created the following table --
CREATE TABLE placed_order
(
bill_number NUMBER(6) NOT NULL,
customer_id NUMBER(6),
order_time TIMESTAMP,
paymentid NUMBER(6),
total_bill_amount NUMBER(10,2),
scheduled_delivery_time TIMESTAMP,
address_id NUMBER(6),
PRIMARY KEY (bill_number),
FOREIGN KEY (customer_id) REFERENCES customer(customer_id),
FOREIGN KEY (paymentid) REFERENCES payment_information(paymentid),
FOREIGN KEY (address_id) REFERENCES delivery_address(address_id)
);
When I insert the following values to the table --
INSERT INTO placed_order
VALUES (123456, 1, '01-Feb-21 12:00:00 AM', 1, 34.56, '03-Feb-21 12:00:00 PM', 1);
The time is stored in the following format --
123456 1 01-FEB-21 12.00.00.000000000 AM 1 34.56 03-FEB-21 12.00.00.000000000 PM 1
This is causing issues when I am trying to run statements to do manipulations on the SQL such as average. For example, even if I want to convert that to a date using to_date --
select (TO_DATE(actual_delivery_time)) from delivery;
I get the following error --
ORA-01830: date format picture ends before converting entire input string
01830. 00000 - "date format picture ends before converting entire input string"
I tried checking the timestamp format in the nls_database_parameters which comes out to the following -- NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM
How can I figure out what the additional zeros are and why are they being appended?
Upvotes: 0
Views: 1198
Reputation: 168232
A TIMESTAMP
is a binary data format consisting of 7-20 bytes (century, year-of-century, month, day, hour, minute, second, up to 6 bytes for fractional seconds and up to 7 bytes for time zone information); it does NOT have a format.
'01-Feb-21 12:00:00 AM'
is NOT a TIMESTAMP
data-type; it is a string-literal and you are relying on an implicit cast from a string to a timestamp. Oracle will do this and your query is effectively:
INSERT INTO placed_order
VALUES (
123456
1,
TO_TIMESTAMP(
'01-Feb-21 12:00:00 AM',
( SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_TIMESTAMP_FORMAT' )
),
1,
34.56,
TO_TIMESTAMP(
'03-Feb-21 12:00:00 PM',
( SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_TIMESTAMP_FORMAT' )
),
1
);
However, if NLS_TIMESTAMP_FORMAT
does not match the format of your string then the conversion will fail.
You should either:
TO_TIMESTAMP( '01-Feb-21 12:00:00 AM', 'DD-MON-RR HH12:MI:SS AM' )
rather than relying on an implicit castTIMESTAMP '2021-02-01 00:00:00'
; orDATE '2021-02-01'
.For example:
INSERT INTO placed_order (
bill_number,
customer_id,
order_time,
paymentid,
total_bill_amount,
scheduled_delivery_time,
address_id
) VALUES (
123456
1,
TIMESTAMP '2021-02-01 00:00:00',
1,
34.56,
TIMESTAMP '2021-02-03 12:00:00',
1
);
TIMESTAMP
value?If you then want to display the timestamp with a format (remember, a TIMESTAMP
is not stored with any format) then you want to use TO_CHAR
to convert it to a string where it can have a format.
If you want to format the TIMESTAMP
as a YYYY-MM-DD
string then use:
SELECT TO_CHAR(actual_delivery_time, 'YYYY-MM-DD') FROM delivery
For example, even if I want to convert that to a date using to_date
TO_DATE
does not convert a TIMESTAMP
to a DATE
; it converts a string to a DATE
. If you want to cast the TIMESTAMP
to a DATE
data-type then use:
SELECT CAST(actual_delivery_time AS DATE) FROM delivery
(Note: A DATE
data-type is also a binary data-type and is not stored with any format; however, the user-interface you are using to access the database may choose to display a date using the NLS_DATE_FORMAT
session parameter.)
I tried checking the timestamp format in the nls_database_parameters which comes out to the following -- NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM
Can anyone please help in figuring out what the additional zeros are and why are they being appended?
You are displaying a binary data-type; the user interface you are using is trying to be helpful and rather than displaying the bytes (which humans may find difficult to interpret) it is implicitly converting the binary data to a formatted string using the NLS_TIMESTAMP_FORMAT
.
Given that your NLS_TIMESTAMP_FORMAT
is DD-MON-RR HH.MI.SSXFF AM
then the FF
format model will display the fractional seconds; in this case your fractional seconds are 0
and it will display that up to the maximum precision of the timestamp.
Change the NLS_TIMESTAMP_FORMAT
and it will change how (some) user interfaces display the TIMESTAMP
(however, it does NOT change how the data is stored).
If you want to change how the data is stored so it does not have fractional seconds then either:
TIMESTAMP
data-type you are using an explicit precision for the fractional seconds and use TIMESTAMP(0)
; orDATE
data-type.Both those data-types will store the value using 7-bytes and will store century, year-of-century, month, day, hour, minute and second. There is little difference between the two; one difference would be that the timestamp would be implicitly formatted using the NLS_TIMESTAMP_FORMAT
and the date using the NLS_DATE_FORMAT
session parameter.
Upvotes: 2