Appearance
高级特性
窗口函数
基本语法
sql
SELECT
name,
salary,
ROW_NUMBER() OVER (ORDER BY salary DESC) AS rank
FROM employees;ROW_NUMBER / RANK / DENSE_RANK
sql
SELECT
name,
salary,
ROW_NUMBER() OVER (ORDER BY salary DESC) AS row_num,
RANK() OVER (ORDER BY salary DESC) AS rank,
DENSE_RANK() OVER (ORDER BY salary DESC) AS dense_rank
FROM employees;分区窗口函数
sql
SELECT
name,
department,
salary,
RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS dept_rank
FROM employees;聚合窗口函数
sql
SELECT
name,
department,
salary,
SUM(salary) OVER (PARTITION BY department) AS dept_total,
AVG(salary) OVER (PARTITION BY department) AS dept_avg,
COUNT(*) OVER (PARTITION BY department) AS dept_count
FROM employees;LAG 和 LEAD
sql
SELECT
name,
salary,
LAG(salary, 1) OVER (ORDER BY salary) AS prev_salary,
LEAD(salary, 1) OVER (ORDER BY salary) AS next_salary
FROM employees;FIRST_VALUE 和 LAST_VALUE
sql
SELECT
name,
department,
salary,
FIRST_VALUE(salary) OVER (PARTITION BY department ORDER BY salary DESC) AS max_in_dept,
LAST_VALUE(salary) OVER (PARTITION BY department ORDER BY salary DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS min_in_dept
FROM employees;JSON 操作
JSON 类型
sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
data JSON,
profile JSONB
);插入 JSON 数据
sql
INSERT INTO users (data, profile) VALUES
('{"name": "张三", "age": 25}', '{"name": "张三", "age": 25}'),
('{"name": "李四", "skills": ["Java", "Python"]}', '{"name": "李四", "skills": ["Java", "Python"]}');提取 JSON 值
sql
SELECT data->>'name' FROM users;
SELECT data->'age' FROM users;
SELECT profile->'skills'->0 FROM users;
SELECT data#>>'{skills,0}' FROM users;JSON 操作符
| 操作符 | 说明 | | ------ | -------------------------- | ---------- | | -> | 获取 JSON 对象字段(JSON) | | ->> | 获取 JSON 对象字段(文本) | | #> | 获取 JSON 路径(JSON) | | #>> | 获取 JSON 路径(文本) | | @> | 包含 | | <@ | 被包含 | | ? | 键存在 | | ? | | 任一键存在 | | ?& | 所有键存在 |
JSON 函数
sql
SELECT json_typeof(data) FROM users;
SELECT json_array_length(data->'skills') FROM users;
SELECT json_extract_path_text(data, 'name') FROM users;
SELECT json_build_object('name', '张三', 'age', 25);
SELECT json_agg(name) FROM users;
SELECT json_object_agg(name, age) FROM users;JSONB 操作
sql
UPDATE users SET profile = profile || '{"city": "北京"}'::jsonb WHERE id = 1;
UPDATE users SET profile = profile - 'city' WHERE id = 1;
UPDATE users SET profile = profile || '{"age": 26}'::jsonb WHERE id = 1;数组操作
创建数组
sql
CREATE TABLE posts (
id SERIAL PRIMARY KEY,
title VARCHAR(100),
tags VARCHAR[]
);
INSERT INTO posts (title, tags) VALUES ('文章1', ARRAY['技术', '数据库']);
INSERT INTO posts (title, tags) VALUES ('文章2', '{"开发", "编程"}');访问数组
sql
SELECT tags[1] FROM posts;
SELECT tags[1:2] FROM posts;
SELECT array_length(tags, 1) FROM posts;数组操作符
| 操作符 | 说明 | | ------ | ------ | --- | ---- | | = | 等于 | | <> | 不等于 | | @> | 包含 | | <@ | 被包含 | | && | 重叠 | | | | | 连接 |
数组函数
sql
SELECT unnest(tags) FROM posts;
SELECT array_append(tags, '新标签') FROM posts;
SELECT array_remove(tags, '技术') FROM posts;
SELECT array_position(tags, '技术') FROM posts;
SELECT cardinality(tags) FROM posts;数组查询
sql
SELECT * FROM posts WHERE '技术' = ANY(tags);
SELECT * FROM posts WHERE tags @> ARRAY['技术'];
SELECT * FROM posts WHERE tags && ARRAY['技术', '开发'];全文搜索
创建全文搜索索引
sql
ALTER TABLE articles ADD COLUMN search_vector tsvector;
UPDATE articles SET search_vector =
to_tsvector('english', title || ' ' || content);
CREATE INDEX idx_search ON articles USING GIN(search_vector);全文搜索查询
sql
SELECT * FROM articles
WHERE search_vector @@ to_tsquery('postgresql & database');
SELECT * FROM articles
WHERE search_vector @@ plainto_tsquery('PostgreSQL database');
SELECT * FROM articles
WHERE search_vector @@ websearch_to_tsquery('PostgreSQL OR database');全文搜索函数
sql
SELECT to_tsvector('hello world');
SELECT to_tsquery('hello & world');
SELECT plainto_tsquery('hello world');
SELECT ts_rank(search_vector, to_tsquery('postgresql')) FROM articles;
SELECT ts_headline(content, to_tsquery('postgresql')) FROM articles;表继承
创建继承表
sql
CREATE TABLE persons (
id SERIAL PRIMARY KEY,
name VARCHAR(50),
city VARCHAR(50)
);
CREATE TABLE employees (
salary DECIMAL(10, 2),
department VARCHAR(50)
) INHERITS (persons);查询继承表
sql
SELECT * FROM persons;
SELECT * FROM ONLY persons;
SELECT * FROM employees;插入数据
sql
INSERT INTO persons (name, city) VALUES ('张三', '北京');
INSERT INTO employees (name, city, salary, department)
VALUES ('李四', '上海', 10000, 'IT');视图
创建视图
sql
CREATE VIEW active_users AS
SELECT id, name, email FROM users WHERE status = 'active';
CREATE OR REPLACE VIEW active_users AS
SELECT id, name, email, age FROM users WHERE status = 'active';物化视图
sql
CREATE MATERIALIZED VIEW user_stats AS
SELECT
user_id,
COUNT(*) as order_count,
SUM(amount) as total_amount
FROM orders
GROUP BY user_id;
REFRESH MATERIALIZED VIEW user_stats;
REFRESH MATERIALIZED VIEW CONCURRENTLY user_stats;删除视图
sql
DROP VIEW active_users;
DROP MATERIALIZED VIEW user_stats;触发器
创建触发器函数
sql
CREATE OR REPLACE FUNCTION update_modified_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;创建触发器
sql
CREATE TRIGGER update_users_modtime
BEFORE UPDATE ON users
FOR EACH ROW
EXECUTE FUNCTION update_modified_column();删除触发器
sql
DROP TRIGGER update_users_modtime ON users;存储过程
创建函数
sql
CREATE OR REPLACE FUNCTION get_user_by_id(user_id INTEGER)
RETURNS TABLE(id INTEGER, name VARCHAR, email VARCHAR) AS $$
BEGIN
RETURN QUERY SELECT u.id, u.name, u.email FROM users u WHERE u.id = user_id;
END;
$$ LANGUAGE plpgsql;调用函数
sql
SELECT * FROM get_user_by_id(1);创建存储过程
sql
CREATE OR REPLACE PROCEDURE transfer_money(
from_id INTEGER,
to_id INTEGER,
amount DECIMAL
)
LANGUAGE plpgsql
AS $$
BEGIN
UPDATE accounts SET balance = balance - amount WHERE id = from_id;
UPDATE accounts SET balance = balance + amount WHERE id = to_id;
COMMIT;
END;
$$;调用存储过程
sql
CALL transfer_money(1, 2, 100);