SQL 语句不适用于 Oracle JDBC

Posted

技术标签:

【中文标题】SQL 语句不适用于 Oracle JDBC【英文标题】:SQL Statement not working on Oracle JDBC 【发布时间】:2017-02-16 09:00:05 【问题描述】:

我有一个语句可以从 Oracle 检索上个月的交易记录:

select 
    c.CustomerID as id, 
    c.Order_ID as txID, 
    c.Transaction_Date as date1 
from 
    Members a, Verify_Detail b, Verify_Request c 
where 
    a.CustomerID = b.CustomerID AND 
    b.CustomerID = c.CustomerID AND 
    b.Order_ID = c.Order_ID AND 
    c.Transaction_Date between add_months(trunc(sysdate,'mm'),-1) and last_day(add_months(trunc(sysdate,'mm'),-1)) 
order by 
    c.CustomerID, c.Transaction_Date desc

此语句在 SQL Developer 上运行良好。但是当我使用 JDBC 和 Prepared 语句来尝试获取我的数据时,它总是向我显示异常 17006: Invalid Column Name, Cause: null

我想知道我的语句有什么问题导致我无法在 JDBC 上执行它?如果可以在Oracle SQL Developer上使用不支持执行吗?

更新: 我使用的代码很简单:

try 
    Context ctx = new InitialContext();
    DataSource ds = (DataSource) ctx.lookup("jdbc/myDBSrc");
    Connection con = ds.getConnection();

    String sql = "select " + 
                 "c.CustomerID as id, c.Order_ID as txID, c.Transaction_Date as date1 " +
                 "from Members a, Verify_Detail b, Verify_Request c " +
                 "where a.CustomerID = b.CustomerID AND b.CustomerID = c.CustomerID AND " +
                 "b.Order_ID = c.Order_ID AND " + 
                 "c.Transaction_Date between add_months(trunc(sysdate,'mm'),-1) and last_day(add_months(trunc(sysdate,'mm'),-1)) " +
                 "order by c.CustomerID, c.Transaction_Date desc";

    PreparedStatement pstmt = con.prepareStatement(sql);
    ResultSet rs = pstmt.executeQuery();

    while(rs.next())
        out.println("ID: " + rs.getLong("id") + ", txID: " + rs.getString("txID") + ", Date: " + rs.getString("date1"));
    

catch(SQLException e)
    out.println("SQL state: " + e.getSQLState() + ", Code: " + e.getErrorCode() + ", Msg: " + e.getMessage() + ", Cause: " + e.getCause());

【问题讨论】:

具有讽刺意味的是,SQL Developer 是用 Java 编写的,因此当您的语句在 SQL Developer 中运行时,它可以在 JDBC 中运行。 分享你的代码来执行这个语句 你能显示执行这个查询的代码吗?通常,会忘记空格,因此您有一个 where 子句,例如 a.CustomerID = b.CustomerID ANDb.CustomerID @AxelH,我的想法正是 ;-) 请发布完整的异常堆栈跟踪。 【参考方案1】:

这只是一个猜测,但对于 cmets 部分来说太大了......

也许您以将两条连续线合并的方式连接线(在我的示例中,一条线中的 AND 与下一条线中的 b.CustomerID 合并):

PreparedStatement stmt = conn.prepareStatement("select "+
    "c.CustomerID as id, "+
    "c.Order_ID as txID, "+
    "c.Transaction_Date as date1 "+
"from "+
    "Members a, Verify_Detail b, Verify_Request c "+
"where "+
    "a.CustomerID = b.CustomerID AND"  // <=====
    "b.CustomerID = c.CustomerID AND "+
    "b.Order_ID = c.Order_ID AND "+
    "c.Transaction_Date between add_months(trunc(sysdate,'mm'),-1) "+
       "and last_day(add_months(trunc(sysdate,'mm'),-1)) "+
"order by "+
    "c.CustomerID, c.Transaction_Date desc");

编辑:我认为原因要简单得多......它是 Oracle 将所有标识符转为大写,所以试试这个:

String sql = "select " + 
                 "c.CustomerID as \"id\", c.Order_ID as \"txID\", c.Transaction_Date as \"date1\" " +
                 "from Members a, Verify_Detail b, Verify_Request c " +
                 "where a.CustomerID = b.CustomerID AND b.CustomerID = c.CustomerID AND " +
                 "b.Order_ID = c.Order_ID AND " + 
                 "c.Transaction_Date between add_months(trunc(sysdate,'mm'),-1) and last_day(add_months(trunc(sysdate,'mm'),-1)) " +
                 "order by c.CustomerID, c.Transaction_Date desc";

【讨论】:

太用你的话了,我的想法完全正确 ;) 查询的特定格式总是一个好主意,我习惯于在新的每个开头添加一个空格行,这样更容易发现缺失的空格。 如果我错过了一个空格,我会得到ORA-00933。抱歉,但这并不能解决。 你确定你在同一个数据库上工作,在两种情况下都使用相同的用户帐户(SQL Developer 和你的程序)? 是的,我确实使用了相同的帐户和数据库。所以这个问题真的很奇怪,因为我无法在 JDBC 上得到相同的结果。 17006 不是 Oracle 错误;我的意思是我认为数据库没有错误。【参考方案2】:

17006: Invalid Column Name 如果您试图从结果集中获取不存在的列,则会引发。

1) 选项添加外部选择并重试select * from (your_select)

2) 尝试使用列名获取数据。 "ID: " + rs.getLong("CustomerID") + ", txID: " + rs.getString("Order_ID") + ", Date: " + rs.getString("Transaction_Date")

我知道有连接属性GET_COLUMN_LABEL_FOR_NAME。如果设置为假。 ResultSet 只知道真正的 column_name。但我不确定 ojdbc 是否支持它。

【讨论】:

以上是关于SQL 语句不适用于 Oracle JDBC的主要内容,如果未能解决你的问题,请参考以下文章

删除语句不适用于oracle中的查询

SQL 插入适用于 Oracle SQL Developer,但不适用于 python

如何在不运行实际查询的情况下检查 JDBC 语句的 SQL 语法?

如何得到JDBC Insert 语句执行后插入Oracle 数据库记录的主键

SQL - 如果存在不适用于 Select 语句?

SQL - 左连接不适用于 switch 语句