Using SQLite

This post discusses SQLite. applications. The post forms part of background documentation developed for a customer, but is sufficiently general to form a blog post.

Introduction

SQLite is an open-source database which provides a useful alternative to an Oracle database for small applications.

SQLite is a transactional database which implements the database ACID properties

SQLite has quietly become one of the most widely used databases in the world, mainly because it is included on Android devices.

SQLite is distributed with Linux. Enterprise Linux 5U6 ships with sqlite-3.3; 6U4 ships with sqlite-3.6.

To run SQLite use:

[user@server]$ sqlite3
SQLite version 3.8.6 2014-08-15 11:46:33
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite>

The above command starts an interactive shell. With parameters this shell will operate on a transient database.

To create a new database or to access an existing one, specify the name of the database on the command line. For example:

[user@server]$ sqlite3 test.db

It is not necessary to explicitly create a SQLite database.

The command shell supports both DML and DDL statements. It also provides other commands which are preceded with a period (.). A summary of available commands can be printed using .help

.backup ?DB? FILE      Backup DB (default "main") to FILE
.bail on|off           Stop after hitting an error.  Default OFF
.clone NEWDB           Clone data into NEWDB from the existing database
.databases             List names and files of attached databases
.dump ?TABLE? ...      Dump the database in an SQL text format
                         If TABLE specified, only dump tables matching
                         LIKE pattern TABLE.
.echo on|off           Turn command echo on or off
.eqp on|off            Enable or disable automatic EXPLAIN QUERY PLAN
.exit                  Exit this program
.explain ?on|off?      Turn output mode suitable for EXPLAIN on or off.
                         With no args, it turns EXPLAIN on.
.fullschema            Show schema and the content of sqlite_stat tables
.headers on|off        Turn display of headers on or off
.help                  Show this message
.import FILE TABLE     Import data from FILE into TABLE
.indices ?TABLE?       Show names of all indices
                         If TABLE specified, only show indices for tables
                         matching LIKE pattern TABLE.
.load FILE ?ENTRY?     Load an extension library
.log FILE|off          Turn logging on or off.  FILE can be stderr/stdout
.mode MODE ?TABLE?     Set output mode where MODE is one of:
                         csv      Comma-separated values
                         column   Left-aligned columns.  (See .width)
                         html     HTML <table> code
                         insert   SQL insert statements for TABLE
                         line     One value per line
                         list     Values delimited by .separator string
                         tabs     Tab-separated values
                         tcl      TCL list elements
.nullvalue STRING      Use STRING in place of NULL values
.once FILENAME         Output for the next SQL command only to FILENAME
.open ?FILENAME?       Close existing database and reopen FILENAME
.output ?FILENAME?     Send output to FILENAME or stdout
.print STRING...       Print literal STRING
.prompt MAIN CONTINUE  Replace the standard prompts
.quit                  Exit this program
.read FILENAME         Execute SQL in FILENAME
.restore ?DB? FILE     Restore content of DB (default "main") from FILE
.save FILE             Write in-memory database into FILE
.schema ?TABLE?        Show the CREATE statements
                         If TABLE specified, only show tables matching
                         LIKE pattern TABLE.
.separator STRING ?NL? Change separator used by output mode and .import
                         NL is the end-of-line mark for CSV
.shell CMD ARGS...     Run CMD ARGS... in a system shell
.show                  Show the current values for various settings
.stats on|off          Turn stats on or off
.system CMD ARGS...    Run CMD ARGS... in a system shell
.tables ?TABLE?        List names of tables
                         If TABLE specified, only list tables matching
                         LIKE pattern TABLE.
.timeout MS            Try opening locked tables for MS milliseconds
.timer on|off          Turn SQL timer on or off
.trace FILE|off        Output each SQL statement as it is run
.vfsname ?AUX?         Print the name of the VFS stack
.width NUM1 NUM2 ...   Set column widths for "column" mode
                         Negative values right-justify

To exit the command shell use .quit or .exit.

DDL Statements

DDL statements are terminiated by a semicolon

CREATE TABLE statement

DDL statements can be entered directly at the command line. For example:

sqlite> CREATE TABLE driver
(
  key NUMBER,
  name VARCHAR2(30),
  team VARCHAR2(30),
  points NUMBER
);

Alternatively statements can be added to a script file which is then passed as standard input to sqlite3. For example we can create a file called c1.sql containing the following:

CREATE TABLE driver
(
  key NUMBER,
  name VARCHAR2(30),
  team VARCHAR2(30),
  points NUMBER
);

This can be executed as follows:

[user@server]$ sqlite3 test.db < c1.sql

DROP TABLE statement

For example:

DROP TABLE driver;

DML Statements

DML statements can also be entered directly at the command line or executed using script files.

INSERT Statement

The INSERT statement syntax is similar to Oracle. For example:

INSERT INTO driver VALUES (1,'Sebastial Vettel','Red Bull',374);
INSERT INTO driver VALUES (2,'Jenson Button','McLaren',240);
INSERT INTO driver VALUES (3,'Fernando Alonso','Ferrari',227);
INSERT INTO driver VALUES (4,'Mark Webber','Red Bull',221);

UPDATE Statement

This is an example of an UPDATE statement:

UPDATE driver SET points = 399 WHERE key = 1;

DELETE Statement

This is an example of an DELETE statement:

