SQL Fundamentals: SELECT, INSERT, UPDATE, DELETE Explained

Master the four core SQL operations—SELECT, INSERT, UPDATE, and DELETE—with clear syntax examples in SQLite. Perfect for developers getting started with databases.

# SQL Fundamentals: SELECT, INSERT, UPDATE, DELETE Explained Every application you build—from a simple todo app to a globally distributed edge database—relies on the same four core SQL operations: **SELECT**, **INSERT**, **UPDATE**, and **DELETE**. Together they form the CRUD backbone (Create, Read, Update, Delete) of every database-driven application. In this tutorial, we'll walk through each one with clear syntax and practical examples using SQLite, the engine that powers Turso's edge database platform. --- ## Table of Contents 1. [Setting Up: Our Example Table](#setting-up) 2. [SELECT — Reading Data](#select) 3. [INSERT — Adding Data](#insert) 4. [UPDATE — Modifying Data](#update) 5. [DELETE — Removing Data](#delete) 6. [Putting It All Together](#putting-it-together) 7. [Next Steps](#next-steps) --- ## Setting Up: Our Example Table Throughout this tutorial we'll use a simple `users` table: ```sql CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, email TEXT UNIQUE NOT NULL, role TEXT DEFAULT 'member', created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); ``` This table has five columns: an auto-incrementing ID, a name, a unique email, a role with a default value, and a timestamp. Let's populate it with some seed data: ```sql INSERT INTO users (name, email, role) VALUES ('Ada Lovelace', 'ada@example.com', 'admin'), ('Grace Hopper', 'grace@example.com', 'member'), ('Linus Torvalds', 'linus@example.com', 'member'); ``` Now we have three rows to work with. Let's dive into each operation. --- ## SELECT — Reading Data The `SELECT` statement is the most frequently used SQL operation. It retrieves rows from one or more tables. ### Basic SELECT ```sql SELECT name, email FROM users; ``` This returns the `name` and `email` columns for every row: | name | email | |------|-------| | Ada Lovelace | ada@example.com | | Grace Hopper | grace@example.com | | Linus Torvalds | linus@example.com | ### SELECT All Columns ```sql SELECT * FROM users; ``` The `*` wildcard returns every column. It's convenient for exploration, but in production code you should always list the specific columns you need for better performance and clarity. ### Filtering with WHERE ```sql SELECT name, email FROM users WHERE role = 'admin'; ``` | name | email | |------|-------| | Ada Lovelace | ada@example.com | You can combine multiple conditions with `AND` and `OR`: ```sql SELECT name, email FROM users WHERE role = 'member' AND name LIKE 'G%'; ``` ### Sorting with ORDER BY ```sql SELECT name, email FROM users ORDER BY name ASC; ``` Use `ASC` for ascending (default) or `DESC` for descending order: ```sql SELECT name, created_at FROM users ORDER BY created_at DESC; ``` ### Limiting Results ```sql SELECT name, email FROM users LIMIT 10; ``` In SQLite, `LIMIT` is especially useful for pagination. Combine it with `OFFSET` to skip rows: ```sql SELECT name, email FROM users LIMIT 10 OFFSET 20; ``` ### Aggregations ```sql SELECT role, COUNT(*) as count FROM users GROUP BY role; ``` | role | count | |------|-------| | admin | 1 | | member | 2 | Other aggregate functions available in SQLite include `MAX()`, `MIN()`, `AVG()`, and `SUM()`. --- ## INSERT — Adding Data The `INSERT` statement adds new rows to a table. ### Single Row Insert ```sql INSERT INTO users (name, email, role) VALUES ('Dennis Ritchie', 'dennis@example.com', 'member'); ``` Columns you omit will use their default values. In our table, `id` auto-increments and `created_at` defaults to the current timestamp. ### Insert Without Column Names ```sql INSERT INTO users VALUES (NULL, 'Dennis Ritchie', 'dennis@example.com', 'member', CURRENT_TIMESTAMP); ``` This works but is fragile—if you add or reorder columns later, the statement breaks. **Always specify column names** in production code. ### Multi-Row Insert ```sql INSERT INTO users (name, email, role) VALUES ('Dennis Ritchie', 'dennis@example.com', 'member'), ('Ken Thompson', 'ken@example.com', 'admin'), ('Brian Kernighan', 'brian@example.com', 'member'); ``` SQLite supports inserting multiple rows in a single statement, which is far more efficient than individual inserts—especially at the edge where network round-trips matter. ### Insert or Ignore ```sql INSERT OR IGNORE INTO users (name, email, role) VALUES ('Ada Lovelace', 'ada@example.com', 'admin'); ``` Since `email` has a `UNIQUE` constraint, this insert would normally fail. `OR IGNORE` silently skips it instead. You can also use `INSERT OR REPLACE` to overwrite the existing row. --- ## UPDATE — Modifying Data The `UPDATE` statement modifies existing rows. **Always include a `WHERE` clause**—without it, you'll update every row in the table. ### Basic Update ```sql UPDATE users SET role = 'admin' WHERE name = 'Grace Hopper'; ``` This promotes Grace to admin. After the update: ```sql SELECT name, role FROM users WHERE name = 'Grace Hopper'; ``` | name | role | |------|------| | Grace Hopper | admin | ### Updating Multiple Columns ```sql UPDATE users SET role = 'member', email = 'linus.t@example.com' WHERE name = 'Linus Torvalds'; ``` ### Conditional Updates ```sql UPDATE users SET role = 'admin' WHERE role = 'member' AND name LIKE 'D%'; ``` This promotes all members whose name starts with "D" to admin. ### Safe Update Pattern A defensive habit: run a `SELECT` first to verify which rows will be affected, then run the `UPDATE` with the same `WHERE` clause. ```sql -- Check first SELECT id, name, role FROM users WHERE role = 'member'; -- Then update UPDATE users SET role = 'admin' WHERE role = 'member'; ``` --- ## DELETE — Removing Data The `DELETE` statement removes rows from a table. Like `UPDATE`, **always use a `WHERE` clause** to avoid deleting everything. ### Basic Delete ```sql DELETE FROM users WHERE name = 'Dennis Ritchie'; ``` ### Delete with Multiple Conditions ```sql DELETE FROM users WHERE role = 'member' AND name LIKE 'K%'; ``` ### Delete All Rows (Use with Caution!) ```sql DELETE FROM users; ``` This removes every row but keeps the table structure intact. The auto-increment counter is not reset unless you also run: ```sql DELETE FROM sqlite_sequence WHERE name = 'users'; ``` ### Safe Delete Pattern Just like with updates, verify before you delete: ```sql -- Check first SELECT id, name FROM users WHERE role = 'member'; -- Then delete DELETE FROM users WHERE role = 'member'; ``` --- ## Putting It All Together Here's a realistic workflow that uses all four operations: ```sql -- 1. INSERT a new user INSERT INTO users (name, email, role) VALUES ('Margaret Hamilton', 'margaret@example.com', 'member'); -- 2. SELECT to verify SELECT * FROM users WHERE email = 'margaret@example.com'; -- 3. UPDATE to promote UPDATE users SET role = 'admin' WHERE email = 'margaret@example.com'; -- 4. DELETE a deactivated account DELETE FROM users WHERE email = 'margaret@example.com'; ``` ### Pro Tip: Use Transactions Wrap related operations in a transaction so they either all succeed or all roll back: ```sql BEGIN TRANSACTION; INSERT INTO users (name, email, role) VALUES ('Margaret Hamilton', 'margaret@example.com', 'admin'); UPDATE users SET role = 'member' WHERE email = 'ada@example.com'; COMMIT; ``` If anything fails before `COMMIT`, all changes are automatically rolled back. This is essential for data integrity. --- ## Next Steps Now that you've mastered the four fundamental SQL operations, here's where to go next: - **Practice with Turso** — Sign up for a free Turso account and run these examples against a real edge database in seconds. Turso uses SQLite under the hood, so everything in this tutorial works out of the box. - **Learn advanced querying** — Explore `JOIN`s, subqueries, window functions, and CTEs in our [Advanced SQL tutorial](/advanced-sql-window-functions-ctes-recursive-queries). - **Explore SQLite-specific features** — SQLite supports full-text search (FTS5), JSON operations, and vector search. Check out our [SQLite indexing guide](/sqlite-indexing-strategies-btree-fts5-vector-search) to learn more. - **Build something real** — Use Turso's TypeScript, Python, Go, or Rust SDKs to connect your application to a distributed SQLite database at the edge. SQL is a skill that pays dividends across every database you'll ever work with—SQLite, PostgreSQL, Oracle, MySQL, and beyond. Master these four operations and you've covered 80% of what you'll do in any database.