ChatGPT解决这个技术问题 Extra ChatGPT

Boolean Field in Oracle

Yesterday I wanted to add a boolean field to an Oracle table. However, there isn't actually a boolean data type in Oracle. Does anyone here know the best way to simulate a boolean? Googling the subject discovered several approaches

Use an integer and just don't bother assigning anything other than 0 or 1 to it. Use a char field with 'Y' or 'N' as the only two values. Use an enum with the CHECK constraint.

Do experienced Oracle developers know which approach is preferred/canonical?

I wish Oracle had a wall data type so I could smash my head against it when using booleans.

S
Shog9

I found this link useful.

Here is the paragraph highlighting some of the pros/cons of each approach.

The most commonly seen design is to imitate the many Boolean-like flags that Oracle's data dictionary views use, selecting 'Y' for true and 'N' for false. However, to interact correctly with host environments, such as JDBC, OCCI, and other programming environments, it's better to select 0 for false and 1 for true so it can work correctly with the getBoolean and setBoolean functions.

Basically they advocate method number 2, for efficiency's sake, using

values of 0/1 (because of interoperability with JDBC's getBoolean() etc.) with a check constraint

a type of CHAR (because it uses less space than NUMBER).

Their example:

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


I advise against using 'N' and 'Y' since it is language dependent. Anglophones sometimes forget that most of the world does not represent the concept of truth with the letter Y. By contrast, the meaning of 0 and 1 is constant across language barriers.
0 and 1 as boolean values aren't consistent within computer science - shell script type languages tend to have 0 as success, and non-zero as failure, while C type languages tend to have 0 as failure, and non-zero as success.
As boolean values, they are unambigous. Process return codes are not boolean values.
Why was this entire paragraph from the provided link ignored in this answer? "The most commonly seen design is to imitate the many Boolean-like flags that Oracle's data dictionary views use, selecting 'Y' for true and 'N' for false. However, to interact correctly with host environments, such as JDBC, OCCI, and other programming environments, it's better to select 0 for false and 1 for true so it can work correctly with the getBoolean and setBoolean functions." They state that while 'Y/N' is common, using '0/1' to increase compatibility with host environments is recommended.
L
Leigh Riffel

Oracle itself uses Y/N for Boolean values. For completeness it should be noted that pl/sql has a boolean type, it is only tables that do not.

If you are using the field to indicate whether the record needs to be processed or not you might consider using Y and NULL as the values. This makes for a very small (read fast) index that takes very little space.


+1 Good point about the Oracle internal views and tables using Y/N. If Oracle do it that way it must be right! :)
Can you explain how Y and NULL makes a small index compared to Y and N?
NULLs aren't indexed in Oracle, so if your index contains a few Y characters, but mostly NULLs you will have a very small index.
B
Bill the Lizard

To use the least amount of space you should use a CHAR field constrained to 'Y' or 'N'. Oracle doesn't support BOOLEAN, BIT, or TINYINT data types, so CHAR's one byte is as small as you can get.


A
Andrew Spencer

The best option is 0 and 1 (as numbers - another answer suggests 0 and 1 as CHAR for space-efficiency but that's a bit too twisted for me), using NOT NULL and a check constraint to limit contents to those values. (If you need the column to be nullable, then it's not a boolean you're dealing with but an enumeration with three values...)

Advantages of 0/1:

Language independent. 'Y' and 'N' would be fine if everyone used it. But they don't. In France they use 'O' and 'N' (I have seen this with my own eyes). I haven't programmed in Finland to see whether they use 'E' and 'K' there - no doubt they're smarter than that, but you can't be sure.

Congruent with practice in widely-used programming languages (C, C++, Perl, Javascript)

Plays better with the application layer e.g. Hibernate

Leads to more succinct SQL, for example, to find out how many bananas are ready to eat select sum(is_ripe) from bananas instead of select count(*) from bananas where is_ripe = 'Y' or even (yuk) select sum(case is_ripe when 'Y' then 1 else 0) from bananas

Advantages of 'Y'/'N':

Takes up less space than 0/1

It's what Oracle suggests, so might be what some people are more used to

Another poster suggested 'Y'/null for performance gains. If you've proven that you need the performance, then fair enough, but otherwise avoid since it makes querying less natural (some_column is null instead of some_column = 0) and in a left join you'll conflate falseness with nonexistent records.


You find that these days that a lot Booleans are TriState ie true, false and unknown. which fits perfectly with the database null idea. simply because alot of times knowing no answer has been given is vitally important
Yes, true-false-unknown can be required, though if I were picky (which I am), I'd say it shouldn't really be described as a Boolean, because it isn't.
if your going to be that picky then you can make the same argument for every data type. as under strict definition integer, double (i guess i should say double length twos complement floating point), Binary, string, etc. all assume a value is provided but database implementations always add a null value option Boolean isn't any different
true, on a plus note for your method if you configure your number correctly its can also be stored in the same single byte as a char field, which nullifies the size argument against using 0 / 1, i can't find the link currently but storage for a number ranges from 1 - 22 bytes depending on configuration
I suspect the downvotes are due to a legacy viewpoint on choosing the most memory efficient implementation. This day and age memory efficiency is far less of a priority and should be taken into account after usability and compatibility. To anyone who may respond to this comment, I recommend reading up on premature optimization. That is exactly what is occurring by choosing 'Y/N' purely based on memory efficiency. You're losing native compatibility with a set of commonly used frameworks because of that decision.
M
Matthew Watson

Either 1/0 or Y/N with a check constraint on it. ether way is fine. I personally prefer 1/0 as I do alot of work in perl, and it makes it really easy to do perl Boolean operations on database fields.

If you want a really in depth discussion of this question with one of Oracles head honchos, check out what Tom Kyte has to say about this Here


1/0 is said to be "less memory efficient" but...I like it more too (and hibernate apparently requires 1/0 for a boolean)
1/0 is Hibernate's default for a boolean but you can define any custom mapping you like.
@rogerdpack thats because a char field is 1 byte, or 2 bytes for nchar, where as depending how it is defined a Number can be 1 to 22 bytes
E
Erick B

The database I did most of my work on used 'Y' / 'N' as booleans. With that implementation, you can pull off some tricks like:

Count rows that are true: SELECT SUM(CASE WHEN BOOLEAN_FLAG = 'Y' THEN 1 ELSE 0) FROM X When grouping rows, enforce "If one row is true, then all are true" logic: SELECT MAX(BOOLEAN_FLAG) FROM Y Conversely, use MIN to force the grouping false if one row is false.


in fact the examples shown are useful for 0/1 approach too - and, IMHO, quicker.
B
Ben.12

A working example to implement the accepted answer by adding a "Boolean" column to an existing table in an oracle database (using number type):

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))
);

This creates a new column in my_table_name called my_new_boolean_column with default values of 0. The column will not accept NULL values and restricts the accepted values to either 0 or 1.


R
Ryan Ahearn

In our databases we use an enum that ensures we pass it either TRUE or FALSE. If you do it either of the first two ways it is too easy to either start adding new meaning to the integer without going through a proper design, or ending up with that char field having Y, y, N, n, T, t, F, f values and having to remember which section of code uses which table and which version of true it is using.