PostgreSQL SQL 基础
数据库操作
sql
-- 创建数据库
CREATE DATABASE dbname;
-- 删除数据库
DROP DATABASE dbname;
-- 重命名数据库
ALTER DATABASE old_name RENAME TO new_name;表操作
创建表
sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) NOT NULL,
age INTEGER DEFAULT 18,
status VARCHAR(20) DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- 带约束
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
total DECIMAL(10,2) CHECK (total >= 0),
status VARCHAR(20) DEFAULT 'pending',
UNIQUE(user_id, status)
);修改表结构
sql
-- 添加列
ALTER TABLE users ADD COLUMN phone VARCHAR(20);
-- 删除列
ALTER TABLE users DROP COLUMN phone;
-- 添加约束
ALTER TABLE users ADD CONSTRAINT email_unique UNIQUE(email);
-- 修改列类型
ALTER TABLE users ALTER COLUMN age TYPE SMALLINT;
-- 重命名列
ALTER TABLE users RENAME COLUMN age TO user_age;
-- 重命名表
ALTER TABLE users RENAME TO app_users;删除表
sql
DROP TABLE users;
DROP TABLE IF EXISTS users CASCADE;INSERT 插入数据
sql
-- 单行插入
INSERT INTO users (username, email, age)
VALUES ('zhangsan', 'zhangsan@example.com', 25);
-- 多行插入
INSERT INTO users (username, email, age) VALUES
('lisi', 'lisi@example.com', 30),
('wangwu', 'wangwu@example.com', 28),
('zhaoliu', 'zhaoliu@example.com', 35);
-- 从查询结果插入
INSERT INTO users (username, email)
SELECT username, email FROM old_users WHERE status = 'active';
-- 带 ON CONFLICT 处理
INSERT INTO users (username, email)
VALUES ('zhangsan', 'new@example.com')
ON CONFLICT (username) DO UPDATE SET email = EXCLUDED.email;
-- 带 RETURNING
INSERT INTO users (username, email)
VALUES ('test', 'test@example.com')
RETURNING id, username;SELECT 查询数据
基本查询
sql
-- 查询所有列
SELECT * FROM users;
-- 查询指定列
SELECT username, email FROM users;
-- 带别名
SELECT username AS "用户名", email AS "邮箱" FROM users;
-- 去重
SELECT DISTINCT status FROM users;
-- 限制结果
SELECT * FROM users LIMIT 10 OFFSET 20;条件查询
sql
-- WHERE 子句
SELECT * FROM users WHERE age >= 18;
SELECT * FROM users WHERE status = 'active' AND age > 25;
SELECT * FROM users WHERE status IN ('active', 'pending');
SELECT * FROM users WHERE username LIKE 'zhang%';
SELECT * FROM users WHERE username ILIKE '%ZHANG%'; -- 不区分大小写
-- NULL 处理
SELECT * FROM users WHERE email IS NULL;
SELECT * FROM users WHERE email IS NOT NULL;
SELECT COALESCE(email, 'no-email@example.com') FROM users;排序
sql
SELECT * FROM users ORDER BY age ASC;
SELECT * FROM users ORDER BY age DESC;
SELECT * FROM users ORDER BY status, age DESC;
SELECT * FROM users ORDER BY age NULLS LAST;分组聚合
sql
-- 分组
SELECT status, COUNT(*) FROM users GROUP BY status;
SELECT status, AVG(age) FROM users GROUP BY status;
-- HAVING 过滤分组
SELECT status, COUNT(*)
FROM users
GROUP BY status
HAVING COUNT(*) > 5;
-- 聚合函数
SELECT
COUNT(*) AS total,
COUNT(DISTINCT status) AS status_count,
AVG(age) AS avg_age,
SUM(age) AS sum_age,
MIN(age) AS min_age,
MAX(age) AS max_age
FROM users;多表查询
sql
-- 连接类型
SELECT u.username, o.total
FROM users u
INNER JOIN orders o ON u.id = o.user_id;
SELECT u.username, o.total
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;
SELECT u.username, o.total
FROM users u
RIGHT JOIN orders o ON u.id = o.user_id;
SELECT u.username, o.total
FROM users u
FULL OUTER JOIN orders o ON u.id = o.user_id;
-- 交叉连接(笛卡尔积)
SELECT * FROM users CROSS JOIN statuses;
-- 自连接
SELECT a.username, b.username AS friend
FROM users a
JOIN friends f ON a.id = f.user_id
JOIN users b ON b.id = f.friend_id;子查询
sql
-- WHERE 中的子查询
SELECT * FROM users WHERE age > (SELECT AVG(age) FROM users);
-- FROM 中的子查询
SELECT status, avg_age
FROM (SELECT status, AVG(age) AS avg_age FROM users GROUP BY status) t
WHERE avg_age > 25;
-- EXISTS
SELECT * FROM users u WHERE EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id
);
-- IN
SELECT * FROM users WHERE id IN (
SELECT user_id FROM orders WHERE total > 100
);高级查询
sql
-- CASE 表达式
SELECT
username,
age,
CASE
WHEN age < 18 THEN '未成年'
WHEN age < 30 THEN '青年'
WHEN age < 60 THEN '中年'
ELSE '老年'
END AS age_group
FROM users;
-- 窗口函数
SELECT
username,
age,
AVG(age) OVER () AS avg_age,
RANK() OVER (ORDER BY age DESC) AS age_rank,
ROW_NUMBER() OVER (ORDER BY age DESC) AS row_num,
SUM(age) OVER (PARTITION BY status ORDER BY age) AS running_sum
FROM users;
-- CTE(公用表表达式)
WITH active_users AS (
SELECT * FROM users WHERE status = 'active'
),
avg_age AS (
SELECT AVG(age) AS avg FROM active_users
)
SELECT * FROM active_users WHERE age > (SELECT avg FROM avg_age);UPDATE 更新数据
sql
-- 基本更新
UPDATE users SET age = 30 WHERE username = 'zhangsan';
-- 多列更新
UPDATE users
SET age = 30, status = 'inactive', updated_at = NOW()
WHERE username = 'zhangsan';
-- 带子查询
UPDATE users
SET age = (SELECT AVG(age) FROM users)
WHERE status = 'inactive';
-- 带 RETURNING
UPDATE users SET age = 35 WHERE username = 'lisi' RETURNING *;DELETE 删除数据
sql
-- 基本删除
DELETE FROM users WHERE username = 'zhangsan';
-- 带子查询
DELETE FROM users WHERE id IN (
SELECT id FROM users WHERE created_at < '2024-01-01'
);
-- 删除所有数据
DELETE FROM users;
TRUNCATE TABLE users RESTART IDENTITY CASCADE;事务控制
sql
-- 开始事务
BEGIN;
-- 或
START TRANSACTION;
-- 提交
COMMIT;
-- 回滚
ROLLBACK;
-- 保存点
SAVEPOINT sp1;
ROLLBACK TO SAVEPOINT sp1;
RELEASE SAVEPOINT sp1;
-- 事务示例
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE user_id = 2;
COMMIT; -- 或 ROLLBACK;索引
sql
-- 创建索引
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_status_age ON users(status, age);
CREATE UNIQUE INDEX idx_users_username ON users(username);
-- 表达式索引
CREATE INDEX idx_users_lower_email ON users(LOWER(email));
-- 部分索引
CREATE INDEX idx_users_active ON users(username) WHERE status = 'active';
-- 重建索引
REINDEX INDEX idx_users_email;
-- 删除索引
DROP INDEX idx_users_email;