Trường Boolean trong Oracle


145

Hôm qua tôi muốn thêm một trường boolean vào bảng Oracle. Tuy nhiên, thực tế không có kiểu dữ liệu boolean trong Oracle. Có ai ở đây biết cách tốt nhất để mô phỏng một boolean? Googling chủ đề phát hiện ra một số cách tiếp cận

  1. Sử dụng một số nguyên và chỉ cần không bận tâm gán bất cứ thứ gì ngoài 0 hoặc 1 cho nó.

  2. Sử dụng trường char với 'Y' hoặc 'N' làm hai giá trị duy nhất.

  3. Sử dụng một enum với ràng buộc KIỂM TRA.

Các nhà phát triển Oracle có kinh nghiệm có biết cách tiếp cận nào được ưa thích / hợp quy không?


195
Tôi ước Oracle có wallkiểu dữ liệu để tôi có thể đập đầu vào nó khi sử dụng booleans.
Greg

Câu trả lời:


82

Tôi thấy liên kết này hữu ích.

Dưới đây là đoạn nhấn mạnh một số ưu / nhược điểm của từng phương pháp.

Thiết kế thường thấy nhất là bắt chước nhiều cờ giống Boolean mà các lượt xem từ điển dữ liệu của Oracle sử dụng, chọn 'Y' cho true và 'N' cho false. Tuy nhiên, để tương tác chính xác với các môi trường máy chủ, chẳng hạn như JDBC, OCCI và các môi trường lập trình khác, tốt hơn là chọn 0 cho false và 1 cho đúng để nó có thể hoạt động chính xác với các hàm getBoolean và setBoolean.

Về cơ bản, họ ủng hộ phương pháp số 2, vì mục đích hiệu quả, sử dụng

  • các giá trị 0/1 (vì khả năng tương tác với JDBC, getBoolean()v.v.) với ràng buộc kiểm tra
  • một loại CHAR (vì nó sử dụng ít không gian hơn SỐ).

Ví dụ của họ:

