# Helpful tips for SQLite3 ## Creating good tables It's a good idea to use `INTEGER PRIMARY KEY AUTOINCREMENT` as one of the columns in a table. This ensures two things: - `INTEGER PRIMARY KEY`: improved performance by reusing SQLite3's built-in `rowid` column. - `AUTOINCREMENT`: no future row will have the same ID as an old one that was deleted. This can prevent potential bugs and security breaches. If you don't use `INTEGER PRIMARY KEY`, then you *must* use `NOT NULL` in all of your your primary key columns. Otherwise you'll be victim to an SQLite3 bug that allows primary keys to be `NULL`. Any column with `INTEGER PRIMARY KEY` will automatically increment when setting its value to `NULL`. But without `AUTOINCREMENT`, the behavior only ensures uniqueness from currently existing rows. It should be noted that `NULL` values count as unique from each other. This has implications when using the `UNIQUE` contraint or any other equality test. ## Default values When a column has a `DEFAULT` value, it only gets applied when no value is specified for an `INSERT` statement. If the `INSERT` statement specifies a `NULL` value, the `DEFAULT` value is **NOT** used. ## Foreign keys Foreign key constraints are not enforced if the child's column value is `NULL`. To ensure that a relationship is always enforced, use `NOT NULL` on the child column. Example: ```sql CREATE TABLE comments (value TEXT, user_id INTEGER NOT NULL REFERENCES users); ``` Foreign key clauses can be followed by `ON DELETE` and/or `ON UPDATE`, with the following possible values: - `SET NULL`: if the parent column is deleted or updated, the child column becomes `NULL`. - *NOTE: This still causes a constraint violation if the child column has `NOT NULL`*. - `SET DEFAULT`: if the parent column is updated or deleted, the child column becomes its `DEFAULT` value. - *NOTE: This still causes a constraint violation if the child column's `DEFAULT` value does not correspond with an actual parent row*. - `CASCADE`: if the parent row is deleted, the child row is deleted; if the parent column is updated, the new value is propogated to the child column.