如何解决PostgreSQL中“关系的列不存在”错误?
PostgreSQL插入提示列不存在的奇怪错误
刚接触PostgreSQL,遇到一个诡异的问题:明明表中有name列,但执行插入语句时却提示该列不存在,以下是详细信息及最终解决方案。
创建表的SQL语句:
CREATE TABLE hsm ( id uuid DEFAULT uuid_generate_v4() PRIMARY KEY, name text, contains text[], contained_by text[] );
执行\d hsm查看表结构的输出:
Table "public.hsm" Column | Type | Collation | Nullable | Default -----------------+--------+-----------+----------+-------------------- id | uuid | | not null | uuid_generate_v4() name | text | | | contains | text[] | | | contained_by | text[] | | | Indexes: "hsm_pkey" PRIMARY KEY, btree ("\tid")
执行\d查看所有关系的输出:
List of relations Schema | Name | Type | Owner --------+----------+-------+------- public | hsm | table | hsm public | hsm_test | table | hsm
执行\dn查看模式的输出:
List of schemas Name | Owner --------+---------- public | postgres (1 row)
执行\du查看角色的输出:
Role name | Attributes | Member of -----------+------------------------------------------------------------+----------- hsm | Superuser, Create role, Create DB | {} postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
执行\dn+查看模式详情的输出:
List of schemas Name | Owner | Access privileges | Description --------+----------+----------------------+------------------------ public | postgres | postgres=UC/postgres+| standard public schema | | =UC/postgres |
执行psql -V查看版本的输出:
psql (PostgreSQL) 12.14 (Ubuntu 12.14-0ubuntu0.20.04.1)
执行查询列名及长度的SQL语句:
select attname, length(attname) from pg_attribute where attrelid = 'hsm'::regclass;
输出结果:
attname | length -----------------+-------- cmax | 4 cmin | 4 ctid | 4 tableoid | 8 xmax | 4 xmin | 4 contained_by | 15 contains | 11 id | 5 name | 7 (10 rows)
执行插入语句:
insert into hsm (name) values (test);
得到错误提示:
ERROR: column "name" of relation "hsm" does not exist LINE 1: insert into hsm (name)
编辑补充:执行\l查看数据库的输出:
List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges -----------+----------+----------+-------------+-------------+----------------------- hsm | hsm | UTF8 | en_US.UTF-8 | en_US.UTF-8 | postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres
解决方案
问题根源在于列名前存在三个空格,比如实际列名是 name而非name。\d hsm这类psql命令的输出不会显示这些前置空格,导致肉眼无法区分,最终引发name和 name不匹配的错误。
这些前置空格大概率是创建表时缩进导致的(可能是复制代码或手动输入时的习惯,比如Python的缩进习惯影响)。
需要注意两个关键点:
- PostgreSQL会将列名中的前置空格纳入标识符的一部分,视为有效字符
- 很多psql命令的输出不会显示这些空格,容易造成误解
关键线索来自查询列名长度的结果:输出显示name列的长度是7,而正常name的长度应该是4,多出来的3个字符就是前置空格。
修复方法:
- 临时验证:使用带引号的标识符引用实际列名(不推荐长期使用):
insert into hsm (" name") values ('test');
- 永久修复:重命名列去掉前置空格:
ALTER TABLE hsm RENAME COLUMN " name" TO name; ALTER TABLE hsm RENAME COLUMN " id" TO id; ALTER TABLE hsm RENAME COLUMN " contains" TO contains; ALTER TABLE hsm RENAME COLUMN " contained_by" TO contained_by;
- 重建表:如果列较多,可直接重建表,创建时确保列名前没有多余空格。
内容的提问来源于stack exchange,提问作者Oliver Cox
相关产品推荐
相关产品推荐

