tags:

views:

202

answers:

5

Hi Everyone,

I work as a developer on a small development team, and something has annoyed me to the point where I have decided to act...

Oracle does not support a Bit datatype - or indeed anything else that makes obvious sense in true/false scenarios. Undeterred however, before I joined the team my forebears decided to use char(1) fields instead, using a specific letter to denote yes / true. Unfortunately though, our application is used to by people all over the world, and for reasons which frankly defy all my attempts at understanding, the value used varies through localisation.

Yes, I do know that's totally unnecessary for values in the back-end that the user never sees - however...

I've noticed that this practice seems to be getting carried forward into new development, which strikes me as mad - so I am thinking of proposing Number(1,0) for this instead - 0 being considered false / no, anything else being interpretted as true / yes...

Simple question - can anyone think of a reason this might be a bad idea?

While we're about it, does anyone know why Oracle doesn't support a simple boolean type? Isn't it a GLARING ommission?

Cheers in anticipation,

Martin.

+1  A: 

Number(1) is no better than char(1). Especially if it will be in addition to the existing char(1). That will just add to the confusion.

FWIW, Oracle in internal views (such as USER_TAB_COLUMNS) uses varchar2(3) (YES and NO). Not sure if they are 100% consistent here, though.

Thilo
My reason for thinking of Number(1,0) was that if nothing else a value would have a definite defined meaning. I take your point about whatever we do having to co-exist with the code of the past, but that's unavoidable - and not as undesirable as simply leaving the situation as it currently is...I was also hoping that the numeric nature would be easier for the server to process, and therefore perhaps (negligably) quicker.Would you care to offer a candidate datatype?
Martin Milan
number(1) might be a little smaller on disc space, but except for huge tables consisting almost only of 'boolean' this should be neglectable. Also you always have the options of compression and bitmap indices which might solve some of the space related negative effects.
Jens Schauder
@Jens: Actually, number(1) is bigger. See my answer.
DCookie
Oracle uses, variously, 'Y'/'N', 'YES'/'NO', 'ENABLED'/'DISABLED', and even ' Y'/' N' (see all_tables.cache column), + a few others. Consistency doesn't even get a look in.
thecoop
+2  A: 

I prefer char(1) over number(1), since with some reasonable choice of characters, it is obvious which character has which boolean meaning.

Of course you should fight all the different varations, choose one and ensure it's use by putting check constraints on the columns.

Although it probably is to late in your case, generating the schema from another tool often takes care at least of the consistency issue. I personally prefer hibernate for this purpose, but that is very situation specific.

And of course that is a glaring obmission. To make it worse, PL/SQL has a boolean, but you can't use it in SQL statements.

Jens Schauder
Both this and Thilo's answers are good - but I've accepted this one because of the advice to enforce compliance through check constraints...Seems like the real answer is "Everyone does their own thing, there is no standard..."
Martin Milan
You can also name the column accordingly such as UPDATE_ALLOWED_YN
Gary
+2  A: 

I'm not an English native so I tend to use either 1 and 0 or '1' and '0'. Using 'Y' and 'N' make little sense if you aren't coding in English. Using 'SI' and 'NO' or 'S' and 'N' doesn't look professional (just like naming variables with accented letters). Ones and zeroes, on the contrary, are pretty standard if you've coded in C, PHP or JavaScript. In any case, I always add the appropriate constraint to disallow any other character. Apart from subjective issues, I don't think there're noticeable performance gain in choosing CHAR or NUMBER. I like numbers a little more becausee I don't need to quote them :)

I agree it's a glaring omission but I've read seriously heated discussions on the subject in some Oracle forums; it's a kind of religious issue. Some claim that booleans belong to application data types and have no place in the database core. Honestly, I believe it's one of those We Have Been So Long Without It That We Had Better Say It Was On Purpose things.

By the way, MySQL has a BOOLEAN type but it's a synonym for TINYINT(1) so it eventually equals to 1 and 0; which is fine, because it also has the constants TRUE and FALSE that evaluate to 1 and 0.

Álvaro G. Vicario
I'm tempted to agree with you - and yes, I have done some C / PHP in my past. I definitely prefer numerics, but I'm surprised to find they take more space (see above)
Martin Milan
+2  A: 

Here is an Ask Tom discussion on the topic. Gives an Oracle-centric view on the issue.

As for storage, char(1) is actually a bit (no pun intended) more efficient:

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
DCookie
That's very interesting - and not what I expected.I still personally feel that numerics have more clarity... I read the Ask Tom discussion before seeing your post (Googled around), but I don't agree with his justification from not having a boolean / bit...
Martin Milan
@Martin: See this SO discussion for further enlightenment, paying particular attention to Quassnoi's answer: http://stackoverflow.com/questions/1087210/oracle-number-comparisons/1087873#1087873
DCookie
@Martin: I agree, there's no logical reason to exclude the BOOLEAN type in the database, only pragmatic ones. Oracle is a bit schizophrenic on the issue, since they do have a BOOLEAN type in their PL/SQL language. That alone is the source of a great deal of confusion to Oracle programmers the first time they bump into it.
DCookie
@DCookie - Thanks for that - didn't know they were stored as centesmimal... My background before this job was largely concerned with MS-SQL, and I have to say in many ways I am beginning to miss it!
Martin Milan
+4  A: 

Use a CHAR(1), and a constraint to allow only '1' and '0'.

...

col CHAR(1),
CONSTRAINT cons_atable_col1 CHECK (col1 IN ('1','0'))
Samuel
Now this answer I really like..
Martin Milan
That is what I was going to write after doing some further research on the case. Anyway, here's a link that should help. http://thinkoracle.blogspot.com/2005/07/oracle-boolean.html Furthermore, you can define yourself a user type which would be BIT, for instance, then accepting only those constrainted values. Another useful link: http://download-uk.oracle.com/docs/cd/B19306_01/server.102/b14200/sql_elements001.htm#i45441
Will Marcouiller