2010-03-11 22 views
23

tôi làm việc như một nhà phát triển trên một nhóm phát triển nhỏ, và một cái gì đó đã làm phiền tôi đến điểm mà tôi đã quyết định phải hành động ...Oracle thiếu một datatype Bit cho các cột bảng

Oracle không hỗ trợ một Bit datatype - hoặc thực sự bất cứ điều gì khác mà làm cho cảm giác rõ ràng trong các kịch bản đúng/sai. Tuy nhiên, trước khi tôi gia nhập nhóm, tổ tiên của tôi đã quyết định sử dụng các trường char (1) thay vào đó, sử dụng một chữ cái cụ thể để biểu thị có/đúng. Thật không may, ứng dụng của chúng tôi được mọi người trên toàn thế giới sử dụng, và vì những lý do mà thẳng thắn thách thức mọi nỗ lực của tôi trong sự hiểu biết, giá trị được sử dụng thay đổi thông qua nội địa hóa.

Vâng, tôi biết đó là hoàn toàn không cần thiết cho các giá trị trong back-end mà người dùng không bao giờ nhìn thấy - tuy nhiên ...

tôi đã nhận thấy rằng thực hành này có vẻ được việc chuyển vào phát triển mới, điều đó đánh tôi như điên - vì vậy tôi đang nghĩ đến việc đề xuất Số (1.0) cho việc này - 0 được coi là sai/không, bất cứ điều gì khác được hiểu là đúng/có ...

Câu hỏi đơn giản - bất cứ ai có thể nghĩ lý do này có thể là một ý tưởng tồi?

Trong khi chúng ta nói về nó, có ai biết tại sao Oracle không hỗ trợ kiểu boolean đơn giản không? Đó không phải là một sự thiếu hụt GLARING?

Chúc mừng dự đoán,

Martin.

+0

Trong tất cả các khoản dự trữ, Oracle có cung cấp loại BOOL hoặc BOOLEAN (có lẽ chỉ với phiên bản mới nhất ...) không? Tôi thực sự không thể nhớ rõ. Tôi đã không làm Oracle trong hơn hai năm nay. Dù sao, NUMBER (1) là tốt, nó nói những gì nó cần, giống như một BIT - 0 hoặc 1, một số (1) - 0 hoặc 1, sự khác biệt là gì? –

+4

@Will: Số (1, 0) có thể là bất kỳ số chữ số đơn nào (0-9), không chỉ 0 hoặc 1. – Cameron

+0

Có, tất nhiên! Nhưng bạn không kiểm soát được các giá trị cột có thể đặt giá trị? –

Trả lời

10

Tôi thích char (1) trên số (1), vì với một số lựa chọn hợp lý của các nhân vật, rõ ràng là nhân vật nào có ý nghĩa boolean.

Tất nhiên bạn nên chiến đấu với tất cả các biến thể khác nhau, chọn một và đảm bảo sử dụng nó bằng cách đặt ràng buộc kiểm tra trên các cột.

Mặc dù có thể là muộn trong trường hợp của bạn, việc tạo lược đồ từ một công cụ khác thường sẽ chăm sóc ít nhất là vấn đề nhất quán. Cá nhân tôi thích ngủ đông cho mục đích này, nhưng đó là tình hình rất cụ thể.

Và tất nhiên đó là một sự cản trở rõ ràng. Để làm cho nó tồi tệ hơn, PL/SQL có một boolean, nhưng bạn không thể sử dụng nó trong các câu lệnh SQL.

+0

Cả hai câu trả lời này và Thilo đều tốt - nhưng tôi đã chấp nhận câu trả lời này vì lời khuyên để thực thi tuân thủ thông qua các ràng buộc kiểm tra ... Có vẻ như câu trả lời thực là "Mọi người điều của riêng họ, không có tiêu chuẩn ... " –

+0

Bạn cũng có thể đặt tên cho cột tương ứng như UPDATE_ALLOWED_YN –

2

Số (1) không tốt hơn char (1). Đặc biệt là nếu nó sẽ được thêm vào các char hiện có (1). Điều đó sẽ chỉ thêm vào sự nhầm lẫn.

FWIW, Oracle trong chế độ xem nội bộ (như USER_TAB_COLUMNS) sử dụng varchar2 (3) (CÓ và KHÔNG). Tuy nhiên, không chắc chắn chúng có phù hợp 100% hay không.

+0

