Oracle lưu trữ DATE
s trong bảng sử dụng 7 byte trong đó 2 byte đầu tiên là:
- Thế kỷ + 100
- Năm thế kỷ + 100
Vì vậy, ngày tối đa có thể (về mặt kỹ thuật) được lưu trữ là khi hai byte đó có các giá trị 255
và 199
sẽ cho năm 15599
(Tôi đang bỏ qua rằng về mặt lý thuyết bạn có thể lưu trữ 255
trong byte thứ hai vì điều đó mở ra một đống các vấn đề riêng biệt).
Bạn có thể chuyển đổi một giá trị thô thành một ngày tháng bằng cách sử dụng DBMS_STATS.CONVERT_RAW_VALUE
có nghĩa là chúng ta có thể bỏ qua các phương pháp tạo ngày bình thường và tạo trực tiếp các giá trị byte sẽ được lưu trữ.
Hàm này là một ví dụ về điều đó:
CREATE FUNCTION createDate(
year int,
month int,
day int,
hour int,
minute int,
second int
) RETURN DATE DETERMINISTIC
IS
hex CHAR(14);
d DATE;
BEGIN
hex := TO_CHAR( FLOOR( year / 100 ) + 100, 'fm0X' )
|| TO_CHAR( MOD( year, 100 ) + 100, 'fm0X' )
|| TO_CHAR( month, 'fm0X' )
|| TO_CHAR( day, 'fm0X' )
|| TO_CHAR( hour + 1, 'fm0X' )
|| TO_CHAR( minute + 1, 'fm0X' )
|| TO_CHAR( second + 1, 'fm0X' );
DBMS_OUTPUT.PUT_LINE( hex );
DBMS_STATS.CONVERT_RAW_VALUE( HEXTORAW( hex ), d );
RETURN d;
END;
/
Sau đó, nếu bạn có cột ngày, bạn có thể chèn các giá trị mà bạn thường không được phép chèn:
CREATE TABLE table_name ( date_column DATE );
INSERT INTO table_name ( date_column )
VALUES ( DATE '2019-12-31' + INTERVAL '1:02:03' HOUR TO SECOND );
INSERT INTO table_name ( date_column ) VALUES ( createDate( 15599, 12, 31, 1, 2, 3 ) );
INSERT INTO table_name ( date_column ) VALUES ( createDate( 12017, 2, 21, 0, 0, 0 ) );
TO_CHAR
không hoạt động khi năm vượt quá giới hạn bình thường của một ngày. Để nhận các giá trị được lưu trữ trong bảng, bạn có thể sử dụng DUMP
để lấy một chuỗi chứa các giá trị byte hoặc bạn có thể sử dụng EXTRACT
để nhận các thành phần riêng lẻ.
SELECT DUMP( date_column ),
TO_CHAR( date_column, 'YYYY-MM-DD' ) AS value,
TO_CHAR( EXTRACT( YEAR FROM date_column ), 'fm00000' )
|| '-' || TO_CHAR( EXTRACT( MONTH FROM date_column ), 'fm00' )
|| '-' || TO_CHAR( EXTRACT( DAY FROM date_column ), 'fm00' )
|| ' ' || TO_CHAR( EXTRACT( HOUR FROM CAST( date_column AS TIMESTAMP ) ), 'fm00' )
|| ':' || TO_CHAR( EXTRACT( MINUTE FROM CAST( date_column AS TIMESTAMP ) ), 'fm00' )
|| ':' || TO_CHAR( EXTRACT( SECOND FROM CAST( date_column AS TIMESTAMP ) ), 'fm00' )
AS full_value
FROM table_name;
kết quả đầu ra:
DUMP(DATE_COLUMN) | VALUE | FULL_VALUE :-------------------------------- | :--------- | :------------------- Typ=12 Len=7: 120,119,12,31,2,3,4 | 2019-12-31 | 02019-12-31 01:02:03 Typ=12 Len=7: 255,199,12,31,2,3,4 | 0000-00-00 | 15599-12-31 01:02:03 Typ=12 Len=7: 220,117,2,21,1,1,1 | 0000-00-00 | 12017-02-21 00:00:00
db <> fiddle here