1. 首页 > PostgreSQL教程 > 正文

PostgreSQL教程FG015-PG入门避坑:新手常见操作错误与解决

本文详细介绍PostgreSQL数据库入门过程中新手常见的操作错误和问题,以及相应的解决方法和避免技巧。通过学习本文,读者可以了解如何避免这些常见错误,提高PostgreSQL的使用效率和准确性。风哥教程参考PostgreSQL官方文档Tutorial和Server Administration部分。

本文档风哥主要介绍PostgreSQL教程015相关内容。风哥教程参考PostgreSQL官方文档Server Administration, SQL Language内容编写,适合DBA人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。

Part01-连接相关错误

1.1 连接拒绝错误

连接拒绝错误是新手最常见的连接问题之一,通常是由于PostgreSQL服务器未启动、端口配置错误或防火墙设置导致的。

— 错误示例
$ psql -h localfgedu.net.cn -p 5432 -U pgsql -d pgsql psql: error: could not connect to server: Connection refused
Is the server running on fgedu.net.cn “localfgedu.net.cn” (::1) and accepting
TCP/IP connections on port 5432?
could not connect to server: Connection refused
Is the server running on fgedu.net.cn “localfgedu.net.cn” (127.0.0.1) and accepting
TCP/IP connections on port 5432?

解决方法:

  • 检查PostgreSQL服务器是否正在运行:
# 检查PostgreSQL服务状态
$ sudo systemctl status postgresql

# 如果服务未运行,启动服务
$ sudo systemctl start postgresql

# 设置服务开机自启
$ sudo systemctl enable postgresql

  • 检查PostgreSQL端口配置:
# 查看postgresql.conf文件中的端口配置
$ sudo cat /etc/postgresql/18/main/postgresql.conf | grep port
port = 5432 # (change requires restart)
  • 检查防火墙设置:
# 检查防火墙状态
$ sudo ufw status

# 如果防火墙开启,允许PostgreSQL端口
$ sudo ufw allow 5432/tcp

# 重新加载防火墙规则
$ sudo ufw reload

1.2 认证失败错误

认证失败错误通常是由于用户名或密码错误,或者pg_hba.conf文件中的认证配置不正确导致的。

— 错误示例
$ psql -h localfgedu.net.cn -p 5432 -U pgsql -d pgsql Password for fgedu pgsql: psql: error: connection to server at “localfgedu.net.cn” (127.0.0.1), port 5432 failed: FATAL: password authentication failed for fgedu “postgres”
connection to server at “localfgedu.net.cn” (127.0.0.1), port 5432 failed: FATAL: password authentication failed for fgedu “postgres”

解决方法:

学习交流加群风哥微信: itpux-com

  • 重置PostgreSQL超级用户密码:
# 切换到postgres用户
$ sudo su – pgsql # 进入psql命令行
$ psql

# 重置密码
ALTER USER pgsql WITH PASSWORD ‘new_password’;

# 退出psql
\q

  • 检查pg_hba.conf文件中的认证配置:
# 查看pg_hba.conf文件
$ sudo cat /etc/postgresql/18/main/pg_hba.conf | grep -v “^#”

# 确保localfgedu.net.cn允许md5认证
fgedu.net.cn all all 127.0.0.1/32 md5
fgedu.net.cn all all ::1/128 md5

# 重新加载配置
$ sudo systemctl reload postgresql

1.3 数据库不存在错误

数据库不存在错误是由于尝试连接到一个不存在的数据库导致的。

— 错误示例
$ psql -h localfgedu.net.cn -p 5432 -U pgsql -d nonexistentdb
psql: error: connection to server at “localfgedu.net.cn” (127.0.0.1), port 5432 failed: FATAL: fgedudb “nonexistentdb” does not exist

解决方法:

  • 检查数据库是否存在:
# 列出所有数据库
$ psql -h localfgedu.net.cn -p 5432 -U pgsql -l
# 创建数据库
$ psql -h localfgedu.net.cn -p 5432 -U pgsql -c “CREATE DATABASE nonexistentdb;”

