2014-02-22 22 views
2

我正在编写一个Web服务,它基本上允许用户向各个SQL数据库中的预先存在的表提交对广告列的查询。如何确定colum名称是否必须在SQL语句中用引号括起来?

我有这样的定义的PostgreSQL表:

CREATE TABLE stpg.test (
    test integer, 
    "Test" integer, 
    "TEST" integer 
); 
insert into stpg.test values (1,2,3); 

要我运行下面的Java代码可用列确定的名字:

ResultSet rs = dbmd.getColumns(null, "stpg", "test", null); 
while (rs.next()) { 
    System.out.println(rs.getString("COLUMN_NAME")); 
} 

我得到:

 
test 
Test 
TEST 

如果用户提交查询,请参考返回的列,如 select test, Test, TEST from stpg.test他会得到1 1 1而不是预期的1 2 3. 这是一个错误?

我知道做select test, "Test", "TEST" from stpg.test会正确返回结果。但是,我的用户不知道要获取在引号中定义的“大写”列的值,因为它们需要在查询中使用引号。

有没有一种方法可以确定列名是否区分大小写,以便我可以用引号报告其名称?我需要一般地针对不同的数据库这样做,因此JDBC API方法更可取。我尝试使用ResultSetMetaData并调用getColumnNamegetColumnLabel,但它们返回没有引号的名称。调用isCaseSensitive总是返回false。

+2

你为什么不总是引用列名? – Camilo

+1

这是记录的行为:http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS和其他人我强烈建议**从来没有**报价专栏名称unles你真的了解其含义。 –

+0

如果你可以避免使用大小写敏感的列名,我建议使用这种方法是个不错的主意。 –

回答

3

有没有一种方法可以确定列名是否区分大小写,以便我可以用引号报告其名称?

它看起来像你说的一个列名称需要引用,如果它包含任何大写字母。在这种情况下:

if (!name.equals(name.toLowercase())) { 
     // needs quoting. 
    } 

但是,这是没有实际意义:

  • ,如果你只是引用的所有列名或
  • 如果你治疗用户提供的列名不区分大小写。

(关于后一点,有列名其中,区分大小写重要的是可能一个不好的设计,区分大小写肯定不是东西,你会想你的网站的用户不用担心...)


我尝试使用的ResultSetMetaData和调用getColumnName和getColumnLabel但他们返回的名称不带引号。

因为他们应该!引号不是列名的一部分!它们是标识符(Postgres)SQL语法的一部分(通常)。名称是引号内的内容。

调用isCaseSensitive总是返回false。

说实话,它并不完全清楚(从javadoc)该方法的结果意味着什么。但是这听起来像您可能在您正在使用的JDBC驱动程序中发现了一个错误。 (或者,也许你只是错了。造成这种情况的代码实现,在目前的Postgres 方法确实咨询列类型的信息......)

+0

我不太明白'if(name.equals(name.toUppercase()))'测试。如果我正确读取,只有列名是*完全*大写时才是如此。但是,如果名称中的*任何*字符都是大写字母,PostgreSQL需要引用它。所以这个测试不会起作用...... – exhuma

+0

这里也存在JDBC API的不足之处; 'Connection'或'DatabaseMetaData'应该暴露一个'quoteIdentifier'方法,但它不会。所以报价比它应该更难。 –

+0

@exhuma - 你说得对。错误。固定。 –

1

我会建议总是引用的列名。没有真正的理由你会删除引号。而且更重要的是,决定是否报价的代码肯定会跨越10-15线,没有附加值。这大约有15行代码可以引入新的错误,错别字,概念错误。

只是引用每一列是直截了当的,并始终正确!

另外,关于你的问题,如果select test, Test, TEST from stpg.test的结果是一个错误:不是。这是PostgreSQL的默认行为。除非用引号括起来,否则所有列名称(或数据库对象名称)总是被降低。这也导致我们到isCaseSensitive。它总是虚假的,因为它不区分大小写。

更重要的注意事项:如果让用户键入SQL查询,您可能会遇到其他奇怪的问题。你永远不会知道你的用户输入了什么样的恶作剧。无论是通过设计还是意外;)

如果这是您第一次允许用户输入SQL查询,请仔细考虑您的行动计划!用户输入错误,错误(5个桌面上有全数百万行的全笛卡尔产品?只有,然后应用过滤器?...有趣的时间...),或者甚至可能试图与您的数据库一起玩。如果你决定真的这样做,扣住! :)这一切都取决于你的用户基础的技术知识。

此外,在Postgres中,我发现将所有内容放在较低位置并将用户下划线分隔为单词很有用。像user_account而不是UserAccount

相关问题