【问题标题】:Java JDBC - invalid character, put printing query and using it in SQLDeveloper worksJava JDBC - 无效字符,放置打印查询并在 SQLDeveloper 中使用它
【发布时间】:2016-01-07 13:20:00
【问题描述】:

rootID、FSA 等都是在代码前面生成的。

PreparedStatement getPotentialParents;

        sql = "SELECT UNIQUE_ID, NAME, ADDRESS_1, ADDRESS_2, POSTAL_CODE FROM "
                + "(SELECT * FROM("
                + "SELECT p.*, CONNECT_BY_ROOT UNIQUE_ID AS ROOT_ID "
                + "FROM UNIQUE_CLINIC p "
                + "START WITH PARENT_ID IS NULL "
                + "CONNECT BY PRIOR UNIQUE_ID = PARENT_ID "
                + "ORDER BY ROOT_ID))" + "WHERE ROOT_ID <> " + rootID + " "
                + "AND (FSA = '" + FSA + "' "
                + "OR NAME IN (" + others + ") "
                + "OR ADDRESS_1 IN (" + others + ") "
                + "OR ADDRESS_2 IN (" + others + "));";


        System.out.println(sql);


        getPotentialParents = connection.prepareStatement(sql);
        rs = getPotentialParents.executeQuery();

我在执行此查询时收到此错误:ORA-00911: invalid character

但是,打印出来的 SQL 可以在 SQLDeveloper 上运行而不会出错:

SELECT UNIQUE_ID, NAME, ADDRESS_1, ADDRESS_2, POSTAL_CODE FROM (SELECT * FROM(SELECT p.*, CONNECT_BY_ROOT UNIQUE_ID AS ROOT_ID FROM UNIQUE_CLINIC p START WITH PARENT_ID IS NULL CONNECT BY PRIOR UNIQUE_ID = PARENT_ID ORDER BY ROOT_ID))
WHERE ROOT_ID <> 10548 AND (FSA = 'null' OR NAME IN ('BRENNAN''S AWESOME PHARMACY #1', '38 SOLUTIONS DR', 'NULLNULLNULL') OR ADDRESS_1 IN ('BRENNAN''S AWESOME PHARMACY #1', '38 SOLUTIONS DR', 'NULLNULLNULL') OR ADDRESS_2 IN ('BRENNAN''S AWESOME PHARMACY #1', '38 SOLUTIONS DR', 'NULLNULLNULL'));

我猜 JDBC 在查询之前正在对 SQL 字符串做一些事情。知道可能是什么原因造成的吗?我怎样才能得到实际的查询?

我进行了一些更新,但仍然无法正常工作,给了我一个无效字符。再一次,打印出来的sql可以在sqldev中运行没有问题了。:

String FSA = rs.getString("FSA");
String rootID = String.valueOf((rs.getInt("ROOT_ID")));
String others = "'" + rs.getString("NAME").replace("'", "''") + "', '" + rs.getString("ADDRESS_1").replace("'", "''") + "', '" + rs.getString("ADDRESS_2").replace("'", "''") + "'";



    Statement getPotentialParents = connection.createStatement();

    sql = "SELECT UNIQUE_ID, NAME, ADDRESS_1, ADDRESS_2, POSTAL_CODE FROM "
            + "(SELECT * FROM("
            + "SELECT p.*, CONNECT_BY_ROOT UNIQUE_ID AS ROOT_ID "
            + "FROM UNIQUE_CLINIC p "
            + "START WITH PARENT_ID IS NULL "
            + "CONNECT BY PRIOR UNIQUE_ID = PARENT_ID "
            + "ORDER BY ROOT_ID)) " + "WHERE ROOT_ID <> " + rootID + " "
            + "AND (FSA = '" + FSA + "' "
            + "OR NAME IN (" + others + ") "
            + "OR ADDRESS_1 IN (" + others + ") "
            + "OR ADDRESS_2 IN (" + others + "));";


    System.out.println(sql);
    rs = getPotentialParents.executeQuery(sql);

【问题讨论】:

  • 像这样传递参数来查询是非常糟糕的主意。它是 sql 注入的潜在受害者。 oracle 推荐使用绑定变量。
  • 从查询字符串中删除最后的;
  • 你确定其他变量包含引号吗?
  • String others = "'" + rs.getString("NAME").replace("'", "''") + "', '" + rs.getString("ADDRESS_1") .replace("'", "''") + "', '" + rs.getString("ADDRESS_2").replace("'", "''") + "'";
  • 这是另一个问题,但您确定要过滤 FSA = 'null' 吗?

标签: java sql oracle jdbc