DELETE FROM driver WHERE key = 3;

SELECT Statements

The contents of the table can be displayed using a SELECT statement. For example:

sqlite> SELECT * FROM driver;
1|Sebastial Vettel|Red Bull|399
2|Jenson Button|McLaren|240
4|Mark Webber|Red Bull|221

By default the output is separated by pipe symbols. The separator can be changed using the .separator command. For example to change the separator to a semicolon:

sqlite> . separator ;
sqlite> SELECT * FROM driver;
1;Sebastial Vettel;Red Bull;399
2;Jenson Button;McLaren;240
4;Mark Webber;Red Bull;221

Transactions

By default auto-commit is enabled in SQLite. So there is an implicit commit after each DML statement.

To disable auto-commit a transaction must start with BEGIN TRANSACTION. Following a BEGIN TRANSACTION all subsequent DML statements are considered part of the same transaction until a COMMIT or ROLLBACK is issued.

For example:

sqlite> SELECT * FROM driver;
1;Sebastial Vettel;Red Bull;399
2;Jenson Button;McLaren;240
4;Mark Webber;Red Bull;221

If BEGIN TRANSACTION is issued then ROLLBACK will discard any changes:

sqlite> BEGIN TRANSACTION;
sqlite> DELETE FROM driver WHERE key = 1;
sqlite> ROLLBACK;
sqlite> SELECT * FROM driver;
1;Sebastial Vettel;Red Bull;399
2;Jenson Button;McLaren;240
4;Mark Webber;Red Bull;221

If BEGIN TRANSACTION; is issued then COMMIT will save any changes:

sqlite> BEGIN TRANSACTION;
sqlite> DELETE FROM driver WHERE key = 1;
sqlite> COMMIT;
sqlite> SELECT * FROM driver;
2;Jenson Button;McLaren;240
4;Mark Webber;Red Bull;221

BEGIN TRANSACTION can be abbreviated to BEGIN

Constraints

SQLite supports several types of constraint including:

Constraints can only be created using the CREATE TABLE statement. Constraints cannot be added after a table has been created.

Note that by default SQLite does not support foreign key constraints.

Primary Key Constraint

The primary key uniquely identifies every row in the table.

The following is an example of the declaration of a table with a primary key constraint

CREATE TABLE funds
(
  fundkey      NUMBER PRIMARY KEY,
  fundcode     VARCHAR2(8),
  fundtype     NUMBER,
  description  VARCHAR2(30)
);

In SQLite primary key columns can be NULL. Specify an additional NOT NULL constraint to force non-null values.

Multi-column primary keys can also be created. For example:

CREATE TABLE order_items
(\t
  order_number NUMBER,
  item_number NUMBER,
  quantity NUMBER,
  PRIMARY KEY (order_number,item_number)
);

Unique Constraint

A unique constraint ensures that all non-null values in a column are unique.

The following is an example of the declaration of a table with a unique constraint

CREATE TABLE funds
(
  fundkey      NUMBER,
  fundcode     VARCHAR2(8) UNIQUE,
  fundtype     NUMBER,
  description  VARCHAR2(30)
);

NOT NULL Constraint

Ensures that a column cannot have a NULL value.

The following is an example of the declaration of a table with NOT NULL constraints


CREATE TABLE funds
(
  fundkey      NUMBER       NOT NULL,
  fundcode     VARCHAR2(8)  NOT NULL,
  fundtype     NUMBER       NOT NULL,
  description  VARCHAR2(30) NOT NULL
);

DEFAULT Constraint

A default constraint provides a default value for a column where none has been specified.

The following is an example of the declaration of a table with a default constraint

CREATE TABLE funds
(
  fundkey      NUMBER,
  fundcode     VARCHAR2(8),
  fundtype     NUMBER DEFAULT 1,
  description  VARCHAR2(30)
);

CHECK Constraint

A check constraint ensures that all values in a column satisfy specified conditions

The following is an example of the declaration of a table with a CHECK constraint

CREATE TABLE funds
(
  fundkey      NUMBER,
  fundcode     VARCHAR2(8),
  fundtype     NUMBER       CHECK(fundtype IN (1,2)),
  description  VARCHAR2(30)
);

In the above example, the value of the fundtype column must be 1 or 2.

DUAL

SQLite does not have a DUAL table

Single-row SELECT statements do not require a FROM clause. For example:

sqlite> SELECT UPPER ('Ferrari');
FERRARI
sqlite> SELECT 400 / 10
40
sqlite> SELECT SUBSTR ('Silverstone',1,6)
Silver

Data Dictionary

The SQLite data dictionary consists of a table containing DDL statements as opposed to using a relational data dictionary.

The .tables command lists all tables in the database. For example:

sqlite> .tables
driver

The entire contents of the data dictionary can be listed using the .schema command.

Alternative DDL for individual tables can be listed using .schema . For example:

sqlite> .schema driver
CREATE TABLE driver
(
  key NUMBER PRIMARY KEY,
  name VARCHAR2(30) UNIQUE,
  team VARCHAR2(30),
  points NUMBER
);

The .schema command returns the result of a join between sqlite_master and sqlite_temp_master

The .indices command reports all indexes created for a specfied table

sqlite> .indices driver
sqlite_autoindex_driver_1
sqlite_autoindex_driver_2

In the above example system-generated indexes have been created for the primary key and the unique key