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的主要内容,如果未能解决你的问题,请参考以下文章
SQL 插入适用于 Oracle SQL Developer,但不适用于 python
如何在不运行实际查询的情况下检查 JDBC 语句的 SQL 语法?