问题描述
该笔记将记录:PostgreSQL 的基本使用方法,以及常见问题的解决办法。
数据库:连接与创建
### 切到到用户,
shell> su - postgres # 通过该用户连接,其是服务运行的默认用户
### 创建数据库
shell> createdb mydb
### 删除数据库
shell> dropdb mydb
### 访问数据库
shell> psql mydb
psql (14.4)
Type "help" for help.
mydb=> # 提示符,暗示当前为普通用户
mydb=# # 提示符,暗示当前为超级用户,不受管控
# 通常为安装用户来连接数据库
mydb=> SELECT version();
mydb=> SELECT current_date;
mydb=> \h
mydb=> \q
表:创建及常用操作
PostgreSQL: Documentation: 14: 2.3. Creating a New Table
CREATE TABLE weather (
city varchar(80),
temp_lo int, -- low temperature
temp_hi int, -- high temperature
prcp real, -- precipitation
date date
);
DROP TABLE tablename;
// ---------------------------------------------------------------------------- // 增
INSERT INTO cities VALUES ('San Francisco', '(-194.0, 53.0)');
COPY weather FROM '/home/user/weather.txt'; # 从扁平化的文件中复制数据
// ---------------------------------------------------------------------------- // 删
DELETE FROM weather WHERE city = 'Hayward';
// ---------------------------------------------------------------------------- // 改
UPDATE weather
SET temp_hi = temp_hi - 2,
WHERE date > '1994-11-28';
// ---------------------------------------------------------------------------- // 查
SELECT city, temp_lo, temp_hi, prcp, date FROM weather;
SELECT city, temp_lo, temp_hi, prcp, date, location
FROM weather JOIN cities ON city = name;
SELECT *
FROM weather LEFT OUTER JOIN cities ON weather.city = cities.name;
该数据库的高级特性
该部分我们将记录部分我们从未见过的高级特性,其他数据库常规特性我们将简单概括;
视图(View)
CREATE VIEW myview AS
SELECT name, temp_lo, temp_hi, prcp, date, location
FROM weather, cities
WHERE city = name;
SELECT * FROM myview;
外键(Foreign Key)
CREATE TABLE cities (
name varchar(80) primary key,
location point
);
CREATE TABLE weather (
city varchar(80) references cities(name),
temp_lo int,
temp_hi int,
prcp real,
date date
);
事务(Transaction)
BEGIN;
UPDATE accounts SET balance = balance - 100.00
WHERE name = 'Alice';
-- etc etc
COMMIT;
PostgreSQL 支持事物部分回滚:ROLLBACK TO
BEGIN;
UPDATE accounts SET balance = balance - 100.00
WHERE name = 'Alice';
SAVEPOINT my_savepoint; # 添加回滚点
UPDATE accounts SET balance = balance + 100.00
WHERE name = 'Bob';
-- oops ... forget that and use Wally's account
ROLLBACK TO my_savepoint; # 撤销到回滚点
UPDATE accounts SET balance = balance + 100.00
WHERE name = 'Wally';
COMMIT;
窗口函数(Window Function)
PostgreSQL: Documentation: 14: 3.5. Window Functions
窗口函数:允许我们将聚合的结果赋给每个行,同时数据并未被聚合;
SELECT depname, empno, salary, avg(salary) OVER (PARTITION BY depname) FROM empsalary;
depname | empno | salary | avg
-----------+-------+--------+-----------------------
develop | 11 | 5200 | 5020.0000000000000000
develop | 7 | 4200 | 5020.0000000000000000
develop | 9 | 4500 | 5020.0000000000000000
develop | 8 | 6000 | 5020.0000000000000000
develop | 10 | 5200 | 5020.0000000000000000
personnel | 5 | 3500 | 3700.0000000000000000
personnel | 2 | 3900 | 3700.0000000000000000
sales | 3 | 4800 | 4866.6666666666666667
sales | 1 | 5000 | 4866.6666666666666667
sales | 4 | 4800 | 4866.6666666666666667
(10 rows)
在示例中,虽然针对 depname 的 salary 计算平均数,但是凭据数被赋值给每个记录,而没有合并记录。
OVER:表示使用 Window Functoin
PARTITION BY:表示被分组的列;
ORDER BY:能够用于排序;
// ---------------------------------------------------------------------------- // 通过 ORDER BY 排序
SELECT depname, empno, salary,
rank() OVER (PARTITION BY depname ORDER BY salary DESC)
FROM empsalary;
depname | empno | salary | rank
-----------+-------+--------+------
develop | 8 | 6000 | 1
develop | 10 | 5200 | 2
develop | 11 | 5200 | 2
develop | 9 | 4500 | 4
develop | 7 | 4200 | 5
personnel | 2 | 3900 | 1
personnel | 5 | 3500 | 2
sales | 1 | 5000 | 1
sales | 4 | 4800 | 2
sales | 3 | 4800 | 2
(10 rows)
Window Frame 是指 Window Function 处理的范围:
// 如果即没有指定 ORDER BY 排序,且没有指定 PARTITION BY,则 Window Frame 为整个表,即针对所有的记录进行处理; SELECT salary, sum(salary) OVER () FROM empsalary; salary | sum --------+------- 5200 | 47100 5000 | 47100 3500 | 47100 4800 | 47100 3900 | 47100 4200 | 47100 4500 | 47100 4800 | 47100 6000 | 47100 5200 | 47100 (10 rows) // 如果已经指定 ORDER BY 排序,但没有指定 PARTITION BY,则 Window Frame 为整个表,即针对所有的记录进行处理,但是行为存在差异; SELECT salary, sum(salary) OVER (ORDER BY salary) FROM empsalary; salary | sum --------+------- 3500 | 3500 3900 | 7400 4200 | 11600 4500 | 16100 4800 | 25700 4800 | 25700 5000 | 30700 5200 | 41100 5200 | 41100 6000 | 47100 (10 rows) 注意,这里的数据是按照顺序进行累加的,并且如果目标字段值相同,则被忽略;
Window Function 别名的使用:
SELECT sum(salary) OVER w, avg(salary) OVER w FROM empsalary WINDOW w AS (PARTITION BY depname ORDER BY salary DESC);
Window Function 的应用范围:
SELECT depname, empno, salary, enroll_date
FROM
(SELECT depname, empno, salary, enroll_date,
rank() OVER (PARTITION BY depname ORDER BY salary DESC, empno) AS pos
FROM empsalary
) AS ss
WHERE pos < 3;
继承(Inheritance)
在 PostgreSQL 中,允许使用面向对象中继承特性:
// ---------------------------------------------------------------------------- // 这种做法类似于 UNION 特性
CREATE TABLE capitals (
name text,
population real,
elevation int, -- (in ft)
state char(2)
);
CREATE TABLE non_capitals (
name text,
population real,
elevation int -- (in ft)
);
CREATE VIEW cities AS
SELECT name, population, elevation FROM capitals
UNION
SELECT name, population, elevation FROM non_capitals;
// ---------------------------------------------------------------------------- // 如果使用继承,便会很简单;
CREATE TABLE cities (
name text,
population real,
elevation int -- (in ft)
);
CREATE TABLE capitals (
state char(2) UNIQUE NOT NULL
) INHERITS (cities);
// 如此,capitals 将具备 cities 的字段;
SELECT name, elevation
FROM cities
WHERE elevation > 500;
// 如下查询,将仅查询所有非 state 且 elevation 超过 500 的城市:
SELECT name, elevation
FROM ONLY cities
WHERE elevation > 500;