名称中带有空格的 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 列的主要内容,如果未能解决你的问题,请参考以下文章