create table tbool (bool char check (bool in (0,1));
insert into tbool values(0);
insert into tbool values(1);`

31
Tôi khuyên bạn không nên sử dụng 'N' và 'Y' vì nó phụ thuộc vào ngôn ngữ. Anglophones đôi khi quên rằng hầu hết thế giới không đại diện cho khái niệm sự thật với chữ Y. Ngược lại, ý nghĩa của 0 và 1 là không đổi qua các rào cản ngôn ngữ.
Andrew Spencer

7
0 và 1 là các giá trị boolean không nhất quán trong khoa học máy tính - các ngôn ngữ loại kịch bản lệnh shell có xu hướng 0 thành công và không bằng 0 là thất bại, trong khi các ngôn ngữ loại C có xu hướng 0 là thất bại và không bằng 0 là thành công.
Phil

41
Là giá trị boolean , chúng không rõ ràng. Mã trả về quá trình không phải là giá trị boolean.
Andrew Spencer

13
Tại sao toàn bộ đoạn này từ liên kết được cung cấp bị bỏ qua trong câu trả lời này? "Thiết kế thường thấy nhất là bắt chước nhiều cờ giống Boolean mà các chế độ xem từ điển dữ liệu của Oracle sử dụng, chọn 'Y' cho đúng và 'N' cho sai. Tuy nhiên, để tương tác chính xác với các môi trường máy chủ, như JDBC, OCCI, và các môi trường lập trình khác, tốt hơn là chọn 0 cho false và 1 cho true để nó có thể hoạt động chính xác với các hàm getBoolean và setBoolean. " Họ tuyên bố rằng mặc dù 'Y / N' là phổ biến, nên sử dụng '0/1' để tăng khả năng tương thích với môi trường máy chủ.
justin.hughey

28

Bản thân Oracle sử dụng Y / N cho các giá trị Boolean. Để đầy đủ, cần lưu ý rằng pl / sql có kiểu boolean, nó chỉ là các bảng không có.

Nếu bạn đang sử dụng trường để cho biết liệu bản ghi có cần được xử lý hay không, bạn có thể xem xét sử dụng Y và NULL làm giá trị. Điều này làm cho một chỉ số rất nhỏ (đọc nhanh) chiếm rất ít không gian.


7
+1 Điểm hay về các chế độ xem và bảng nội bộ của Oracle bằng Y / N. Nếu Oracle làm theo cách đó thì phải đúng! :)
Jeffrey Kemp

Bạn có thể giải thích làm thế nào Y và NULL tạo ra một chỉ số nhỏ so với Y và N không?
styfle

6
Các NULL không được lập chỉ mục trong Oracle, vì vậy nếu chỉ mục của bạn chứa một vài ký tự Y, nhưng chủ yếu là các NULL, bạn sẽ có một chỉ mục rất nhỏ.
Leigh Riffel

25

Để sử dụng ít dung lượng nhất, bạn nên sử dụng trường CHAR bị ràng buộc thành 'Y' hoặc 'N'. Oracle không hỗ trợ các kiểu dữ liệu BOOLESE, BIT hoặc TINYINT, do đó, một byte của CHAR nhỏ như bạn có thể nhận được.


19

Tùy chọn tốt nhất là 0 và 1 (dưới dạng số - một câu trả lời khác cho thấy 0 và 1 là CHAR cho hiệu quả không gian nhưng điều đó hơi quá đối với tôi), sử dụng KHÔNG NULL và ràng buộc kiểm tra để giới hạn nội dung cho các giá trị đó. (Nếu bạn cần cột là null, thì đó không phải là một boolean mà bạn đang xử lý mà là một phép liệt kê với ba giá trị ...)

Ưu điểm của 0/1:

  • Ngôn ngữ độc lập. 'Y' và 'N' sẽ ổn nếu mọi người sử dụng nó. Nhưng họ không. Ở Pháp, họ sử dụng 'O' và 'N' (Tôi đã nhìn thấy điều này bằng chính mắt mình). Tôi chưa lập trình ở Phần Lan để xem họ có sử dụng 'E' và 'K' ở đó không - chắc chắn họ thông minh hơn thế, nhưng bạn không chắc chắn.
  • Phù hợp với thực hành trong các ngôn ngữ lập trình được sử dụng rộng rãi (C, C ++, Perl, Javascript)
  • Chơi tốt hơn với lớp ứng dụng, ví dụ như Hibernate
  • Dẫn đến SQL ngắn gọn hơn, ví dụ, để tìm hiểu có bao nhiêu quả chuối đã sẵn sàng để ăn select sum(is_ripe) from bananasthay vì select count(*) from bananas where is_ripe = 'Y'hoặc thậm chí (yuk)select sum(case is_ripe when 'Y' then 1 else 0) from bananas

Ưu điểm của 'Y' / 'N':

  • Chiếm ít không gian hơn 0/1
  • Đó là những gì Oracle gợi ý, vì vậy có thể là những gì một số người đã quen với

Một poster khác đề xuất 'Y' / null để tăng hiệu suất. Nếu bạn đã chứng minh rằng bạn cần hiệu suất, thì đủ công bằng, nhưng nếu không thì vì nó làm cho việc truy vấn trở nên ít tự nhiên hơn ( some_column is nullthay vì some_column = 0) và trong một liên kết bên trái, bạn sẽ kết luận sai với các bản ghi không tồn tại.


3
Bạn thấy rằng những ngày này có rất nhiều Booleans là TriState tức là đúng, sai và chưa biết. phù hợp hoàn hảo với ý tưởng null cơ sở dữ liệu. đơn giản vì rất nhiều lần không biết câu trả lời nào được đưa ra là cực kỳ quan trọng
MikeT

1
Vâng, đúng-sai-không xác định có thể được yêu cầu, mặc dù nếu tôi kén chọn (tôi là vậy), tôi sẽ nói rằng nó không thực sự được mô tả như là một Boolean, bởi vì nó không phải là.
Andrew Spencer

2
nếu bạn sẽ khó tính như vậy thì bạn có thể đưa ra lập luận tương tự cho mọi loại dữ liệu. như theo định nghĩa số nguyên nghiêm ngặt, đôi (tôi đoán tôi nên nói đôi twos dài bổ sung cho dấu chấm động), nhị phân, chuỗi, vv tất cả giả định một giá trị được cung cấp nhưng việc triển khai cơ sở dữ liệu luôn luôn thêm một lựa chọn giá trị null Boolean không phải là bất kỳ khác nhau
MikeT

1
đúng, trên một lưu ý cộng cho phương thức của bạn nếu bạn định cấu hình chính xác số của mình, nó cũng có thể được lưu trữ trong cùng một byte với trường char, điều này vô hiệu hóa đối số kích thước so với sử dụng 0/1, hiện tại tôi không thể tìm thấy liên kết nhưng lưu trữ cho một số phạm vi từ 1 - 22 byte tùy thuộc vào cấu hình
MikeT

4
Tôi nghi ngờ các downvote là do quan điểm kế thừa về việc chọn triển khai hiệu quả bộ nhớ nhất. Hiệu quả bộ nhớ ngày và tuổi này ít được ưu tiên hơn nhiều và nên được tính đến sau khi sử dụng và tương thích. Đối với bất cứ ai có thể trả lời bình luận này, tôi khuyên bạn nên đọc về tối ưu hóa sớm. Đó chính xác là những gì đang xảy ra bằng cách chọn 'Y / N' hoàn toàn dựa trên hiệu quả bộ nhớ. Bạn đang mất khả năng tương thích tự nhiên với một tập hợp các khung thường được sử dụng vì quyết định đó.
justin.hughey

5

1/0 hoặc Y / N với ràng buộc kiểm tra trên đó. cách ether là tốt. Cá nhân tôi thích 1/0 vì tôi làm rất nhiều công việc trong perl và nó thực sự dễ dàng thực hiện các thao tác Boolean trên các trường cơ sở dữ liệu.

Nếu bạn muốn có một cuộc thảo luận thực sự sâu sắc về câu hỏi này với một trong những honchos đầu của Oracles, hãy xem Tom Kyte nói gì về điều này Tại đây


1/0 được cho là "ít bộ nhớ hiệu quả hơn" nhưng ... tôi cũng thích nó hơn (và ngủ đông rõ ràng cần 1/0 cho một boolean)
rogerdpack

1/0 là mặc định của Hibernate cho boolean nhưng bạn có thể xác định bất kỳ ánh xạ tùy chỉnh nào bạn muốn.
Andrew Spencer

@rogerdpack đó là vì một trường char là 1 byte hoặc 2 byte cho nchar, trong đó tùy thuộc vào cách xác định nó, Số có thể là 1 đến 22 byte
MikeT

4

Cơ sở dữ liệu tôi đã thực hiện hầu hết các công việc của mình về việc sử dụng 'Y' / 'N' dưới dạng booleans. Với việc thực hiện đó, bạn có thể rút ra một số thủ thuật như:

  1. Đếm các hàng là đúng:
    CHỌN SUM (TRƯỜNG HỢP KHI BOOLESE_FLAG = 'Y' THÌ 1 ELSE 0) TỪ X

  2. Khi nhóm các hàng, thực thi logic "Nếu một hàng là đúng, thì tất cả đều đúng":
    CHỌN MAX (BOOLESE_FLAG) TỪ Y
    Ngược lại, sử dụng MIN để buộc nhóm sai nếu một hàng sai.


4
trong thực tế, các ví dụ hiển thị cũng hữu ích cho cách tiếp cận 0/1 - và, IMHO, nhanh hơn.
igorsantos07

2

Một ví dụ hoạt động để thực hiện câu trả lời được chấp nhận bằng cách thêm cột "Boolean" vào bảng hiện có trong cơ sở dữ liệu orory (sử dụng numberloại):

ALTER TABLE my_table_name ADD (
my_new_boolean_column number(1) DEFAULT 0 NOT NULL
CONSTRAINT my_new_boolean_column CHECK (my_new_boolean_column in (1,0))
);

Điều này tạo ra một cột mới my_table_nameđược gọi my_new_boolean_columnvới các giá trị mặc định là 0. Cột sẽ không chấp nhận NULLcác giá trị và giới hạn các giá trị được chấp nhận ở một trong hai 0hoặc 1.


1

Trong cơ sở dữ liệu của chúng tôi, chúng tôi sử dụng một enum đảm bảo chúng tôi vượt qua nó TRUE hoặc FALSE. Nếu bạn thực hiện một trong hai cách đầu tiên thì quá dễ dàng để bắt đầu thêm ý nghĩa mới vào số nguyên mà không thông qua một thiết kế phù hợp hoặc kết thúc với trường char có Y, y, N, n, T, t, Giá trị F, f và phải nhớ phần nào của mã sử dụng bảng nào và phiên bản đúng của nó đang sử dụng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.