You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Comprehensive SQLite cheatsheet covering database management, CRUD, indexes, joins, transactions, FTS5, JSON, date functions, PRAGMA settings, performance tuning, and command-line tools. Includes 21 sections with syntax examples, best practices, and quick reference for beginners to advanced users.
CREATETABLEusers (
id INTEGERPRIMARY KEY AUTOINCREMENT,
username TEXTNOT NULL UNIQUE,
email TEXTNOT NULL,
age INTEGER,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Without rowid (explicit primary key)CREATETABLEproducts (
product_code TEXTPRIMARY KEY,
name TEXT,
price REAL
) WITHOUT ROWID;
-- Create from queryCREATETABLEactive_usersASSELECT*FROM users WHERE status ='active';
Alter Table
-- Add columnALTERTABLE users ADD COLUMN phone TEXT;
-- Rename tableALTERTABLE users RENAME TO customers;
-- Rename column (SQLite 3.25+)ALTERTABLE users RENAME COLUMN username TO user_name;
-- Add column with checkALTERTABLE users ADD COLUMN status TEXT DEFAULT 'active'CHECK (status IN ('active', 'inactive'));
Drop Table
DROPTABLE IF EXISTS users;
DROPTABLE users; -- Without check
List Tables
.tables -- Command lineSELECT name FROM sqlite_master WHERE type='table';
SELECT name FROM sqlite_master WHERE type='table'AND name NOT LIKE'sqlite_%';
Table Info
PRAGMA table_info(users);
.schema users -- Command line
-- Single rowINSERT INTO users (username, email, age) VALUES ('john', 'john@mail.com', 25);
-- Multiple rowsINSERT INTO users (username, email, age) VALUES
('jane', 'jane@mail.com', 30),
('bob', 'bob@mail.com', 28);
-- Insert with defaultINSERT INTO users (username, email) VALUES ('alice', 'alice@mail.com');
-- Insert or replace (conflict handling)
INSERT OR REPLACE INTO users (id, username, email) VALUES (1, 'john_new', 'new@mail.com');
-- Insert or ignore
INSERT OR IGNORE INTO users (id, username) VALUES (2, 'existing_user');
-- Insert from selectINSERT INTO premium_users SELECT*FROM users WHERE age >30;
UPDATE
-- Basic updateUPDATE users SET age =26WHERE username ='john';
-- Multiple columnsUPDATE users SET email ='new@mail.com', age = age +1WHERE id =1;
-- Update all rowsUPDATE users SET status ='active';
-- Update with joinUPDATE users SET age =users.age+1WHERE id IN (SELECT user_id FROM orders WHERE total >100);
DELETE
-- Delete specific rowsDELETEFROM users WHERE username ='bob';
-- Delete all rowsDELETEFROM users;
-- Truncate (faster)DELETEFROM users; VACUUM;
-- Delete with limit/order (SQLite 3.25+)DELETEFROM logs WHEREtimestamp<'2024-01-01'ORDER BYtimestampLIMIT1000;
SELECT (Basic)
-- All columnsSELECT*FROM users;
-- Specific columnsSELECT username, email FROM users;
-- DistinctSELECT DISTINCT age FROM users;
-- With limitSELECT*FROM users LIMIT10 OFFSET 5;
-- AliasSELECT username AS name, email AS contact FROM users;
6. Querying Data
WHERE Clause
-- ComparisonsSELECT*FROM users WHERE age >=18;
SELECT*FROM users WHERE username ='john';
-- Logical operatorsSELECT*FROM users WHERE age >18AND status ='active';
SELECT*FROM users WHERE age <18OR age >65;
SELECT*FROM users WHERE NOT status ='inactive';
-- IN operatorSELECT*FROM users WHERE age IN (25, 30, 35);
SELECT*FROM users WHERE username IN ('john', 'jane');
-- BETWEENSELECT*FROM users WHERE age BETWEEN 20AND30;
-- LIKE (case-insensitive by default)SELECT*FROM users WHERE username LIKE'j%'; -- Starts with jSELECT*FROM users WHERE username LIKE'%hn'; -- Ends with hnSELECT*FROM users WHERE username LIKE'%oh%'; -- Contains oh-- GLOB (case-sensitive, wildcards: * ?)SELECT*FROM users WHERE username GLOB 'J*';
-- NULL checksSELECT*FROM users WHERE email IS NULL;
SELECT*FROM users WHERE email IS NOT NULL;
ORDER BY
-- Ascending (default)SELECT*FROM users ORDER BY age;
-- DescendingSELECT*FROM users ORDER BY age DESC;
-- Multiple columnsSELECT*FROM users ORDER BY age DESC, username ASC;
LIMIT & OFFSET (Pagination)
-- First 10 rowsSELECT*FROM users LIMIT10;
-- Next 10 rows (offset 10)SELECT*FROM users LIMIT10 OFFSET 10;
-- Alternative syntaxSELECT*FROM users LIMIT10, 10;
GROUP BY & HAVING
-- Count by ageSELECT age, COUNT(*) as count FROM users GROUP BY age;
-- With aggregate functionsSELECT status, AVG(age) as avg_age, MAX(age) as max_age
FROM users GROUP BY status;
-- Having filterSELECT age, COUNT(*) as count
FROM users
GROUP BY age
HAVINGCOUNT(*) >1;
-- With WHERE (executes before GROUP BY)SELECT status, COUNT(*) as count
FROM users
WHERE age >18GROUP BY status
HAVINGCOUNT(*) >=2;
7. Constraints
Constraint
Description
NOT NULL
Column cannot be NULL
UNIQUE
All values must be different
PRIMARY KEY
Unique identifier, automatically indexed
FOREIGN KEY
References column in another table
CHECK
Validates values against expression
DEFAULT
Default value when not specified
Examples
CREATETABLEproducts (
id INTEGERPRIMARY KEY,
name TEXTNOT NULL,
sku TEXT UNIQUE,
price REALCHECK (price >0),
category_id INTEGER,
status TEXT DEFAULT 'draft',
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETESETNULL
);
-- Composite primary keyCREATETABLEorder_items (
order_id INTEGER,
product_id INTEGER,
quantity INTEGER,
PRIMARY KEY (order_id, product_id)
);
-- Composite unique constraintCREATETABLEusers (
id INTEGERPRIMARY KEY,
first_name TEXT,
last_name TEXT,
UNIQUE(first_name, last_name)
);
-- Foreign key with cascadeCREATETABLEcomments (
id INTEGERPRIMARY KEY,
user_id INTEGER,
content TEXT,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
Enable Foreign Keys
PRAGMA foreign_keys =ON;
PRAGMA foreign_keys; -- Check status
8. Indexes
Create Index
-- Basic indexCREATEINDEXidx_users_emailON users(email);
-- Unique indexCREATEUNIQUE INDEXidx_users_usernameON users(username);
-- Composite indexCREATEINDEXidx_users_age_statusON users(age, status);
-- Descending indexCREATEINDEXidx_users_age_descON users(age DESC);
-- Partial indexCREATEINDEXidx_active_usersON users(email) WHERE status ='active';
-- Index with collationCREATEINDEXidx_users_namesON users(last_name COLLATE NOCASE);
-- Query to check index usage (EXPLAIN QUERY PLAN)
EXPLAIN QUERY PLAN SELECT*FROM users WHERE email ='john@mail.com';
9. Views
Create View
-- Basic viewCREATEVIEWactive_usersASSELECT id, username, email FROM users WHERE status ='active';
-- View with joinCREATEVIEWuser_ordersASSELECTu.username, o.order_date, o.totalFROM users u
JOIN orders o ONu.id=o.user_id;
-- Temporary view (session only)
CREATE TEMP VIEW temp_view ASSELECT*FROM users;
Drop View
DROPVIEW IF EXISTS active_users;
List Views
SELECT name FROM sqlite_master WHERE type='view';
Updatable Views (limited)
-- View that can be updated (simple, no joins, no aggregates)CREATEVIEWsimple_usersASSELECT id, username, email FROM users;
INSERT INTO simple_users (username, email) VALUES ('new', 'new@mail.com');
10. Transactions
Basic Transaction
BEGIN; -- or BEGIN TRANSACTION;UPDATE accounts SET balance = balance -100WHERE id =1;
UPDATE accounts SET balance = balance +100WHERE id =2;
COMMIT; -- or END TRANSACTION;-- Rollback on errorBEGIN;
DELETEFROM users WHERE id =100;
-- Something wrong?ROLLBACK; -- Undo the delete
Savepoints
BEGIN;
SAVEPOINT sp1;
UPDATE users SET age =30WHERE id =1;
ROLLBACK TO sp1; -- Undo only last change
SAVEPOINT sp2;
INSERT INTO logs VALUES ('action');
RELEASE sp2; -- Make permanentCOMMIT;
Transaction Types
-- DEFERRED (default): starts when first read/write occursBEGIN DEFERRED;
-- IMMEDIATE: acquires write lock immediatelyBEGIN IMMEDIATE;
-- EXCLUSIVE: prevents all other accessBEGIN EXCLUSIVE;
11. Functions
Aggregate Functions
SELECTCOUNT(*) as total_rows,
COUNT(email) as non_null_emails,
COUNT(DISTINCT age) as unique_ages,
SUM(age) as age_sum,
AVG(age) as age_avg,
MIN(age) as youngest,
MAX(age) as oldest,
TOTAL(age) as age_total_float, -- Returns 0.0 instead of NULL
GROUP_CONCAT(username) as usernames, -- Comma-separated
GROUP_CONCAT(username, '; ') as usernames_semicolon
FROM users;
Scalar Functions
-- StringSELECT
LENGTH('hello') as len, -- 5UPPER('hello') asupper, -- HELLOLOWER('HELLO') aslower, -- hello
SUBSTR('hello world', 7) as substr, -- world
SUBSTR('hello world', 7, 3) as substr_lim, -- worTRIM(' hello ') as trimmed, -- hello
LTRIM(' hello'), RTRIM('hello '),
REPLACE('hello world', 'world', 'sqlite'),
INSTR('hello', 'e') as position, -- 2LIKE('%lo%', 'hello') as like_match,
GLOB('*lo*', 'hello') as glob_match,
'Hello '||'World'as concat;
-- NumericSELECT
ABS(-5) as abs, -- 5
ROUND(3.14159, 2) as rounded, -- 3.14
CEIL(3.2) as ceil, -- 4
FLOOR(3.8) as floor, -- 3
RANDOM() as random,
RANDOM() % 100as random_0_99,
POWER(2, 3) as power, -- 8 (SQLite 3.35+)
SQRT(16) as sqrt; -- 4-- Type conversionSELECT
CAST('123'ASINTEGER) as int_val,
CAST('3.14'ASREAL) as float_val,
TYPEOF(123) as type; -- integer
Conditional Functions
-- CASE expressionSELECT
username,
CASE age
WHEN 18 THEN 'Just adult'
WHEN 21 THEN 'Legal drinking'
ELSE 'Other'
END as age_status,
CASE
WHEN age <18 THEN 'Minor'
WHEN age BETWEEN 18AND65 THEN 'Adult'
ELSE 'Senior'
END as age_group
FROM users;
-- IIF (ternary)SELECT IIF(age >=18, 'Adult', 'Minor') as status FROM users;
-- COALESCE (first non-NULL)SELECT COALESCE(phone, email, 'No contact') as contact FROM users;
-- NULLIF (NULL if equal)SELECT NULLIF(age, 0) as valid_age FROM users;
12. Joins
INNER JOIN
SELECTu.username, o.order_date, o.totalFROM users u
INNER JOIN orders o ONu.id=o.user_id;
LEFT OUTER JOIN
SELECTu.username, o.order_date, o.totalFROM users u
LEFT JOIN orders o ONu.id=o.user_id;
-- Users without orders will have NULL for order columns
SELECTa.usernameas employee, b.usernameas manager
FROM employees a
LEFT JOIN employees b ONa.manager_id=b.id;
Multi-table Join
SELECTu.username, o.order_date, p.nameas product_name, oi.quantityFROM users u
JOIN orders o ONu.id=o.user_idJOIN order_items oi ONo.id=oi.order_idJOIN products p ONoi.product_id=p.id;
13. Subqueries & CTEs
Subqueries in WHERE
-- Scalar subquerySELECT*FROM products
WHERE price > (SELECTAVG(price) FROM products);
-- IN subquerySELECT*FROM users
WHERE id IN (SELECT user_id FROM orders WHERE total >100);
-- EXISTS subquerySELECT*FROM users u
WHERE EXISTS (SELECT1FROM orders o WHEREo.user_id=u.id);
-- ANY/ALL (SQLite 3.25+)SELECT*FROM products
WHERE price > ANY (SELECT price FROM products WHERE category ='electronics');
Subqueries in SELECT
SELECT
username,
(SELECTCOUNT(*) FROM orders WHERE user_id =users.id) as order_count,
(SELECTSUM(total) FROM orders WHERE user_id =users.id) as total_spent
FROM users;
Subqueries in FROM (Derived Tables)
SELECT category, avg_price
FROM (
SELECT category, AVG(price) as avg_price
FROM products
GROUP BY category
) WHERE avg_price >50;
Common Table Expressions (CTE)
-- Basic CTE
WITH high_value_orders AS (
SELECT user_id, SUM(total) as total_spent
FROM orders
GROUP BY user_id
HAVINGSUM(total) >1000
)
SELECTu.username, h.total_spentFROM users u
JOIN high_value_orders h ONu.id=h.user_id;
Recursive CTE (Hierarchical queries)
WITH RECURSIVE subordinates AS (
-- Base case: direct subordinates of manager 1SELECT id, name, manager_id, 1as level
FROM employees
WHERE manager_id =1UNION ALL-- Recursive caseSELECTe.id, e.name, e.manager_id, s.level+1FROM employees e
JOIN subordinates s ONe.manager_id=s.id
)
SELECT*FROM subordinates;
-- Generate numbers
WITH RECURSIVE numbers(n) AS (
VALUES(1)
UNION ALLSELECT n+1FROM numbers WHERE n <100
)
SELECT*FROM numbers;
Materialized CTEs (SQLite 3.35+)
WITH MATERIALIZED expensive_computation AS (
SELECT complex_query
)
SELECT*FROM expensive_computation;
14. Triggers
Create Trigger
-- Before insertCREATETRIGGERvalidate_email_before_insert
BEFORE INSERT ON users
BEGINSELECT CASE
WHEN NEW.email NOT LIKE'%@%' THEN
RAISE(ABORT, 'Invalid email address')
END;
END;
-- After updateCREATETRIGGERlog_user_update
AFTER UPDATEON users
BEGININSERT INTO audit_log (table_name, action, old_value, new_value, timestamp)
VALUES ('users', 'UPDATE', OLD.email, NEW.email, CURRENT_TIMESTAMP);
END;
-- Instead of (for views)CREATETRIGGERupdate_active_users
INSTANT OF UPDATEON active_users_view
BEGINUPDATE users SET username =NEW.usernameWHERE id =OLD.id;
END;
Trigger Events
-- DELETE triggerCREATETRIGGERprevent_user_delete
BEFORE DELETEON users
BEGINSELECT CASE
WHEN (SELECTCOUNT(*) FROM orders WHERE user_id =OLD.id) >0 THEN
RAISE(ABORT, 'Cannot delete user with orders')
END;
END;
-- UPDATE of specific columnsCREATETRIGGERtrack_email_changes
AFTER UPDATE OF email ON users
BEGININSERT INTO email_history (user_id, old_email, new_email, changed_at)
VALUES (OLD.id, OLD.email, NEW.email, CURRENT_TIMESTAMP);
END;
Drop Trigger
DROPTRIGGER IF EXISTS validate_email_before_insert;
List Triggers
SELECT name FROM sqlite_master WHERE type='trigger';
SELECT*FROM sqlite_master WHERE type='trigger'AND tbl_name='users';
-- Difference between datesSELECT JULIANDAY('2024-12-31') - JULIANDAY('2024-01-01') as days;
SELECT (STRFTIME('%s', '2024-12-31') - STRFTIME('%s', '2024-01-01')) /86400as days;
-- Age calculationSELECT (STRFTIME('%s', 'now') - STRFTIME('%s', birth_date)) /31536000as age FROM users;
17. Full-Text Search (FTS5)
Create FTS Table
-- Basic FTS5 table
CREATE VIRTUAL TABLE posts_fts USING fts5(
title,
content,
author
);
-- With options
CREATE VIRTUAL TABLE posts_fts USING fts5(
title UNINDEXED, -- Stored but not indexed
content,
author,
content='posts', -- External content table
tokenize='porter unicode61'
);
-- External content mode
CREATE VIRTUAL TABLE posts_fts USING fts5(content, content='posts');
Insert/Update
-- Direct insertINSERT INTO posts_fts (title, content, author)
VALUES ('SQLite Tutorial', 'Learn SQLite FTS5', 'John');
-- For external content, sync with source tableINSERT INTO posts_fts (rowid, title, content, author)
SELECT rowid, title, content, author FROM posts;
-- Update after content changes
INSERT OR REPLACE INTO posts_fts (rowid, title, content, author)
VALUES (1, 'Updated Title', 'New content', 'John');
Query with FTS5
-- Basic MATCHSELECT*FROM posts_fts WHERE posts_fts MATCH 'sqlite';
-- Column-specificSELECT*FROM posts_fts WHERE title MATCH 'tutorial';
-- Phrase searchSELECT*FROM posts_fts WHERE content MATCH '"learn sqlite"';
-- Prefix searchSELECT*FROM posts_fts WHERE posts_fts MATCH 'learn*';
-- NEAR operatorSELECT*FROM posts_fts WHERE content MATCH 'NEAR("sqlite" "fts5", 5)';
-- Boolean operatorsSELECT*FROM posts_fts WHERE posts_fts MATCH 'sqlite AND tutorial';
SELECT*FROM posts_fts WHERE posts_fts MATCH 'sqlite NOT fts5';
SELECT*FROM posts_fts WHERE posts_fts MATCH 'sqlite OR fts5';
-- Highlight and snippetSELECT
highlight(posts_fts, 1, '<b>', '</b>') as title_highlighted,
snippet(posts_fts, 2, '<mark>', '</mark>', '...', 15) as content_snippet
FROM posts_fts
WHERE posts_fts MATCH 'sqlite';
FTS5 Auxiliary Functions
-- BM25 rankingSELECT*, bm25(posts_fts) as rank
FROM posts_fts
WHERE posts_fts MATCH 'sqlite'ORDER BY rank;
-- Debug infoSELECT*FROM posts_fts('sqlite');
Maintain FTS Tables
-- Rebuild indexINSERT INTO posts_fts(posts_fts) VALUES('optimize');
-- Delete from external content tableDELETEFROM posts_fts WHERE rowid IN (SELECT rowid FROM posts WHERE deleted =1);
-- Extract value (returns JSON)SELECT json_extract(attributes, '$.brand') as brand FROM products;
-- Extract as textSELECT attributes->>'$.brand'as brand FROM products;
-- Extract as integerSELECT attributes->>'$.ram'as ram FROM products;
-- Nested extractionSELECT json_extract(attributes, '$.colors[0]') as first_color FROM products;
-- Multiple extractionsSELECT
json_extract(attributes, '$.brand'),
json_extract(attributes, '$.ram')
FROM products;
Query JSON Arrays
-- Check if array contains valueSELECT*FROM products
WHERE json_extract(attributes, '$.colors') LIKE'%"gold"%';
-- JSON each (3.37+)SELECTp.name,
value as color
FROM products p, json_each(p.attributes, '$.colors');
Modify JSON
-- Insert/update JSON valueUPDATE products
SET attributes = json_insert(attributes, '$.cpu', 'Intel i7')
WHERE name ='Laptop';
-- Replace valueUPDATE products
SET attributes = json_replace(attributes, '$.ram', 32)
WHERE name ='Laptop';
-- Set (insert or replace)UPDATE products
SET attributes = json_set(attributes, '$.storage', 1024, '$.ssd', true)
WHERE name ='Laptop';
-- Remove keyUPDATE products
SET attributes = json_remove(attributes, '$.colors')
WHERE name ='Phone';
Create JSON
-- Build JSON objectSELECT json_object(
'name', name,
'attributes', json(attributes)
) as product_json FROM products;
-- Build JSON arraySELECT json_group_array(name) as product_names FROM products;
-- Validate JSONSELECT json_valid('{"key": "value"}'); -- 1 (valid)
JSON Functions Summary
Function
Description
json()
Validates and minifies JSON
json_extract()
Extracts value from JSON
json_array()
Creates JSON array
json_object()
Creates JSON object
json_insert()
Inserts new values
json_replace()
Replaces existing values
json_set()
Inserts or replaces
json_remove()
Removes key/value
json_each()
Table-valued function for array elements
json_tree()
Table-valued function for recursive extraction
json_valid()
Validates JSON format
json_quote()
Escapes string as JSON
json_group_array()
Aggregates rows into JSON array
json_group_object()
Aggregates rows into JSON object
19. Backup & Recovery
Command Line Backup
# Simple copy
cp database.db database_backup.db
# Using .backup (creates consistent backup)
sqlite3 database.db ".backup database_backup.db"# Backup specific table
sqlite3 database.db ".dump users"> users.sql
# Full database dump
sqlite3 database.db ".dump"> database.sql
# Restore from dump
sqlite3 new_database.db < database.sql
SQL Backup Commands
-- Backup to file (within SQLite)
BACKUP TO 'backup.db';
-- Backup with encryption (SQLite Encryption Extension)
BACKUP TO 'encrypted.db' KEY 'password';
-- Vacuum to rebuild and shrink
VACUUM;
-- Vacuum into new file
VACUUM INTO 'compacted.db';
-- Create backup triggerCREATETRIGGERauto_backup
AFTER INSERT ON critical_table
BEGINSELECT backup('auto_backup.db');
END;
Recovery Methods
-- Recover from corrupt database
PRAGMA integrity_check;
PRAGMA quick_check;
-- Dump and restore
.output recovery.sql
.dump
.output stdout
-- Try to recover data from corrupt DB
sqlite3 corrupt.db".recover" | sqlite3 recovered.db
20. Performance Tuning
Query Optimization
-- Analyze to update statistics
ANALYZE;
ANALYZE users; -- Specific table
ANALYZE sqlite_schema; -- System tables-- Query plan analysis
EXPLAIN QUERY PLAN SELECT*FROM users WHERE email ='test@mail.com';
-- Force index usageSELECT*FROM users INDEXED BY idx_users_email WHERE email ='test@mail.com';
-- Disable index usageSELECT*FROM users NOT INDEXED WHERE email ='test@mail.com';
Optimize Performance Settings
-- Use WAL mode for better concurrency
PRAGMA journal_mode=WAL;
-- Increase cache size
PRAGMA cache_size =-20000; -- 20,000 pages (negative = KB)-- Memory-mapped I/O
PRAGMA mmap_size =268435456; -- 256MB-- Optimize synchronous (trade safety for speed)
PRAGMA synchronous = OFF; -- Not recommended for critical data-- Use temp store in memory
PRAGMA temp_store = MEMORY;
-- Disable schema locking (read-only)
PRAGMA query_only =ON;
-- Compile-time optimizations
PRAGMA trusted_schema =ON; -- Disable bytecode verification
Bulk Insert Optimization
-- Wrap in transactionBEGIN;
INSERT INTO users SELECT*FROM temp_users;
COMMIT;
-- Use prepared statements-- (in application code)-- Disable indexes temporarily (rebuild later)
PRAGMA writable_schema =ON;
-- Drop indexes, insert data, re-create indexes-- Increase page cache
PRAGMA cache_size =100000;
.help -- Show all commands
.quit / .exit -- Exit sqlite3
.databases -- List attached databases
.tables ?PATTERN? -- List tables
.schema ?TABLE? -- Show CREATE statements
.indices ?TABLE? -- List indexes
.dump ?TABLE? -- Dump database as SQL
.output FILE -- Send output to file
.output stdout -- Send output to console
.mode MODE -- Set output mode
.headers ON|OFF -- Toggle headers for column mode
.timer ON|OFF -- Toggle query timings
Output Modes
.mode list -- Separated by |
.mode column -- Table format (aligned)
.mode csv -- Comma-separated values
.mode tab -- Tab-separated
.mode insert -- SQL INSERT statements
.mode line-- Each column on separate line
.mode quote -- SQL quoted strings
.mode json -- JSON format (3.33+)
.mode markdown -- Markdown tables (3.37+)
.mode table -- ASCII table (3.36+)
.mode box-- Box-drawing table (3.36+)
Import/Export
-- Import CSV
.mode csv
.import data.csv table_name
-- Import CSV with header
.import --csv --skip 1 data.csv table_name-- Export to CSV
.headers ON
.mode csv
.output data.csvSELECT*FROM table_name;
.output stdout
-- Export to JSON
.mode json
.output data.jsonSELECT*FROM table_name;
-- Script execution
.read script.sql
.once output.csv-- Output for next query only
Database Maintenance
.backup FILE -- Backup database
.restore FILE -- Restore from backup
.vacuum -- Rebuild database file
.recover -- Recover data from corrupt DB
.check ?DB? -- Check database integrity
.sha3sum ?FILE? -- Compute SHA3 hash
Configuration
.echo ON|OFF -- Echo commands
.stats ON|OFF -- Show statistics
.nullvalue STRING -- String for NULL values
.separator CHAR-- Change separator for list mode
.cd DIR -- Change directory
.system CMD -- Run system command
.shell CMD -- Run shell command
.parameter list -- List bound parameters
.parameter set NAME VALUE
.parameter clear
Debugging
.show -- Show current settings
.trace FILE|OFF -- Enable SQL tracing
.log FILE|OFF -- Enable logging
.eqp ON|OFF -- Explain query plan
.expert -- Index recommendations (experimental)
Quick Reference Card
Most Used Commands
-- Connect
sqlite3 database.db-- Create tableCREATETABLEusers (id INTEGERPRIMARY KEY, name TEXT);
-- CRUDINSERT INTO users (name) VALUES ('John');
SELECT*FROM users WHERE name='John';
UPDATE users SET name='Jane'WHERE id=1;
DELETEFROM users WHERE id=1;
-- Schema
.schema users
.tables
-- Backup
.backup backup.db-- Exit
.quit
Create indexes on columns used in WHERE, JOIN, ORDER BY
Avoid SELECT * in production
Use transactions for multiple operations
Regularly run ANALYZE and VACUUM
Backup before major schema changes
About
Comprehensive SQLite cheatsheet covering database management, CRUD, indexes, joins, transactions, FTS5, JSON, date functions, PRAGMA settings, performance tuning, and command-line tools. Includes 21 sections with syntax examples, best practices, and quick reference for beginners to advanced users.