views:

287

answers:

2

Any suggestions on whether fewer check constraints are better, or more? How should they be grouped if at all?

Suppose I have 3 columns which are VARCHAR2(1 BYTE), each of which is a 'T'/'F' flag. I want to add a check constraint to each column specifying that only characters IN ('T', 'F') are allowed.

Should I have 3 separate check constraints, one for each column:

COL_1 IN ('T', 'F')

COL_2 IN ('T', 'F') 

COL_3 IN ('T', 'F')

Or a single check constraint:

COL_1 IN ('T', 'F') AND COL_2 IN ('T', 'F') AND COL_3 IN ('T', 'F')

My thoughts are it is best to keep these three separate, as the columns are logically unrelated to each other. The only case I would have a check constraint that examines more than one column is if there was some relationship between the value in one and the value in another, e.g.:

(PARENT_CNT > 0 AND PRIMARY_PARENT IS NOT NULL) OR (PARENT_CNT = 0 AND PRIMARY_PARENT IS NULL)
+8  A: 

Keep the separate, they are different columns. Also, the error message will display the check constraint name that failed, and you will better know where the problem is. A future developer will be confused why they are all together, or not notice them since they are on a different column.

KM
OMG Ponies
Check constraints can be used by the optimizer too, and the more granular they are, the more often they can be used.
Gary
@OMG Ponies, I only prefer FK codes tables for columns that have many values or non-typical values "S"=shipped, "P"=pending review, etc. For common "Y"es/"N"o or "T"rue/"F"alse only columns I like check constraints instead of FK codes. When using a check constraint, I do make sure the column is named in a way that the value makes sense: HasShipped "Y" or "N".
KM
A: 

I recommend not using a varchar at all. This is not a standard practice for how people store booleans in databases without a boolean data type. I recommend your smallest integer type where 0 = False and non-zero = True. Constraints become trivial to check at this point (even unnecessary).

Addressing criticisms: you should make 3 constraints for debugging and maintenance reasons (better errors, logging). Performance may be slightly lessened on insert and update but no big deal.

marr75
I didn't downvote, but Oracle only has the NUMBER data type. Using `NUMBER(1)` allows for values 0 to 9 iirc. To this day, Oracle doesn't have a boolean data type: http://asktom.oracle.com/pls/asktom/f?p=100:11:0::NO::P11_QUESTION_ID:6263249199595
OMG Ponies
I'm with OMG Ponies. Oracle doesn't have an integer type so your NUMBER(1) will take up 4 bytes of space as opposed to 2 bytes for CHAR(1).
Scott Bailey
Adam Musch
Disagree - a CHAR(1) takes up less space, constraints are just as easy, plus you can often get away with showing it to the user without any fancy decoding - most users will understand a Y/N column, but will be confused by a column of 0s and 1s. And if you have non-English speakers, either way you'll have to do translation anyway, so using a 4-byte number still doesn't make anything easier.
Jeffrey Kemp
Anyway, the -1 is only because this doesn't actually answer the question - which is how to structure the constraint, not about how to store booleans in SQL.
Jeffrey Kemp
@Adam Not sure what you mean by native logic. No PL/SQL developer is going to use "col_1 + col_2 * col_3 = 1" instead of "col_1 = 'T' or col_2 = 'T' and col_3 = 'T'". Guess which case gives more information to the optimizer?
jva
I wish you luck making your byte wide column only a byte wide on the disk or in memory. The operating system definitely doesn't grant this fine grain control over disk storage and probably not over memory either. In fact, for performance reasons, I'm willing to bet a lot of dbases store everything under double-word length as a padded double-word, at least in memory.
marr75