名称中带有空格的 SQLite 列

Posted

技术标签:

【中文标题】名称中带有空格的 SQLite 列【英文标题】:SQLite column with space in name 【发布时间】:2017-09-29 15:46:16 【问题描述】:

我尝试在我的战争中访问 SQLLite 数据库,其中某些列的名称中有空格。

我在 SO 上看到了上一个问题 Read data from SQLite where column name contains spaces,但解决方案不起作用:

我知道我应该使用 ``、"" 或 [] 来转义列名,但这些都不适合我,每个转义字符都会出现以下异常,有空格或没有空格在列名中:

java.sql.SQLException: no such column: '[class of worker]'
java.sql.SQLException: no such column: '"age"'

与 ` 相同,在 SO 上不能很好地转义

同时,该请求适用于没有空格的未转义列名称(例如“年龄”或“教育”)

并且我的代码中的请求看起来格式正确:

SELECT DISTINCT `class of worker`, COUNT(*) as countt, ROUND(CAST(SUM(age) AS FLOAT)/COUNT(*),3) as avgage FROM census_learn_sql GROUP BY `class of worker` ORDER BY countt DESC

这是访问数据库的代码:

public Results getColumnValues(String column)

    column = "`" + column + "`"; //handle space in column names
    String sql = "SELECT DISTINCT "+column+", COUNT(*) as countt, ROUND(CAST(SUM(age) AS FLOAT)/COUNT(*),3) as avgage FROM census_learn_sql GROUP BY "
                    +column+" ORDER BY countt DESC";

    Results results = new Results();
    int count = 0;
    int clippedOutRows = 0;

    try (Connection conn = this.connect();
         Statement stmt  = conn.createStatement();
         ResultSet rs    = stmt.executeQuery(sql))

        while (rs.next()) 
            if (count >= 100)
                clippedOutRows += rs.getInt("countt");
            
            else 
                results.getResults().add(new RowResult(rs.getString(column),
                        rs.getInt("countt"),
                        rs.getDouble("avgage")));
            

            count++;
        

        results.setClippedOutRows(clippedOutRows);
        results.setClippedOutValues(count > 99 ? count - 99 : 0);
     catch (SQLException e) 
        System.out.println(e.getMessage());
    

    return results;

这是我的 pom 文件依赖项:

<properties>
        <!-- maven-compiler-plugin -->
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
        <version.javaee>7.0</version.javaee>
        <version.resteasy>3.0.10.Final</version.resteasy>
        <version.jackson>2.4.1</version.jackson>
        <version.junit>4.11</version.junit>
        <version.assertj>1.6.1</version.assertj>
        <version.commons>3.2.1</version.commons>
    </properties>


    <dependencies>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jaxrs</artifactId>
            <version>$version.resteasy</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-servlet-initializer</artifactId>
            <version>$version.resteasy</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jackson-provider</artifactId>
            <version>$version.resteasy</version>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>$version.javaee</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>$version.commons</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>$version.junit</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
            <version>$version.assertj</version>
            <scope>test</scope>
        </dependency>
        <!-- SQLite JDBC library -->
        <dependency>
           <groupId>org.xerial</groupId>
           <artifactId>sqlite-jdbc</artifactId>
           <version>3.8.11.2</version>
        </dependency>
    </dependencies>

我没有看到我在这里做错了什么,是依赖问题吗?

提前感谢您的帮助

【问题讨论】:

【参考方案1】:

您正在修改字符串值column 以分隔列名

column = "`" + column + "`"; //handle space in column names
String sql = "SELECT DISTINCT "+column+", COUNT(*) ...

但是当您从 ResultSet 中检索值时,您使用的是分隔列名

rs.getString(column)

相当于

rs.getString("`class of worker`")

并且 ResultSet 不包含该名称的列:名称只是 class of worker。也就是说,SQL 命令需要分隔符,而ResultSet#getString 方法不需要。

因此,与其修改column 变量,不如将反引号(或双引号或方括号;SQLite 都支持)放在sql 字符串中

// column = "`" + column + "`"; // do not handle space in column names here, do it below
String sql = "SELECT DISTINCT `" + column + "`, COUNT(*) ...

然后你的rs.getString(column) 应该可以正常工作了。

【讨论】:

哇,我觉得自己很愚蠢,谢谢你的理解!调试器在欺骗我,因为当逐行执行代码时,它直接从 try 的资源部分跳转到 catch 异常部分,而没有进入 try 和 while 循环。

以上是关于名称中带有空格的 SQLite 列的主要内容,如果未能解决你的问题,请参考以下文章

在 Sqlite 中,为不同列中返回的每个名称获取前 2 个

SQLite 替换现有列中的数据

在 Android 中返回 SQLite 表的所有列

使用 rtree 和普通索引的 SQLite 查询很慢

反应,渲染名称中带有空格的图像的问题

SQLite python - 将值转换为变量