【解决方案1】:

你不能像这样使用 PreparedStatement。 您必须使用 setString() 方法在 qyery 中设置值。 否则使用 CreateStatement 而不是 PreparedStatement

声明 getPotentialParents;

    sql = "SELECT UNIQUE_ID, NAME, ADDRESS_1, ADDRESS_2, POSTAL_CODE FROM "
            + "(SELECT * FROM("
            + "SELECT p.*, CONNECT_BY_ROOT UNIQUE_ID AS ROOT_ID "
            + "FROM UNIQUE_CLINIC p "
            + "START WITH PARENT_ID IS NULL "
            + "CONNECT BY PRIOR UNIQUE_ID = PARENT_ID "
            + "ORDER BY ROOT_ID))" + "WHERE ROOT_ID <> " + rootID + " "
            + "AND (FSA = '" + FSA + "' "
            + "OR NAME IN (" + others + ") "
            + "OR ADDRESS_1 IN (" + others + ") "
            + "OR ADDRESS_2 IN (" + others + "));";


    System.out.println(sql);


    getPotentialParents = connection.createStatement(sql);
    rs = getPotentialParents.executeQuery();

【讨论】:

  • 你 100% 确定我不能使用这样的 PreparedStatement 吗?我以前用过那么多吨。在这种情况下它不起作用有什么具体原因吗?
  • 您的代码也给了我以下错误:“Connection 类型中的方法 createStatement() 不适用于参数(字符串)”
  • 你的连接码是什么???它是直接来自 java.sql.Connection 还是被覆盖???
  • 也可以在executeQuery()中传入sql作为参数。
  • 直接来自java.sql.Connection。也许我正在使用旧驱动程序或其他东西?
【解决方案2】:

首先,检查这是否在 Oracle 中给出了预期的结果:

VARIABLE rootid   NUMBER;
VARIABLE fsa      VARCHAR2(20);
VARIABLE name     VARCHAR2(20);
VARIABLE address1 VARCHAR2(200);
VARIABLE address2 VARCHAR2(200);

BEGIN
  :rootid   := 10548;
  :fsa      := 'null';
  :name     := 'BRENNAN''S AWESOME PHARMACY #1';
  :address1 := '38 SOLUTIONS DR';
  :address2 := 'NULLNULLNULL';
END;
/

SELECT UNIQUE_ID,
       NAME,
       ADDRESS_1,
       ADDRESS_2,
       POSTAL_CODE
FROM (
  SELECT *
  FROM   (
    SELECT p.*,
           CONNECT_BY_ROOT UNIQUE_ID AS ROOT_ID
    FROM   UNIQUE_CLINIC p
    START WITH PARENT_ID IS NULL
    CONNECT BY PRIOR UNIQUE_ID = PARENT_ID
    ORDER BY ROOT_ID
  )
)
WHERE ROOT_ID <> :rootid
AND   (   FSA       = :fsa
      OR  NAME      IN ( :name, :address1, :address2 )
      OR  ADDRESS_1 IN ( :name, :address1, :address2 )
      OR  ADDRESS_2 IN ( :name, :address1, :address2 )
      );

如果是这样,那么您可以在 Java 中使用绑定变量:

(注意,查询不需要尾随 ;。)

String sql = "SELECT UNIQUE_ID, NAME, ADDRESS_1, ADDRESS_2, POSTAL_CODE FROM ( SELECT * FROM ( SELECT p.*, CONNECT_BY_ROOT UNIQUE_ID AS ROOT_ID FROM UNIQUE_CLINIC p START WITH PARENT_ID IS NULL CONNECT BY PRIOR UNIQUE_ID = PARENT_ID ORDER BY ROOT_ID ) ) WHERE ROOT_ID <> :rootid AND ( FSA = :fsa OR NAME IN ( :name, :address1, :address2 ) OR ADDRESS_1 IN ( :name, :address1, :address2 ) OR ADDRESS_2 IN ( :name, :address1, :address2 ) )";

PreparedStatement ps=connection.prepareStatement( sql );
OraclePreparedStatement ops = (OraclePreparedStatement) ps;
ops.setStringAtName( "fsa", rs.getString("FSA") );
ops.setIntAtName( "rootid", rs.getInt("ROOT_ID") );
ops.setStringAtName( "name", rs.getString("NAME") );
ops.setStringAtName( "address1", rs.getString("ADDRESS_1") );
ops.setStringAtName( "address2", rs.getString("ADDRESS_2") );
ps.execute();

【讨论】:

    猜你喜欢
    • 2016-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 2014-12-01
    相关资源
    最近更新 更多