You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin Exposed操作PostgreSQL时表名被小写,如何使用大写表名?

问题根源

PostgreSQL 默认会将未用双引号包裹的标识符(表名、列名等)自动转换为小写,而 Kotlin Exposed 的默认命名策略不会给标识符添加引号,这就导致你定义的大写表名"Table"在生成 SQL 时被转成了小写的table,数据库自然找不到对应的关系表,从而抛出PSQLException: ERROR: relation "..."。

解决方案

这里提供两种可行的解决方式,你可以根据自己的项目场景选择:

方式一:全局配置带引号的命名策略

如果你的项目中有多个大写表/列需要处理,推荐全局自定义一个命名策略,让 Exposed 生成 SQL 时自动给标识符添加双引号:

// 自定义带引号的命名策略
object QuotedNamingStrategy : DefaultNamingStrategy() {
    override fun tableName(table: String): String = "\"$table\""
    override fun columnName(column: String): String = "\"$column\""
}

// 在初始化数据库连接后、执行事务前配置该策略
fun main() {
    Database.connect("jdbc:postgresql://...", driver = "org.postgresql.Driver")
    
    // 应用自定义命名策略
    TransactionManager.defaultDatabase.apply {
        defaultLocale = Locale.ROOT
        namingStrategy = QuotedNamingStrategy
    }

    transaction {
        logger.addLogger(StdOutSqlLogger)
        val query = Table.select { Table.id eq 5 }
        query.forEach { println(it[Table.tC]) }
    }
}

方式二:单独给表/列指定带引号的名称

如果只是个别表需要使用大写名称,可以直接在定义实体类时,给表名和列名包裹双引号:

// 表名和列名直接用双引号包裹
object Table : IntIdTable("\"Table\"") { 
    val tC = text("\"Text\"") 
    val vC = text("\"Value\"") 
}

// 后续的数据库操作代码保持不变
fun main() {
    Database.connect("jdbc:postgresql://...", driver = "org.postgresql.Driver") 
    transaction { 
        logger.addLogger(StdOutSqlLogger) 
        val query = Table.select { Table.id eq 5 } 
        query.forEach { println(it[Table.tC]) } 
    }
}

原理说明

PostgreSQL 对标识符的大小写敏感规则是:

未加双引号的标识符会被自动转为小写;加双引号的标识符会严格保留原始大小写(包括大小写敏感匹配)。

Exposed 默认的DefaultNamingStrategy只是直接返回传入的名称,不会添加引号,所以才会出现大写名称被转成小写的问题。通过上述两种方式让标识符带上双引号,就能让 PostgreSQL 正确识别你的大写表和列了。

内容的提问来源于stack exchange,提问作者Halcyon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:29:31