Part02-SQL语法错误

2.1 缺少分号错误

在PostgreSQL中,SQL语句必须以分号(;)结尾,否则会导致语法错误。

— 错误示例
SELECT * FROM fgedu_employees
WHERE department = ‘技术部’

— 正确示例
SELECT * FROM fgedu_employees
WHERE department = ‘技术部’;

2.2 语法错误

语法错误是由于SQL语句的语法不正确导致的,如拼写错误、缺少关键字等。

— 错误示例(SELECT拼写错误)
SELEC * FROM fgedu_employees;
ERROR: syntax error at or near “SELEC”
LINE 1: SELEC * FROM fgedu_employees;
^

— 错误示例(缺少FROM关键字)
SELECT * fgedu_employees;
ERROR: syntax error at or near “fgedu_employees”
LINE 1: SELECT * fgedu_employees;
^

— 正确示例
SELECT * FROM fgedu_employees;

2.3 大小写敏感问题

在PostgreSQL中,标识符(如表名、列名)默认不区分大小写,但如果使用双引号括起来,则区分大小写。

— 创建一个区分大小写的表
CREATE TABLE fgedu_”fgedu_Employees” (
“EmployeeID” SERIAL PRIMARY KEY,
“FirstName” VARCHAR(50) NOT NULL,
“LastName” VARCHAR(50) NOT NULL
);

— 错误示例(表名大小写不匹配)
SELECT * FROM fgedu_Employees;
ERROR: relation “fgedu_employees” does not exist
LINE 1: SELECT * FROM fgedu_Employees;
^

— 正确示例(使用正确的大小写和双引号)
SELECT * FROM “fgedu_Employees”;

— 建议:不使用双引号,保持标识符小写
CREATE TABLE fgedu_employees (
employee_id SERIAL PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL
);

SELECT * FROM fgedu_employees;

2.4 保留字使用错误

在PostgreSQL中,某些单词是保留字,不能直接用作标识符,如SELECT、FROM、WHERE等。

