2009-08-12 34 views
14

Rõ ràng oracle dường như không phân biệt giữa các chuỗi rỗng và null. Ví dụ.Oracle không phân biệt giữa các giá trị rỗng và các chuỗi rỗng?

Select name from TABLE_A where id=100; 
    ID NAME 
    100 null 

Update TABLE_A set NAME='' where id=100; 
SELECT --> 
    ID NAME 
    100 null 

SELECT length(NAME) FROM TABLE_A WHERE id=100; 
    null 

Tôi không thể nghĩ ra bất kỳ lý do chính đáng tại sao Oracle sẽ được xây dựng để hành xử theo cách này (nó làm điều này trong sqlplus cũng? -I'm truy cập thông qua một giao diện java, bài viết tham chiếu sử dụng một khách hàng php).

Bạn sẽ ít nhất muốn phân biệt 0 độ dài với độ dài không xác định? Đây có phải là một vấn đề được biết đến? Hành vi có chủ ý đối với một số mục đích cụ thể? Một tranh chấp dài hạn trong lý thuyết cơ sở dữ liệu? Đưa cái gì?

(Điều này được thúc đẩy bởi câu trả lời Matt Solnit để this question.)

+0

Câu hỏi này đã được đăng là có liên quan, mặc dù nó không giải quyết được "tại sao": http://stackoverflow.com/questions/1171196/difference-between-varchar-and-varchar2 –

Trả lời

33

Oracle là rất rất rất cũ.

Quay lại 80's khi nó được phát triển (và trước khi có bất kỳ tiêu chuẩn nào) mà họ nghĩ là một ý tưởng hay, và sau đó cách Oracle lưu trữ giá trị của nó, thực sự là vậy.

Sau đây là cách Oracle lưu trữ dữ liệu (lấy từ documentation):

alt text

Không datatype được lưu trữ trong dữ liệu, chỉ có độ dài dữ liệu và dữ liệu riêng của mình.

Nếu NULL xảy ra giữa hai cột có giá trị, cột được lưu trữ dưới dạng cột có nghĩa là một byte có độ dài 0 (thực tế, 0xFF). Trailing NULL s không được lưu trữ.

Vì vậy, để lưu trữ giá trị 'test', Oracle cần lưu trữ 5 byte: 04 74 65 73 74.

Tuy nhiên, để lưu trữ cả chuỗi trống và NULL, Oracle chỉ cần đặt độ dài dữ liệu là 0.

Rất thông minh nếu dữ liệu của bạn được lưu trữ trên 20 Mb ổ đĩa cứng có chi phí 5,000$ mỗi.

Sau đó, khi các tiêu chuẩn xuất hiện, nó không phải là một ý tưởng tốt nữa, nhưng vào thời điểm đó đã có rất nhiều và rất nhiều mã dựa trên NULL'' là giống nhau.

Làm VARCHAR để thực hiện sự khác biệt này sẽ phá vỡ tấn mã.

Để khắc phục điều đó, họ đổi tên VARCHAR-VARCHAR2 (mà không phải là một phần của tiêu chuẩn có), tuyên bố rằng VARCHAR2 sẽ không bao giờ phân biệt giữa một NULL và một chuỗi rỗng và kêu gọi tất cả mọi người sử dụng kiểu dữ liệu này thay thế.

Hiện tại, có thể họ đang chờ người cuối cùng sử dụng cơ sở dữ liệu VARCHAR trong cơ sở Oracle để chết.

+0

Lý do duy nhất là lịch sử? Và không cố định trong 25 năm? Làm thế nào có thể được, cho rằng nó chi phí rất nhiều? ;) –

+2

Chi phí! = Chất lượng. Tôi chưa bao giờ sử dụng Oracle, nhưng hãy kiểm tra Lotus Notes. Phần mềm đó cũng tốn rất nhiều $$$, nhưng ít người nói rằng đó là một ứng dụng chất lượng cao. –

+3

+1 "đang chờ người cuối cùng chết" ... Tôi chỉ có thể chụp ảnh ... –

0

Có vẻ như Oracle đã nói rằng hành vi này có thể thay đổi trong bản phát hành trong tương lai.Khi nào và bản phát hành nào sẽ không được đề cập đến.

Nếu bạn có quyền truy cập vào metalink xem lưu ý: 1.011.340,6 (tiếc vì các hạn chế tôi không thể sao chép nội dung của các lưu ý ở đây)

Nếu bạn không có quyền truy cập vào metalink sau đó nhìn nhìn vào sau từ việc phát hành 10g 2 tài liệu here

0

@Tôi có thể trả lời bạn.

trigger Oracle có thể tham khảo bảng họ đang tạo ra trên:

create table t (id number(10)); 

create or replace trigger t_bir before insert on t for each row 
declare 
    l_id t.id%type; 
begin 
    select id 
    into l_id 
    from t 
    where id = :new.id; 
exception 
    when no_data_found then 
    null; 
end; 
/


SQL> insert into t values (20); 

1 row is created. 


SQL> select * from t; 

     ID 
---------- 
     20 
+0

@tuinstoel: chỉ vì bạn đang sử dụng mệnh đề GIÁ TRỊ Nếu bạn chuyển sang CHỌN CHỌN: SQL> chèn vào t chọn 20 từ kép; chèn vào t chọn 20 từ kép * LRI một t dòng 1: ORA-04091: bảng RWIJK.T là đột biến, kích hoạt/chức năng có thể không nhìn thấy nó ORA-06512: tại "RWIJK.T_BIR", dòng 4 ORA-04088: lỗi trong khi thực hiện kích hoạt 'RWIJK. T_BIR ' –

+0

-------- Tôi biết. – tuinstoel

1

Đó là lý do tại sao những người thông minh như ngày nói rằng bạn KHÔNG BAO GIỜ nên sử dụng null.

(Không, tôi phải được chính xác. Đó là trong thực tế chỉ một duy nhất của hầu hết hàng trăm lý do ông đã đề cập trên đây vài thập kỷ qua để hỗ trợ tuyên bố đó.)

EDIT

Tôi thực sự cũng muốn trả lời câu hỏi này:

"Làm VARCHAR để làm một sự phân biệt như vậy sẽ phá vỡ tấn mã."

Vâng, và chắc chắn, phá vỡ ít nhất tinh thần của tiêu chuẩn bằng cách thay thế "chuỗi rỗng" bằng null trên mỗi lần cập nhật là một điều xấu xa hơn?

(Lưu ý: null không bằng bất kỳ thứ gì, thậm chí không phải chính nó, vì vậy sau khi gán chuỗi rỗng cho cột, oracle sẽ cung cấp cho bạn giá trị trong cột đó KHÔNG giống như giá trị bạn đã nói để xuất hiện ở đó. Wow.)

Các vấn đề liên quan