Best Practices
Learn SQL best practices for writing clean, maintainable, and secure database code.
Naming Conventions
Tables and Columns
- Use lowercase for table and column names
- Use underscores for multi-word names:
user_profiles - Use singular for table names:
usernotusers - Use descriptive names:
created_atnotdate
-- Good
CREATE TABLE user_profile (
id INTEGER PRIMARY KEY,
first_name TEXT NOT NULL,
last_name TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Avoid
CREATE TABLE up (
ID INT,
FN VARCHAR(50),
LN VARCHAR(50),
date_created DATETIME
);Primary Keys
- Use
idas the primary key column name - Use auto-incrementing integers or UUIDs
-- Good
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL
);
-- Also good (for distributed systems)
CREATE TABLE users (
id TEXT PRIMARY KEY DEFAULT (hex(randomblob(16))),
name TEXT NOT NULL
);Query Writing
Use Specific Columns
-- Good
SELECT id, name, email FROM users WHERE active = 1;
-- Avoid in production
SELECT * FROM users WHERE active = 1;Use Parameterized Queries
-- Good (parameterized)
SELECT * FROM users WHERE email = ?;
-- Bad (SQL injection vulnerable)
SELECT * FROM users WHERE email = '" + userInput + "';Consistent Formatting
-- Good
SELECT
users.name,
departments.name as department
FROM users
INNER JOIN departments ON users.department_id = departments.id
WHERE users.active = 1
ORDER BY users.name;
-- Harder to read
SELECT users.name, departments.name as department FROM users INNER JOIN departments ON users.department_id = departments.id WHERE users.active = 1 ORDER BY users.name;Performance Best Practices
Index Strategy
- Create indexes on frequently queried columns
- Use composite indexes for multi-column queries
- Don’t over-index (slows down writes)
-- Create indexes for common queries
CREATE INDEX idx_user_email ON users(email);
CREATE INDEX idx_user_active_created ON users(active, created_at);Query Optimization
- Use LIMIT for large result sets
- Avoid functions on indexed columns
- Use appropriate data types
-- Good
SELECT id, name FROM users WHERE active = 1 LIMIT 100;
-- Avoid (prevents index usage)
SELECT * FROM users WHERE UPPER(name) = 'JOHN';Security
Input Validation
- Validate all input data
- Use parameterized queries
- Implement proper error handling
-- Good (prepared statement)
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email");
$stmt->execute(['email' => $email]);Access Control
- Grant minimum necessary permissions
- Use different users for different applications
- Regular connection strings in configuration
-- Grant specific permissions
GRANT SELECT, INSERT, UPDATE ON app_db.users TO 'app_user'@'%';Documentation
Table Documentation
- Comment complex table structures
- Document business rules
- Use consistent naming that explains purpose
-- Users table: stores all registered user accounts
-- Business rule: email must be unique across all users
CREATE TABLE users (
id INTEGER PRIMARY KEY,
email TEXT UNIQUE NOT NULL, -- User's unique email address
name TEXT NOT NULL, -- Full display name
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- Account creation time
);Practice Exercises
Test your knowledge with these exercises:
-- 1. Find all users older than 30
-- 2. Count users by age group (under 25, 25-35, over 35)
-- 3. Find the highest paid employee in each department
-- 4. List departments with no employees
-- 5. Find users who haven't logged in in the last 30 daysResources
Congratulations! You’ve completed the SQL fundamentals tutorial. You now have the knowledge to create, query, and optimize relational databases.
Last updated on