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

Trailing Zero

Tôi đã có một nhà phát triển hỏi tôi một câu hỏi thú vị gần đây. Anh ấy đang giải quyết một vấn đề trong đó các giá trị số được lưu trữ trong một bảng nhưng khi anh ấy truy vấn bảng đó trong PL / SQL Developer, nó sẽ hiển thị các số 0 ở cuối sau chữ số cuối cùng. Anh ấy tự hỏi liệu điều này có đang góp phần gây ra sự cố mà anh ấy đang cố gắng gỡ lỗi hay không. Nhà phát triển cần biết liệu Oracle có đang lưu trữ những số 0 ở cuối hay không.

Câu trả lời của tôi là Oracle không lưu trữ các số 0 ở cuối. Oracle chỉ lưu trữ số mũ và phần định trị của một số. Oracle không điền vào bên phải giá trị số bằng các số 0. Giờ đây, nhà phát triển biết rằng vấn đề của anh ấy không phải với dữ liệu trong cơ sở dữ liệu mà là với thứ mà nền tảng phát triển của anh ấy đang làm.

Nhưng lời nói của tôi có đúng không? Nhiều lần tôi đã tuyên bố về cách hoạt động nội bộ của Oracle nhưng sau đó phải quay lại và xác thực tuyên bố của mình hoặc chứng minh rằng nó là sai, điều này chắc chắn dẫn đến tuyên bố đúng.

Để kiểm tra tuyên bố của mình, tôi đã tạo một bảng đơn giản và chèn dữ liệu vào đó.

SQL> create table test_tab (val number(38,5));
Table created.
SQL> insert into test_tab values (25);
1 row created.
SQL> insert into test_tab values (25.0);
1 row created.
SQL> insert into test_tab values (25.2);
1 row created.
SQL> insert into test_tab values (25.20);
1 row created.
SQL> commit;
Commit complete.
SQL> select * from test_tab;
VAL
----------
        25
        25
      25.2
      25.2

Trong SQL * Plus, chúng tôi không thấy bất kỳ số 0 ở cuối nào mặc dù tôi đã thêm chúng vào một cách rõ ràng. Các giá trị 25 và 25.0 cũng như 25,2 và 25,20 đều giống nhau. Nhưng có thể đây chỉ là cách SQL * Plus hiển thị các giá trị. Vì vậy, hãy kết xuất khối dữ liệu để xem chính xác cách Oracle đang lưu trữ các giá trị này.

SQL> select file_id,block_id,blocks
2  from dba_extents where segment_name='TEST_TAB';
FILE_ID   BLOCK_ID     BLOCKS
---------- ---------- ----------
6        128          8
SQL> alter system dump datafile 6 block min 128 block max 135;
System altered.

Tôi phải xác định tệp và số khối cho phân đoạn của mình mà tôi đã tạo. Sau đó, tôi đã ra lệnh để kết xuất nội dung của các khối dữ liệu vào một tệp theo dõi. Khi bạn nhìn vào tệp theo dõi, hãy tìm kiếm từ khóa “block_row_dump” và bạn có thể thấy nội dung của các hàng này trong kết xuất bên dưới:

block_row_dump:
tab 0, row 0, @0x1f92
tl: 6 fb: --H-FL-- lb: 0x1  cc: 1
col  0: [ 2]  c1 1a
tab 0, row 1, @0x1f8c
tl: 6 fb: --H-FL-- lb: 0x1  cc: 1
col  0: [ 2]  c1 1a
tab 0, row 2, @0x1f85
tl: 7 fb: --H-FL-- lb: 0x1  cc: 1
col  0: [ 3]  c1 1a 15
tab 0, row 3, @0x1f7e
tl: 7 fb: --H-FL-- lb: 0x1  cc: 1
col  0: [ 3]  c1 1a 15
end_of_block_dump

Chúng ta có thể thấy từ kết xuất khối, giá trị đầu tiên dài 2 byte và bao gồm các ký tự hex “C1 1A”. Hàng thứ hai có cùng các giá trị chính xác! Điều này rất quan trọng vì nó xác minh tuyên bố ban đầu của tôi rằng Oracle không lưu trữ thêm bất kỳ số 0 nào cho hàng thứ hai trong bảng. Nếu có thêm một số 0, độ dài sẽ không phải là 2 byte. Đối với hàng thứ ba và thứ tư, chúng ta có thể thấy các giá trị hex là giống hệt nhau, “C1 1A 15”.

Nhưng hãy đảm bảo rằng các giá trị hex này tương ứng với dữ liệu của chúng tôi. Để làm điều đó, chúng tôi sẽ sử dụng quy trình DBMS_STATS.CONVERT_RAW_VALUE.

SQL> set serveroutput on

SQL> declare

  2  n number;

  3  begin

  4  dbms_stats.convert_raw_value('C11A',n);

  5  dbms_output.put_line(n);

  6  end;

  7  /

25

 

PL/SQL procedure successfully completed.

 

SQL> declare

  2  n number;

  3  begin

  4  dbms_stats.convert_raw_value('C11A15',n);

  5  dbms_output.put_line(n);

  6  end;

  7  /

25.2

 

PL/SQL procedure successfully completed.

Vì vậy, các giá trị hex "C1 1A" là đại diện bên trong (thô) của "25" và "C1 1A 15" là 25,2 như chúng tôi mong đợi.

Đạo lý của câu chuyện này là đôi khi khi bạn nghĩ rằng bạn biết Oracle đang hoạt động như thế nào trong nội bộ, bạn vẫn có thể phải tạo ra một trường hợp thử nghiệm để xác thực các tuyên bố của mình.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách xuất kết quả truy vấn sang tệp .txt khi sử dụng SQLcl (Oracle)

  2. Tạo trình kích hoạt cập nhật một cột trên một bảng khi một cột trong bảng khác được cập nhật

  3. Tạo tệp Excel (.xlsx) bằng PL / SQL

  4. Mệnh đề GIỮA so với <=AND> =

  5. Vì SQL Server không có các gói, các lập trình viên phải làm gì để giải quyết nó?