Manipulating Data with SQL DML

1. Inserting Single Rows

FormExample
Explicit columnsINSERT INTO t(a,b) VALUES (1,2);
All columnsINSERT INTO t VALUES (1,2,3); (fragile)
DEFAULTINSERT INTO t(a) VALUES (DEFAULT);
RETURNINGINSERT ... RETURNING id; (PG, Oracle 23ai)

2. Inserting Multiple Rows

Example: Multi-row Insert

INSERT INTO products(sku, name, price) VALUES
  ('A1','Widget', 9.99),
  ('A2','Gadget',19.99),
  ('A3','Gizmo', 29.99);
TipDetail
Batch size1k-10k per statement balances memory + network
COPY (Postgres)10–100× faster than INSERT for bulk
LOAD DATA (MySQL)High-speed CSV loader

3. Inserting from SELECT

FormExample
Copy dataINSERT INTO archive_orders SELECT * FROM orders WHERE placed_at < '2024-01-01';
TransformUse expressions in SELECT
CREATE TABLE ASOne-shot create + populate

4. Updating Rows

FormExample
Single colUPDATE t SET a=1 WHERE id=42;
Multiple colsUPDATE t SET a=1, b=2 WHERE id=42;
RETURNING (PG)Returns affected rows
Always WHEREMissing WHERE updates ALL rows
Warning: Always test UPDATE/DELETE as SELECT ... WHERE ... first. In production, wrap in transactions with BEGIN/ROLLBACK rehearsal.

5. Updating with Joins

Example: UPDATE FROM (Postgres)

UPDATE products p
SET price = p.price * 1.10
FROM categories c
WHERE p.category_id = c.id AND c.name = 'Electronics';
DBSyntax
PostgresUPDATE ... FROM ... WHERE
MySQLUPDATE t1 JOIN t2 ON ... SET ...
SQL ServerUPDATE t1 SET ... FROM t1 JOIN t2 ...
OracleUse MERGE or updatable subquery

6. Deleting Rows

FormExample
BasicDELETE FROM t WHERE id=42;
With join (PG)DELETE FROM t USING ref WHERE t.x=ref.y;
RETURNING (PG)Get deleted rows
Soft deleteUPDATE t SET deleted_at = NOW() ...

7. Truncating Tables

AspectTRUNCATE vs DELETE
SpeedTRUNCATE: O(1) metadata op; DELETE: per-row
TriggersTRUNCATE skips row triggers (Postgres can fire stmt triggers)
TransactionalPostgres: yes; MySQL InnoDB: yes; Oracle: implicit COMMIT
RESTART IDENTITYReset sequence values
CASCADETruncate dependent tables

8. Using MERGE/UPSERT

DBSyntax
SQL standardMERGE INTO ... USING ... ON ... WHEN MATCHED/NOT MATCHED
Postgres 15+ NEWSupports MERGE
Postgres altINSERT ... ON CONFLICT DO UPDATE
MySQLINSERT ... ON DUPLICATE KEY UPDATE
SQLiteINSERT ... ON CONFLICT ... or INSERT OR REPLACE

Example: MERGE

MERGE INTO target t
USING source s ON t.id = s.id
WHEN MATCHED THEN UPDATE SET name = s.name, updated_at = NOW()
WHEN NOT MATCHED THEN INSERT (id, name) VALUES (s.id, s.name);

9. Returning Affected Rows

MechanismDetail
RETURNING (PG)Get inserted/updated/deleted columns
OUTPUT (SQL Server)Same concept
ROW_COUNT()MySQL function: # rows affected
Driver APIcursor.rowcount, PreparedStatement.getUpdateCount

10. Handling DML Errors

StrategyDetail
TransactionsBEGIN/COMMIT/ROLLBACK
SAVEPOINTPartial rollback within tx
ON CONFLICT DO NOTHINGSkip violators silently
Try/catch (driver)Map SQLSTATE → app errors
Retry on serialization failureDetect 40001 and replay