views:

208

answers:

6

I'm using a MSSQL database and would like to create a column that only has 4 possible values. Is there any way to define a 2-bit column? I see the bit datatype and then the next smallest is tinyint which is 1 full byte.

If there is no such field, I'd be interesting in finding out why not.

Thanks.

+3  A: 

What is your concern with field size? The way to implement a field domain should be using a Foreign Key constraint (MSSQL should have that).

friol
You can go ahead and say "MSSQL has that". OF COURSE it has foreign key contraints.
MusiGenesis
+1  A: 

So you're saying that I should just have a foreign key to another table that contains my four values?

I have no serious concern with it. I just don't see the point of giving a full byte to something that only needs 2 bits. I'm more curious as to the reasons why a variable bit-length field doesn't exist.

Mr Grieves
+1  A: 

I am with friol on this.

I would create a lookup table that contains your four possible values, and then link to them via a foreign key.

As for the data type, smallint is as small as you are going to get, SQL Server really isn't designed to hold individual bits of data and manipulate them, but it can be done via Bitwise operators in Binary columns, but even the smallest of those is much larger on disk. The SQL Server Bit column is also unusual as it has 3 potential values (1, 0, and null).

Mitchel Sellers
TinyInt is only 1 byte, and bit is only one bit... Albiet you still take up a whole buyte of disk storage for the first eight bit columns defined in the table...
Charles Bretana
+2  A: 

I don't see the reason for such a field.

It definately cannot be space - that's cheap today, and an economy of 6 bits is really negligible unless you have lots of rows. But in that case it will take up much space anyway, and extra 6 bits per row will again hardly make a difference.

Speed is also not a valid reason. Such bit fields would require additional manipulation to store and retrieve, making the whole process a lot slower than simply dealing with a whole byte.

Lastly, if it's about constraints, then you should use foreign keys or user-defined types (though that would require additional coding in .NET). Although I'd simply use a byte and implement the constraint in my application. Not so nice perhaps, but heck of a lot easier.

Update: Although, yes, an "enum" constraint would be useful in MSSQL. But that's again a little different than simply a 2-bit field.

Vilx-
+1  A: 

Without rehashing what the other gentlemen have said, If you still want to do this, there is no direct way... But you could use two Bit columns,

and then add a computed column that generates the values (0-3) that correspond to the values of the 2 bit columns....

CREATE TABLE [dbo].[testTable](
    [colA] [bit] NOT NULL,
    [colB] [bit] NOT NULL,
    [CalcCol]  AS (case [colA] when (1) then (2) else (0) end+[colB])
) ON [PRIMARY]

if you need a different set of four values then 0-3 just put them into the calculation formula:

CREATE TABLE [dbo].[testTable](
    [colA] [bit] NOT NULL,
    [colB] [bit] NOT NULL,
    [CalcCol]  As 
         (Case ColA 
             When 0 Then Case ColB WHen 0 Then ValueA Else ValueB End
                    Else Case ColB WHen 0 Then ValueC Else ValueD End
             End)
) ON [PRIMARY]

Only issue is that calculated column is not directly "writable" - you'd have to write to the individual bit fields in separate code... like

Update TestTable Set 
  colA = Case When Value In (ValueA, ValueB) Then 0 Else 1 End, 
  colB = Case When Value In (ValueA, ValueC) Then 0 Else 1 End 
Where ...
Charles Bretana
Not a bad idea there, and based on your comment above, this would use 1 byte per row if I am correct (2 bit columns = 1 byte per row min), and the computed item would be done on the fly correct?
Mitchel Sellers
yes - that is exactly correct.. Up to 8 bit fields in a table will use only one byte...
Charles Bretana
A: 

Unless your database is being stored on a floppy disk, I wouldn't sweat it. Take the advice of the rest here and move on with building the rest of the database.

Kevin Fairchild