【问题标题】:SQLite Query With Parameters Not Working in Java带有参数的 SQLite 查询在 Java 中不起作用
【发布时间】:2017-05-13 09:31:31
【问题描述】:

我有一个程序可以从给定表和列字符串的数据库中进行选择。

public void selectAllFrom(String table, String column){
        String sql = "SELECT ? FROM ?";

        try (Connection conn = this.connect();
             PreparedStatement pstmt  = conn.prepareStatement(sql)){
            pstmt.setString(1, column);
            pstmt.setString(2, table);

            ResultSet rs = pstmt.executeQuery();

            while (rs.next()){
                System.out.println(rs.getString(column));
            }

        } catch (SQLException e){
            System.out.println(" select didn't work");
            System.out.println(e.getMessage());
        }
    }

由于某种原因它无法正常工作,它会直接赶上

这里也是 connect() 函数:

private Connection connect(){
    Connection conn = null;
    // SQLite connection string
    String url = "jdbc:sqlite:C:/sqlite/db/chinook.db";

    try{
    // creates connection to the database
    conn = DriverManager.getConnection(url);
    System.out.println("Connection to SQLite has been established");
    } catch (SQLException e){
        System.out.println(e.getMessage());
        System.out.println("Connection didn't work");
    } 

    return conn;
}

我知道问题不在于数据库,因为我能够在没有参数的情况下运行其他选择查询。是参数给我带来了问题。谁能告诉我是什么问题?

【问题讨论】:

  • 很好奇......当@Gurwinder Singh 建议的那样将变量直接放入 SQL 字符串要容易得多时,你为什么还要费心去经历所有这些混乱。

标签: java sql database sqlite database-connection


【解决方案1】:

表或列名不能用作 PreparedStatement 的参数。它必须是硬编码的。

String sql = "SELECT " + column + " FROM " + table;

您应该重新考虑设计,以使这两个恒定并参数化列值。

【讨论】:

    【解决方案2】:

    ? 是一个占位符,用于指示绑定变量。执行 SQL 语句时,数据库首先检查语法,并验证被引用的对象、列和指定对象的访问权限(即有关对象的元数据),并确认所有内容都到位且有效。这个阶段称为解析。

    解析后,它将绑定变量替换为查询,然后继续实际获取结果。

    绑定变量可以在查询中的任何位置替换以替换实际的硬编码数据/字符串,但查询不能自行构造它们。这意味着

    • 你不能对sql查询的关键字使用绑定变量(例如:SELECT、UPDATE等)
    • 您不能对对象或其属性(即表名、列名、函数、过程等)使用绑定变量
    • 您只能使用它们来代替硬编码数据。

    例如:SELECT FIRST_NAME, LAST_NAME, 'N' IS_DELETED FROM USER_DATA WHERE COUNTRY ='CANADA' AND VERIFIED_USER='YES' 在上面的示例查询中,'N''CANADA''YES' 是唯一可以被绑定变量替换的字符串,而不是任何其他词。

    使用绑定变量是编码的最佳实践。它提高了查询性能(当在 Oracle 或 MSSQL 等优化数据库产品中使用大量查询时),还可以保护您的代码免受 sql injection 攻击。

    从不推荐通过连接字符串(尤其是查询的数据部分)来构造查询。只要这些字符串不是直接从输入中获取的,您仍然可以通过连接其他部分(如表名或列名)来构造查询。

    下面的例子是可以接受的:

    query = "Select transaction_id, transaction_date from ";
    if (isHistorical(reportType) 
       { query = query + "HISTORY_TRANSACTIONS" ;}
    else
       {query = query + "PRESENT_TRANSACTIONS" ; }
    

    推荐的做法是使用

    String query_present = "SELECT transaction_id, transaction_date from PRESENT_TRANSACTIONS";
    String query_historical = "SELECT transaction_id, transaction_date from HISTORY_TRANSACTIONS";
    
    if (isHisotrical(reportType))
     { 
        ps.executeQuery(query_historical);
     }else{
        ps.executeQuery(query_present);
     }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-12
      • 2015-02-22
      相关资源
      最近更新 更多