Lý do của tôi để suy nghĩ về Số (1,0) là nếu không có gì khác một giá trị sẽ có một ý nghĩa xác định rõ ràng. Tôi lấy ý kiến ​​của bạn về bất cứ điều gì chúng tôi phải cùng tồn tại với mã của quá khứ, nhưng điều đó là không thể tránh khỏi - và không phải là không mong muốn vì chỉ đơn giản là rời khỏi tình huống hiện tại ... Tôi cũng hy vọng rằng bản chất số sẽ dễ dàng hơn cho máy chủ để xử lý, và do đó có lẽ (cẩu thả) nhanh hơn. Bạn có muốn cung cấp kiểu dữ liệu ứng cử viên không? –

+1

số (1) có thể là một chút nhỏ hơn trên không gian đĩa, nhưng ngoại trừ các bảng lớn bao gồm gần như chỉ 'boolean' này nên được bỏ qua. Ngoài ra, bạn luôn có các tùy chọn nén và các chỉ mục bitmap có thể giải quyết một số hiệu ứng tiêu cực liên quan đến không gian. –

+2

@Jens: Trên thực tế, số (1) lớn hơn. Xem câu trả lời của tôi. – DCookie

13

Tôi không phải là người gốc bản xứ nên tôi có xu hướng sử dụng 1 và 0 hoặc '1' và '0'. Sử dụng 'Y' và 'N' có ý nghĩa rất ít nếu bạn không viết mã bằng tiếng Anh (có, mã hóa ngôn ngữ bản địa không tồn tại). Sử dụng 'SI' và 'NO' hoặc 'S' và 'N' trông không chuyên nghiệp (giống như các biến đặt tên có các chữ cái có dấu). Ones và zeroes, ngược lại, là khá chuẩn nếu bạn đã mã hóa trong C, PHP hoặc JavaScript. Trong mọi trường hợp, tôi luôn thêm ràng buộc thích hợp để không cho phép bất kỳ ký tự nào khác. Ngoài các vấn đề chủ quan, tôi không nghĩ rằng có được hiệu suất đáng chú ý trong việc chọn CHAR hoặc NUMBER. Tôi thích số nhiều hơn một chút bởi vì tôi không cần phải báo giá chúng :)

Tôi đồng ý đó là một thiếu sót rõ ràng nhưng tôi đã đọc các cuộc thảo luận nghiêm túc về chủ đề này trong một số diễn đàn của Oracle; đó là một vấn đề tôn giáo. Một số cho rằng boolean thuộc về các kiểu dữ liệu ứng dụng và không có vị trí nào trong lõi cơ sở dữ liệu.Thành thật mà nói, tôi tin rằng đó là một trong những người chúng ta đã quá lâu mà không có nó mà chúng tôi đã tốt hơn nói nó đã được trên mục đích điều.

Nhân tiện, MySQL có kiểu BOOLEAN nhưng nó là một từ đồng nghĩa với TINYINT (1) sao cho nó cuối cùng bằng 1 và 0; đó là tốt, bởi vì nó cũng có hằng số TRUE và FALSE đánh giá 1 và 0.

+0

Tôi bị cám dỗ đồng ý với bạn - và có, tôi đã thực hiện một số C/PHP trong quá khứ của tôi. Tôi chắc chắn thích số học, nhưng tôi ngạc nhiên khi thấy rằng họ chiếm nhiều không gian hơn (xem ở trên) –

+5

+1 cho "Chúng ta có-được-quá-lâu-không-nó-điều-chúng-có-tốt hơn-nói-nó -Was-On-Purpose "Chúng ta nên đồng xu cụm từ đó: WHBSLWITWHBSIWOP. – Baodad

8

Đây là một cuộc thảo luận Ask Tom về chủ đề. Cung cấp chế độ xem trung tâm của Oracle về vấn đề này.

Đối với lưu trữ, char (1) thực sự là một chút (không ý định chơi chữ) hiệu quả hơn:

SQL> CREATE TABLE xx (c CHAR(1), n NUMBER); 

Table created 

SQL> insert into xx values('T', 1); 

1 row inserted 

SQL> select dump(c), dump(n) from xx; 

DUMP(C)    DUMP(N) 
------------------- ------------- 
Typ=96 Len=1: 84 Typ=2 Len=2: 193,2 
+3

Điều đó rất thú vị - và không phải những gì tôi mong đợi. Cá nhân tôi vẫn cảm thấy rằng số liệu rõ ràng hơn ... Tôi đã đọc cuộc thảo luận Ask Tom trước khi xem bài đăng của bạn (Googled around), nhưng tôi không đồng ý với lý do của mình không có boolean/bit ... –

+1

@ Martin: Xem cuộc thảo luận SO này để có thêm sự giác ngộ, đặc biệt chú ý đến câu trả lời của Quassnoi: http://stackoverflow.com/questions/1087210/oracle-number-comparisons/1087873#1087873 – DCookie

