SQLite is not weakly typed!

September 23, 2024

One of the things you’ll often hear about SQLite is that it’s "weakly typed."

But let me tell you: SQLite isn’t weakly typed—it’s flexibly typed. Big difference!

In SQLite, the column types you define are more like suggestions. You can say a column is for integers, but SQLite will allow other types to slip in there unless you’ve set it to be strict.

(Prefer to watch instead of read? Check out the video version of this article on YouTube: SQLite is not weakly typed!)

Storing multiple types in a column

Let’s take a look at a non-strict table in action. (NB: non-strict is the default table type.)

Say we create a table, insert an integer into it, and then check the type of that column. SQLite will store and return it as an integer:

CREATE TABLE types (n INTEGER);
INSERT INTO types VALUES (1);
 
SELECT n, TYPEOF(n) FROM types;
 
-- | n | typeof(n) |
-- | -- | --------- |
-- | 1 | integer |
Code highlighting powered by torchlight.dev (A service I created!)

What happens if we insert a string into that same column? Let’s give it a try:

INSERT INTO types VALUES ('hello');
 
SELECT n, TYPEOF(n) FROM types;
 
-- | n | typeof(n) |
-- | ------ | --------- |
-- | 1 | integer |
-- | hello | text |

We’ve just added a text value into a column we suggested was for integers! SQLite’s flexible typing lets you put anything in a traditional table.

Want to learn SQLite?
I teach a full video course on SQLite! Learn everything you need to use SQLite in production at HighPerformanceSQLite.com.

The interesting thing is that when you insert a value, if SQLite can convert the input that you give it into the type suggested for that column (i.e. INTEGER in this case) without losing data, then it will do so. If it can't, it will store the value as is and will not convert it to the suggested type. Look at what happens when we insert a floating point number into the column:

INSERT INTO types VALUES (1.0);
INSERT INTO types VALUES (1.1);
 
SELECT n, TYPEOF(n) FROM types;
 
-- | n | typeof(n) |
-- | ----- | --------- |
-- | 1 | integer |
-- | hello | text |
-- | 1 | integer |
-- | 1.1 | real |

1.0 is stored as an integer because it can be converted to an integer without losing data. 1.1 is stored as a real because it can't be converted to an integer without losing data.

Why flexible typing can be a good thing

Is this behavior good or bad? Well... it depends. If flexibility is what you want, it’s fantastic. If you’re not expecting it, it might catch you off guard. But there are some situations where SQLite’s flexibility really shines.

Imagine you’re building a key-value store where the value could be a number, a string, or even a blob. SQLite’s flexible typing makes that easy. Or say you’re working with CSV files—people don’t always follow strict database rules when they create CSVs, so having a system that’s forgiving can save you a lot of headaches.

It’s also great for scenarios like user settings, where some settings are integers and others are strings. Flexible typing gives you the ability to store mixed data types in the same column, no problem.

What if you want strict typing?

What if you hate the idea of flexible typing? You want rules! Structure! Don’t worry—SQLite can do that too.

Let’s create a strict table and try entering a non-integer into column n:

CREATE TABLE types_strict (n INTEGER) STRICT;
INSERT INTO types_strict VALUES ('hello');

Error! You can’t store a text value in an integer column in a strict table. SQLite will enforce the types you declare.

The best of both worlds: strict and flexible

Here’s where it gets even cooler. What if you want some columns to be strict but others to be flexible? You can do that too! Here we have one column to strictly hold integers but another column to accept any type:

CREATE TABLE types_both (n INTEGER, value ANY) STRICT;
INSERT INTO types_both VALUES (1, 1);
INSERT INTO types_both VALUES (1, 'hello');

The n column is strictly integers, but the value column can be anything. You can only insert an integer into n and anything (a string, a float, a blob) into value. Flexibility and structure—best of both worlds!

SQLite is flexibly typed! And if you want strict typing? SQLite can do that too. It's up to you!

YouTube video

Check out the video version of this article on YouTube!

Me

Thanks for reading! My name is Aaron and I write, make videos , and generally try really hard .

If you ever have any questions or want to chat, I'm always on Twitter.

If you want to give me money (please do), you can buy my course on SQLite at HighPerformanceSQLite.com or my course on screencasting at Screencasting.com . On the off chance you're a sophomore at Texas A&M University, you can buy my accounting course at acct229.com .

You can find me on YouTube on my personal channel . If you love podcasts, I got you covered. You can listen to me on Mostly Technical .