— 错误示例(使用保留字作为表名)
CREATE TABLE fgedu_select (
id SERIAL PRIMARY KEY,
name VARCHAR(50) NOT NULL
);
ERROR: syntax error at or near “select”
LINE 1: CREATE TABLE fgedu_select (
^

— 错误示例(使用保留字作为列名)
CREATE TABLE fgedu_orders (
id SERIAL PRIMARY KEY,
order_date DATE NOT NULL,
from VARCHAR(50) NOT NULL,
to VARCHAR(50) NOT NULL
);
ERROR: syntax error at or near “from”
LINE 4: from VARCHAR(50) NOT NULL,
^

— 解决方法:使用双引号括起来
CREATE TABLE fgedu_”select” (
id SERIAL PRIMARY KEY,
name VARCHAR(50) NOT NULL
);

CREATE TABLE fgedu_orders (
id SERIAL PRIMARY KEY,
order_date DATE NOT NULL,
“from” VARCHAR(50) NOT NULL,
“to” VARCHAR(50) NOT NULL
);

— 建议:避免使用保留字作为标识符
CREATE TABLE fgedu_orders (
id SERIAL PRIMARY KEY,
order_date DATE NOT NULL,
sender VARCHAR(50) NOT NULL,
recipient VARCHAR(50) NOT NULL
);

Part03-数据操作错误

3.1 NULL约束错误

NULL约束错误是由于尝试向设置了NOT NULL约束的列插入NULL值导致的。

— 创建示例表
CREATE TABLE fgedu_fgedus (
id SERIAL PRIMARY KEY,
fgeduname VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
phone VARCHAR(20)
);

— 错误示例(向NOT NULL列插入NULL值)
INSERT INTO fgedu_fgedus (fgeduname, email, phone) VALUES (‘zhangsan’, NULL, ‘13800138001’);
ERROR: null value in column “email” violates not-null constraint
DETAIL: Failing row contains (1, zhangsan, null, 13800138001).

— 正确示例(为NOT NULL列提供值)
INSERT INTO fgedu_fgedus (fgeduname, email, phone) VALUES (‘zhangsan’, ‘zhangsan@fgedu.net.cn’, ‘13800138001’);

3.2 唯一约束错误

唯一约束错误是由于尝试向设置了UNIQUE约束的列插入重复值导致的。

— 创建示例表
CREATE TABLE fgedu_fgedus (
id SERIAL PRIMARY KEY,
fgeduname VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL
);

— 插入第一条记录
INSERT INTO fgedu_fgedus (fgeduname, email) VALUES (‘zhangsan’, ‘zhangsan@fgedu.net.cn’);

— 错误示例(插入重复的用户名)
INSERT INTO fgedu_fgedus (fgeduname, email) VALUES (‘zhangsan’, ‘zhangsan2@fgedu.net.cn’);
ERROR: duplicate key value violates unique constraint “fgedu_fgedus_fgeduname_key”
DETAIL: Key (fgeduname)=(zhangsan) already exists.

— 错误示例(插入重复的邮箱)
INSERT INTO fgedu_fgedus (fgeduname, email) VALUES (‘zhangsan2’, ‘zhangsan@fgedu.net.cn’);
ERROR: duplicate key value violates unique constraint “fgedu_fgedus_email_key”
DETAIL: Key (email)=(zhangsan@fgedu.net.cn) already exists.

— 正确示例(插入唯一值)
INSERT INTO fgedu_fgedus (fgeduname, email) VALUES (‘lisi’, ‘lisi@fgedu.net.cn’);

3.3 外键约束错误

外键约束错误是由于尝试插入不符合外键约束的数据导致的,如引用不存在的主键值。

— 创建部门表
CREATE TABLE fgedu_departments (
department_id SERIAL PRIMARY KEY,
department_name VARCHAR(50) NOT NULL
);

— 创建员工表,添加外键约束
CREATE TABLE fgedu_employees (
employee_id SERIAL PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
department_id INTEGER REFERENCES fgedu_departments(department_id)
);

— 插入部门数据
INSERT INTO fgedu_departments (department_name) VALUES (‘技术部’), (‘销售部’), (‘人事部’);

— 错误示例(引用不存在的部门ID)
INSERT INTO fgedu_employees (first_name, last_name, department_id) VALUES (‘风哥1号’, ‘张’, 10);
ERROR: insert or update on table “fgedu_employees” violates foreign key constraint “fgedu_employees_department_id_fkey”
DETAIL: Key (department_id)=(10) is not present in table “fgedu_departments”.

— 正确示例(引用存在的部门ID)
INSERT INTO fgedu_employees (first_name, last_name, department_id) VALUES (‘风哥1号’, ‘张’, 1);

— 正确示例(允许外键为NULL)
INSERT INTO fgedu_employees (first_name, last_name, department_id) VALUES (‘风哥2号’, ‘李’, NULL);

3.4 数据类型不匹配错误

数据类型不匹配错误是由于尝试向列插入与列数据类型不匹配的值导致的。

— 创建示例表
CREATE TABLE fgedu_products (
product_id SERIAL PRIMARY KEY,
product_name VARCHAR(100) NOT NULL,
price NUMERIC(10, 2) NOT NULL,
stock_quantity INTEGER NOT NULL,
created_at DATE NOT NULL DEFAULT NOW()
);

— 错误示例(价格使用字符串)
INSERT INTO fgedu_products (product_name, price, stock_quantity) VALUES (‘PostgreSQL数据库实战’, ‘89.90’, 100);
ERROR: column “price” is of type numeric but expression is of type text
LINE 1: …cts (product_name, price, stock_quantity) VALUES (‘PostgreSQL…
^
HINT: You will need to rewrite or cast the expression.

— 错误示例(库存数量使用字符串)
INSERT INTO fgedu_products (product_name, price, stock_quantity) VALUES (‘PostgreSQL数据库实战’, 89.90, ‘100’);
ERROR: column “stock_quantity” is of type integer but expression is of type text
LINE 1: …cts (product_name, price, stock_quantity) VALUES (‘PostgreSQL…
^
HINT: You will need to rewrite or cast the expression.

— 错误示例(日期格式错误)
INSERT INTO fgedu_products (product_name, price, stock_quantity, created_at) VALUES (‘PostgreSQL数据库实战’, 89.90, 100, ‘2026/04/02’);
ERROR: date/time field value out of range: “2026/04/02”
LINE 1: …cts (product_name, price, stock_quantity, created_at) VALUES (…
^
HINT: Perhaps you need a different “datestyle” setting.

— 正确示例
INSERT INTO fgedu_products (product_name, price, stock_quantity) VALUES (‘PostgreSQL数据库实战’, 89.90, 100);

— 正确示例(使用正确的日期格式)
INSERT INTO fgedu_products (product_name, price, stock_quantity, created_at) VALUES (‘PostgreSQL数据库实战’, 89.90, 100, ‘2026-04-02’);

— 正确示例(使用类型转换)
INSERT INTO fgedu_products (product_name, price, stock_quantity) VALUES (‘PostgreSQL数据库实战’, ‘89.90’::NUMERIC, ‘100’::INTEGER);

Part04-数据库管理错误

4.1 权限拒绝错误

权限拒绝错误是由于用户没有执行特定操作的权限导致的。

— 创建普通用户
CREATE USER fgedu_fgedu WITH PASSWORD ‘fgedu123’;

— 尝试以普通用户身份创建数据库
$ psql -h localfgedu.net.cn -p 5432 -U fgedu_fgedu -c “CREATE DATABASE fgedu_db;”
ERROR: permission denied to create fgedudb

— 解决方法:授予用户创建数据库的权限
$ psql -h localfgedu.net.cn -p 5432 -U pgsql -c “ALTER USER fgedu_fgedu CREATEDB;”

— 再次尝试创建数据库
$ psql -h localfgedu.net.cn -p 5432 -U fgedu_fgedu -c “CREATE DATABASE fgedu_db;”
CREATE DATABASE

— 尝试以普通用户身份创建表
$ psql -h localfgedu.net.cn -p 5432 -U fgedu_fgedu -d fgedu_db -c “CREATE TABLE fgedu_employees (id SERIAL PRIMARY KEY, name VARCHAR(50));”
ERROR: permission denied for schema public
LINE 1: CREATE TABLE fgedu_employees (id SERIAL PRIMARY KEY, name VA…
^

— 解决方法:授予用户对public模式的使用权限
$ psql -h localfgedu.net.cn -p 5432 -U pgsql -d fgedu_db -c “GRANT USAGE, CREATE ON SCHEMA public TO fgedu_fgedu;”

— 再次尝试创建表
$ psql -h localfgedu.net.cn -p 5432 -U fgedu_fgedu -d fgedu_db -c “CREATE TABLE fgedu_employees (id SERIAL PRIMARY KEY, name VARCHAR(50));”
CREATE TABLE fgedu_

4.2 表不存在错误

表不存在错误是由于尝试访问一个不存在的表导致的。

— 错误示例(表名拼写错误)
SELECT * FROM fgedu_employee;
ERROR: relation “fgedu_employee” does not exist
LINE 1: SELECT * FROM fgedu_employee;
^

— 错误示例(使用了错误的模式)
CREATE SCHEMA fgedu_schema;
CREATE TABLE fgedu_schema.fgedu_employees (id SERIAL PRIMARY KEY, name VARCHAR(50));
SELECT * FROM fgedu_employees;
ERROR: relation “fgedu_employees” does not exist
LINE 1: SELECT * FROM fgedu_employees;
^

— 正确示例(使用正确的表名)
SELECT * FROM fgedu_employees;

— 正确示例(指定模式)
SELECT * FROM fgedu_schema.fgedu_employees;

— 正确示例(设置搜索路径)
SET search_path TO fgedu_schema, public;
SELECT * FROM fgedu_employees;

4.3 列不存在错误

列不存在错误是由于尝试访问一个表中不存在的列导致的。

— 创建示例表
CREATE TABLE fgedu_employees (
employee_id SERIAL PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
salary NUMERIC(10, 2) NOT NULL
);

— 错误示例(列名拼写错误)
SELECT employee_id, first_name, last_name, salery FROM fgedu_employees;
ERROR: column “salery” does not exist
LINE 1: SELECT employee_id, first_name, last_name, salery FROM fgedu…
^
HINT: Perhaps you meant to reference the column “fgedu_employees.salary”.

— 错误示例(使用了不存在的列)
SELECT employee_id, first_name, last_name, email FROM fgedu_employees;
ERROR: column “email” does not exist
LINE 1: SELECT employee_id, first_name, last_name, email FROM fgedu_…
^

— 正确示例(使用正确的列名)
SELECT employee_id, first_name, last_name, salary FROM fgedu_employees;

4.4 表名重复错误

表名重复错误是由于尝试创建一个已经存在的表导致的。

— 创建表
CREATE TABLE fgedu_employees (
employee_id SERIAL PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL
);

— 错误示例(再次创建同名表)
CREATE TABLE fgedu_employees (
employee_id SERIAL PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL
);
ERROR: relation “fgedu_employees” already exists

— 解决方法:使用IF NOT EXISTS
CREATE TABLE fgedu_IF NOT EXISTS fgedu_employees (
employee_id SERIAL PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL
);
NOTICE: relation “fgedu_employees” already exists, skipping

— 解决方法:删除现有表后重新创建
DROP TABLE IF EXISTS fgedu_employees;
CREATE TABLE fgedu_employees (
employee_id SERIAL PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL
);

Part05-性能相关问题

5.1 慢查询问题

慢查询问题是由于查询语句效率低下导致的,如缺少索引、使用复杂的子查询等。

— 创建示例表
CREATE TABLE fgedu_large_table (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
value INTEGER NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

— 插入大量数据(100万条)
INSERT INTO fgedu_large_table (name, value)
SELECT ‘name_’ || generate_series(1, 1000000), random() * 10000;

— 慢查询示例(没有索引)
SELECT * FROM fgedu_large_table WHERE value = 5000;
— 这个查询会全表扫描,非常慢

— 解决方法:为查询字段创建索引
CREATE INDEX idx_fgedu_large_table_value ON fgedu_large_table(value);

— 再次执行查询,速度会显著提升
SELECT * FROM fgedu_large_table WHERE value = 5000;

5.2 缺少索引问题

缺少索引是导致查询性能低下的主要原因之一,特别是在大表上进行查询时。

— 检查表的索引
\d fgedu_large_table

— 查看查询执行计划
EXPLAIN SELECT * FROM fgedu_large_table WHERE value = 5000;

— 创建索引
CREATE INDEX idx_fgedu_large_table_value ON fgedu_large_table(value);

— 再次查看查询执行计划
EXPLAIN SELECT * FROM fgedu_large_table WHERE value = 5000;

— 建议:为频繁用于查询、排序和连接的字段创建索引
CREATE INDEX idx_fgedu_large_table_created_at ON fgedu_large_table(created_at);

5.3 资源耗尽问题

资源耗尽问题是由于数据库服务器的资源(如内存、CPU、磁盘空间)被耗尽导致的。

— 检查磁盘空间
$ df -h

— 检查内存使用情况
$ free -h

— 检查PostgreSQL进程的CPU使用情况
$ top -p $(pgrep -f postgres)

— 检查PostgreSQL的连接数
SELECT count(*) FROM pg_stat_activity;

— 检查PostgreSQL的配置(如最大连接数)
SHOW max_connections;

— 解决方法:增加最大连接数(需要修改配置文件)
$ sudo vi /etc/postgresql/18/main/postgresql.conf
max_connections = 200

— 重启PostgreSQL服务
$ sudo systemctl restart postgresql

Part06-生产案例与实战讲解

下面是一个综合实战案例,展示如何避免和解决PostgreSQL新手常见的错误。

— 实战案例:创建一个完整的用户管理系统

— 1. 创建数据库和用户
— 错误:使用了错误的命令
CREATE DATABASE fgedu_fgedu_db;
CREATE USER fgedu_admin WITH PASSWORD ‘fgedu_admin123’;
GRANT ALL PRIVILEGES ON DATABASE fgedu_fgedu_db TO fgedu_admin;

— 2. 连接到数据库并创建表
— 错误:没有指定数据库
psql -U fgedu_admin
— 正确:指定数据库
psql -U fgedu_admin -d fgedu_fgedu_db

— 创建部门表
CREATE TABLE fgedu_departments (
department_id SERIAL PRIMARY KEY,
department_name VARCHAR(50) NOT NULL UNIQUE
);

— 创建用户表
CREATE TABLE fgedus (
fgedu_id SERIAL PRIMARY KEY,
fgeduname VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE,
department_id INTEGER REFERENCES departments(department_id),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

— 3. 插入数据
— 错误:忘记为NOT NULL列提供值
INSERT INTO departments (department_name) VALUES (‘技术部’), (‘销售部’);
INSERT INTO fgedus (fgeduname, password, email, department_id) VALUES
(‘zhangsan’, ‘password123’, ‘zhangsan@fgedu.net.cn’, 1),
(‘lisi’, ‘password456’, ‘lisi@fgedu.net.cn’, 2),
(‘wangwu’, ‘password789’, ‘wangwu@fgedu.net.cn’, NULL);

— 4. 查询数据
— 错误:使用了错误的表名
SELECT * FROM fgedu;
— 正确:使用正确的表名
SELECT * FROM fgedus;

— 错误:列名拼写错误
SELECT fgedu_id, fgeduname, emial FROM fgedus;
— 正确:使用正确的列名
SELECT fgedu_id, fgeduname, email FROM fgedus;

— 5. 更新数据
— 错误:没有WHERE子句,更新了所有记录
UPDATE fgedus SET password = ‘new_password’;
— 正确:使用WHERE子句限制更新范围
UPDATE fgedus SET password = ‘new_password’ WHERE fgedu_id = 1;

— 6. 删除数据
— 错误:没有WHERE子句,删除了所有记录
DELETE FROM fgedus;
— 正确:使用WHERE子句限制删除范围
DELETE FROM fgedus WHERE fgedu_id = 3;

— 7. 创建索引提高查询性能
— 为频繁查询的字段创建索引
CREATE INDEX idx_fgedus_fgeduname ON fgedus(fgeduname);
CREATE INDEX idx_fgedus_email ON fgedus(email);
CREATE INDEX idx_fgedus_department_id ON fgedus(department_id);

— 8. 检查查询执行计划
EXPLAIN SELECT * FROM fgedus WHERE fgeduname = ‘zhangsan’;
EXPLAIN SELECT * FROM fgedus WHERE email = ‘zhangsan@fgedu.net.cn’;
EXPLAIN SELECT * FROM fgedus WHERE department_id = 1;

Part07-风哥经验总结与分享

1. 连接相关建议:

2. SQL语法建议:

3. 数据操作建议:

from oracle:www.itpux.com

风哥提示:在执行UPDATE和DELETE操作时,一定要使用WHERE子句,否则会更新或删除表中的所有记录,导致数据丢失。建议在执行这些操作前,先使用SELECT语句验证WHERE条件的正确性。

4. 数据库管理建议:

5. 性能优化建议:

6. 调试技巧:

7. 最佳实践:

通过学习和避免这些常见错误,新手可以更快地掌握PostgreSQL的使用,提高数据库操作的准确性和效率。在遇到问题时,不要慌张,仔细阅读错误信息,分析问题原因,然后采取相应的解决方法。学习交流加群风哥QQ113257174

更多视频教程www.fgedu.net.cn

更多学习教程公众号风哥教程itpux_com

from PostgreSQL:www.itpux.com

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

相关推荐

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息