【异常】连接Postgres库报relation “表名“ does not exist

当使用SpringBoot+Mybatis连接Postgres库时,遇到relation '表名' does not exist错误,原因是用户默认搜索路径不包括实际表所在的schema。解决方案是在连接URL中指定目标schema。文章还对比了PostgresSQL和MySQL中模式与表的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、报错内容

SpringBoot+Mybatis连接Postgres库报relation “表名“ does not exist
连接PG库的时候,进行数据库操作,结果报错:
org.postgresql.util.PSQLException: ERROR: relation “users” does not exist
在这里插入图片描述

明明数据库里面有表,为何找不到???
在这里插入图片描述

二、问题说明

原来,PG库用户登录后,默认搜索的schema名字为search_path = ‘“$user”, public’,
但是我又不能在public的schema中建立表,他会提示报错。
在这里插入图片描述

而我操

### Linux 系统中 PostgreSQL 和 openGauss 的及字段自动转小写的原因 #### 一、PostgreSQL 中未加双引号的或字段自动转小写的原因 在 PostgreSQL 数据中,标准 SQL 是不区分大小写的。然而,PostgreSQL 提供了一种特殊机制来支持对象称的大写敏感性——通过使用双引号包裹对象称[^2]。如果没有使用双引号,则 PostgreSQL 在解析 SQL 语句时会将所有的标识符强制转换为小写。 具体来说,在执行 `CREATE` 或其他 DDL/DML 操作时,如果或字段未被双引号包围,PostgreSQL 将其视为小写形式并存储到系统目录中。因此,当后续查询这些对象时,如果不加上双引号,也会默认查找小写版本的对象称[^1]。 例如: ```sql -- 创建一个未加双引号的小写 CREATE TABLE test_table ( id SERIAL PRIMARY KEY, name VARCHAR(50) ); -- 查询该不会错 SELECT * FROM test_table; -- 创建一个带有双引号的大写 CREATE TABLE "TestTable" ( "ID" SERIAL PRIMARY KEY, "Name" VARCHAR(50) ); -- 查询时不带双引号则无法找到对应 SELECT * FROM TestTable; -- 错:relation "testtable" does not exist ``` 上述行为的根本原因在于 PostgreSQL 的设计哲学:为了兼容性和简化操作,默认情况下忽略大小写差异。只有显式指定双引号才能保留原始大小写格式。 --- #### 二、openGauss 中未加双引号的或字段自动转小写的行为 与 PostgreSQL 类似,openGauss 同样遵循这一原则:即对于未加双引号的标识符(如、字段),它们会被统一转换成小写进行存储和匹配[^3]。这是因为 openGauss 继承了许多 PostgreSQL 的特性,并在此基础上进行了扩展优化。 不过需要注意的是,尽管两者有相似之处,但在某些高级功能上可能存在细微差别。例如,openGauss 可能会对特定场景下的大小写处理提供额外配置选项,但这通常不影响基础的大小写转换逻辑。 同样地,下面是一个简单的例子展示 openGauss 如何对待不同情况下的命约定: ```sql -- 不加双引号的情况 CREATE TABLE example_table ( column_one INT NOT NULL ); INSERT INTO example_table VALUES (1); -- 加双引号保持原样的情况 CREATE TABLE "Example_Table" ( "Column_One" INT NOT NULL ); INSERT INTO "Example_Table" ("Column_One") VALUES (2); ``` 在这里可以看到,无论是在 PostgreSQL 还是 openGauss 下,只要没有用双引号保护住字,最终都会变成全小写字母的形式存入元数据结构里去[^3]。 --- #### 三、解决方法 为了避免因大小写问题引发的各种异常状况,可以采取如下措施之一: 1. **始终使用小写字母定义所有数据对象** 推荐开发者养成习惯,一律采用小写字母书写以及列等相关实体称。这样即使偶尔忘记添加必要的引号也不会影响程序正常运行。 2. **严格应用双引号封装每一个需要精确控制大小写的部分** 当确实有必要维持某个特定模式(含大写字母)时,请务必记得给它套上一层 `" "` 符号作为标记。如此一来便能够确保每次访问都能准确命中目标资源而无需担心意外转化的发生。 3. **利用脚本批量调整现有架构至一致状态** 针对已经存在的遗留项目可能存在着大量混合型别的命风格难以逐一修正的情形下,可以通过编写专门针对此需求定制化的迁移工具帮助快速完成整体改造工作。例如基于 Python 脚本来读取当前 schema 并重新生成标准化后的建模语句集等等[^4]。 以下是实现自动化重命的一个简单示例代码片段用于演示如何更改 PostgresQL 及其属性全部变为小写的过程: ```python import psycopg2 def rename_to_lowercase(conn_string): conn = psycopg2.connect(conn_string) cursor = conn.cursor() try: # 获取所有非小写的 cursor.execute(""" SELECT table_name FROM information_schema.tables WHERE table_schema='public' AND lower(table_name)!=table_name; """) tables = [row[0] for row in cursor.fetchall()] for old_name in tables: new_name = old_name.lower() # 修改为小写 cursor.execute(f'ALTER TABLE "{old_name}" RENAME TO {new_name};') # 获取所有非小写的列 cursor.execute(""" SELECT column_name, table_name FROM information_schema.columns WHERE table_schema='public' AND lower(column_name)!=column_name; """) columns = [(row[0], row[1]) for row in cursor.fetchall()] for col_old, tbl in columns: col_new = col_old.lower() # 修改列为小写 cursor.execute(f'ALTER TABLE "{tbl}" RENAME COLUMN "{col_old}" TO {col_new};') conn.commit() # 提交事务 except Exception as e: print(e) conn.rollback() # 出现错误回滚 finally: cursor.close() conn.close() if __name__ == '__main__': db_conn_str = 'dbname=test user=postgres password=secret host=localhost' rename_to_lowercase(db_conn_str) ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

本本本添哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值