Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Oracle 10g chấp nhận năm chữ số trong một ngày

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ị 255199 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




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Lỗi khi cố gắng truy xuất văn bản do lỗi ORA-01804

  2. Hỗ trợ Spring JDBC và tập dữ liệu lớn

  3. Làm thế nào để hiển thị kích thước lược đồ Oracle với truy vấn SQL?

  4. SEC_CASE_SENSTIVE_LOGON trong 12c

  5. Thay đổi số ngày Excel thành ngày Oracle