+4

@Martin: Tôi đồng ý, không có lý do hợp lý để loại trừ kiểu BOOLEAN trong cơ sở dữ liệu, chỉ có những cái thực dụng. Oracle là một chút tâm thần phân liệt về vấn đề này, vì chúng có một kiểu BOOLEAN trong ngôn ngữ PL/SQL của chúng. Điều đó một mình là nguồn gốc của rất nhiều sự nhầm lẫn với các lập trình viên Oracle lần đầu tiên họ va vào nó. – DCookie

23

Sử dụng một CHAR (1), và một hạn chế chỉ cho phép '1' và '0 '.

...

col CHAR(1), 
CONSTRAINT cons_atable_col1 CHECK (col1 IN ('1','0')) 
+0

Bây giờ câu trả lời này tôi thực sự thích .. –

+0

Đó là những gì tôi sẽ viết sau khi thực hiện một số nghiên cứu thêm về vụ việc. Dù sao, đây là một liên kết mà nên giúp đỡ. http://thinkoracle.blogspot.com/2005/07/oracle-boolean.html Hơn nữa, bạn có thể tự định nghĩa một kiểu người dùng sẽ là BIT, sau đó chỉ chấp nhận các giá trị ràng buộc đó. Một liên kết hữu ích khác: http://download-uk.oracle.com/docs/cd/B19306_01/server.102/b14200/sql_elements001.htm#i45441 –

+0

Đừng quên "Default 0 Not Null", nếu cần. Tôi đã kiểm tra sự cần thiết - để tránh chèn null –

0

Câu hỏi đặt ra là cũ nhưng cho đến phiên bản mới nhất của oracle được sử dụng nó vẫn là một câu hỏi hợp lệ.

Tôi sẽ giải quyết vấn đề theo cách này: Tạo bảng chứa các giá trị có thể cho văn bản hiển thị đúng/sai cộng với bản địa hóa hiển thị f.e. T $ KEYWORDS ITEMNO ITEMTEXT ITEMTEXT_DE ITEMTEXT_FE ... 0 False Falsch 1 Đúng Wahr

Thay vì True/False này cũng có thể được lựa chọn, Chưa chọn vv

Và sau đó thêm một chìa khóa foreigh vào cột của bạn tới bảng này. Bằng cách đó bạn chỉ có các giá trị hợp lệ và chúng không thay đổi với bản địa hóa.

Imho giải pháp khác tốt là sử dụng ràng buộc kiểm tra trên cột dữ liệu của bạn. Điều này ofc không hoạt động nếu giá trị của bạn có thể khác nhau trong cùng một cơ sở dữ liệu/cột tùy thuộc vào nội địa hóa của khách hàng.

alter table tblLocations add flag number CONSTRAINT <constraintname> CHECK (flag IN (1,0));

-1

https://docs.oracle.com/cd/E17952_01/refman-5.5-en/char.html enter image description here

Như DCookie nói, char (1) là hiệu quả hơn. Vì VARCHAR2 (VARCHAR) trống chứa 1 byte, nhưng khi chúng tôi lưu trữ 1 ký tự thì trống 1 byte size + với ký tự 1 byte size -> 2 byte cần lưu 1 ký tự trong varchar

0

Oracle sử dụng nội bộ "bit" (không phải là một kiểu dữ liệu cho mỗi se) trong các khung nhìn Data Dictionary khác nhau.

Ví dụ, DBA_USERS xem có:

.. 
     , DECODE (BITAND (u.spare1, 128), 128, 'YES', 'NO') 
.. 
     , DECODE (BITAND (u.spare1, 256), 256, 'Y', 'N') 
.. 

trong đó cho thấy một cách để workaround này theo một cách. Nếu bạn không phải sửa đổi các bit "boolean" thường xuyên, bạn có thể sử dụng cùng một cách tiếp cận mà Oracle đã có từ Oracle 6 (ít nhất). Tạo một bảng có một cột NUMBER và một VIEW trên đầu trang mà ẩn sự phức tạp của các thao tác BITAND.

ps.Một lưu ý phụ, Oracle JDBC có một kiểu dữ liệu "Bit" https://docs.oracle.com/cd/E16338_01/appdev.112/e13995/oracle/jdbc/OracleTypes.html#BIT cũng như bạn đã biết PL/SQL có Boolean. Mặc dù nó có thể không giúp bạn nhiều. Xem cách tiếp cận BITAND ở trên nếu nó bao gồm trường hợp của bạn.

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