15

Why does TINYINT(1) work as a boolean? The way I understood the official docs, the (1) should mean it has a display width of 1, so if I store 56 in it, I thought it should print 5. But for some reason it always prints either 1 or 0.

And another case is if I store 56 in an INT(1), then it prints 56 (at least according to SQLFiddle). What's going on here?

vidit
  • 6,293
  • 3
  • 32
  • 50
argoneus
  • 1,097
  • 2
  • 13
  • 24

5 Answers5

22

The (1) in parentheses for a MySQL integer type has nothing to do with the range of values accepted by the data type, or how it is stored. It's only for display.

See also my answer to Types in MySQL: BigInt(20) vs Int(20) etc.

TINYINT is no different from TINYINT(1) or TINYINT(2) or TINYINT(64). It's an 8-bit signed integer data type, and it accepts any 8-bit integer value from -128 to 127.

mysql> create table b (i tinyint(1));

mysql> insert into b values (42);

mysql> select * from b;
+------+
| i    |
+------+
|   42 |
+------+

For convenience, MySQL supports an alias for BOOL, which is replaced immediately by TINYINT(1).

mysql> create table b2 (i bool);

mysql> show create table b2;

CREATE TABLE `b2` (
  `i` tinyint(1) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1

As I said, the use of (1) means almost nothing, it's only a convention so that if you see TINYINT(1) it's reasonable to assume the column is intended to be used as a boolean. But nothing in MySQL prevents you from storing other integer values in it.

If you want a column to accept only 0 or 1, you can use BIT(1):

mysql> create table b3 (i bit(1));

mysql> insert into b3 values (0), (1);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> insert into b3 values (-1);
ERROR 1406 (22001): Data too long for column 'i' at row 1

mysql> insert into b3 values (2);
ERROR 1406 (22001): Data too long for column 'i' at row 1

This doesn't save any space compared to TINYINT though, because the storage for a given column rounds up to the nearest byte.

PS: Despite answer from @samdy1, TINYINT does not store strings '0' or '1' at all, it stores integers 0 or 1, as well as other integers from -128 to 127. There is no need to quote integers in SQL, and I am often puzzled why so many developers do.

Community
  • 1
  • 1
Bill Karwin
  • 538,548
  • 86
  • 673
  • 828
  • What version of MySQL is this? This is not the behavior reported by the OP, by the SQLfiddle linked elsewhere in this q&a, or by ypercube's answer... – pilcrow May 28 '13 at 18:44
  • These code samples are copied from running them on MySQL 5.5.31. Actually it's Percona Server, but there's no difference in data type handling in Percona Server. – Bill Karwin May 28 '13 at 18:47
  • My local instance (MySQL 5.5, not Percona) agrees with your findings. I was wrting an answer in your line and then tested and was really surprised with these results in Fiddle. – ypercubeᵀᴹ May 28 '13 at 18:53
  • JakeFeasel has responded (in [the Heap](http://chat.stackexchange.com/transcript/179?m=9651348#9651348)) that this is related to JBDC. – ypercubeᵀᴹ May 30 '13 at 18:28
  • Okay I just tested MySQL Connector/J 5.1.22 and it does **not** do any such boolean conversions on INSERT or on SELECT. I don't know what JDBC driver Jake is using. – Bill Karwin May 30 '13 at 18:43
9

TINYINT columns can store numbers from -128 to 127.

TINYINT(1) is a bit weird though. It is (perhaps because it is supposed to act as a BOOLEAN datatype), returns only 0 and 1 in some context, while it still keeps the stored (-128 to 127) values.

(Correction: I only see this weird behaviour in SQL-Fiddle and not when accessing MySQL locally so it may well be a SQL-Fiddle quirkiness, possibly related to the quivalence with BOOLEAN) and not a MySQL problem.

See the SQL-Fiddle

CREATE TABLE test
( i TINYINT(1)
) ;

INSERT INTO test 
  (i)
VALUES
  (0),  (1), (6), (120), (-1) ;

Where we get (only in SQL-Fiddle, not if we access MySQL otherwise!):

SELECT i
FROM test ;

  i
-----
  0
  1
  1
  1
  1

but:

SELECT CAST(i AS SIGNED) i2
FROM test ;

  i2
-----
   0
   1
   6
 120
  -1
ypercubeᵀᴹ
  • 113,259
  • 19
  • 174
  • 235
  • Is this documented anywhere that you know of? Current docs on BOOL, TINYINT([M]) and anyINT([M]) very strongly suggest the behavior the OP expected. – pilcrow May 28 '13 at 18:44
  • I see on the SQLfiddle that this works, but I can't reproduce it on my instance of MySQL 5.5.31. Do you know what it takes to get tinyint(1) to behave this way? A SQL mode perhaps? – Bill Karwin May 28 '13 at 18:45
  • @pilcrow, BillKarwin: No idea really. Perhaps it is a quirkiness of SQL-Fiddle and not of MySQL. – ypercubeᵀᴹ May 28 '13 at 18:47
8

This is a mysql Jdbc configuration subject.

You can config mysql jdbc to convert TinyInt(1) to Boolean or Integer through set jdbc url config property "tinyInt1isBit" to "true" (default) or "false".

from: https://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html

Should the driver treat the datatype TINYINT(1) as the BIT type (because the server silently converts BIT -> TINYINT(1) when creating tables)?

Default: true

JianrongChen
  • 156
  • 1
  • 2
3

The engine is smart enough to know that TINYINT(1) and BOOL are the same. However INT(1) only affects the Display Width instead of the underlying storage size. Display width only comes into play when the value is less width then the display width. Then it gets padded.

http://alexander.kirk.at/2007/08/24/what-does-size-in-intsize-of-mysql-mean/

Lance Hudson
  • 151
  • 7
0

As I understand it, TINYINT(1) can only hold '0' or '1' (from own experience).
Thus, one can assume that the '0' or '1' is translated into true or false.

notquiteamonad
  • 1,159
  • 2
  • 12
  • 28
  • 1
    Not quite: http://www.sqlfiddle.com/#!2/0dc1d/5 It only displays as 1, it does not actually store 1. –  May 28 '13 at 18:26
  • Oh, OK, so does it stil return true? – notquiteamonad May 28 '13 at 18:36
  • Well, it's a bit confusing, the thing is it doesn't return false (0), and anything that isn't false (0) counts as true, but not necessary equal to true (1). http://www.sqlfiddle.com/#!2/0dc1d/11. See [the docs](https://dev.mysql.com/doc/refman/5.0/en/numeric-type-overview.html), the examples there are relevant. –  May 28 '13 at 18:40