Như đã lưu ý trong Tham chiếu ngôn ngữ SQL :
Chuyển đổi ngầm định được thực hiện trên cột bảng khi các loại không khớp. Có thể thấy điều này bằng cách truy tìm trong SQL * Plus, với một số dữ liệu giả.
create table t42 (foo varchar2(3 byte));
insert into t42 (foo) values ('10');
insert into t42 (foo) values ('2A');
set autotrace on explain
Điều này hoạt động:
select * from t42 where foo = '10';
FOO
---
10
Execution Plan
----------------------------------------------------------
Plan hash value: 3843907281
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T42 | 1 | 3 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("FOO"='10')
Note
-----
- dynamic sampling used for this statement (level=2)
Nhưng lỗi này:
select * from t42 where foo = 10;
ERROR:
ORA-01722: invalid number
Execution Plan
----------------------------------------------------------
Plan hash value: 3843907281
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T42 | 1 | 3 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TO_NUMBER("FOO")=10)
Lưu ý sự khác biệt trong bộ lọc; filter("FOO"='10')
so với filter(TO_NUMBER("FOO")=10)
. Trong trường hợp thứ hai, so sánh với một số, to_number()
đang được thực hiện đối với mọi hàng trong bảng, kết quả của chuyển đổi đó được so sánh với giá trị cố định. Vì vậy, nếu không thể chuyển đổi bất kỳ giá trị ký tự nào, bạn sẽ nhận được ORA-01722. Hàm đang được áp dụng cũng sẽ ngừng sử dụng một chỉ mục, nếu một chỉ mục hiện diện trên cột đó.
Nơi thú vị là nếu bạn có nhiều hơn một bộ lọc. Oracle có thể đánh giá chúng theo các thứ tự khác nhau vào những thời điểm khác nhau, vì vậy bạn có thể không phải lúc nào cũng nhìn thấy ORA-01722 và đôi khi nó sẽ bật lên. Giả sử bạn có where foo = 10 and bar = 'X'
. Nếu Oracle nghĩ rằng nó có thể lọc ra không phải X
đầu tiên, nó sẽ chỉ áp dụng to_number()
ở bên trái và mẫu nhỏ hơn đó có thể không có giá trị không phải số trong foo
. Nhưng nếu bạn có and bar = 'Y'
, không phải Y
các giá trị có thể bao gồm các số liệu không phải là số, hoặc Oracle có thể lọc trên foo
đầu tiên , tùy thuộc vào mức độ chọn lọc mà nó cho rằng các giá trị.
Đạo đức là không bao giờ lưu trữ thông tin số dưới dạng ký tự.
Tôi đang tìm kiếm một tham chiếu AskTom để sao lưu đạo đức và cái đầu tiên tôi xem thuận tiện đề cập đến tác dụng của "sự thay đổi thứ tự của một vị từ" cũng như nói "không lưu trữ số trong varchar2's".