Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用JDBC,如何将多个ID替换为;从T中删除(?)中的id;_Java_Sql_Jdbc_Prepared Statement - Fatal编程技术网

Java 使用JDBC,如何将多个ID替换为;从T中删除(?)中的id;

Java 使用JDBC,如何将多个ID替换为;从T中删除(?)中的id;,java,sql,jdbc,prepared-statement,Java,Sql,Jdbc,Prepared Statement,我有一些生成一组主键值的代码,我想从数据库表中删除这些主键值 long[] keysToDelete = { 0, 1, 2, 3 }; 我想用一个PreparedStatement来执行 DELETE FROM MyTable WHERE myPrimaryKey IN (0, 1, 2, 3); 知道怎么做吗?两个步骤: 使用适当的参数#构建PreparedStatement SQL字符串 在值数组上循环并将每个值绑定到其参数 不幸的是,没有一种很好的方法可以同时绑定一个数组。两个步骤:

我有一些生成一组主键值的代码,我想从数据库表中删除这些主键值

long[] keysToDelete = { 0, 1, 2, 3 };
我想用一个PreparedStatement来执行

DELETE FROM MyTable WHERE myPrimaryKey IN (0, 1, 2, 3);
知道怎么做吗?

两个步骤:

  • 使用适当的参数#构建PreparedStatement SQL字符串
  • 在值数组上循环并将每个值绑定到其参数
  • 不幸的是,没有一种很好的方法可以同时绑定一个数组。

    两个步骤:

  • 使用适当的参数#构建PreparedStatement SQL字符串
  • 在值数组上循环并将每个值绑定到其参数

  • 不幸的是,没有一种很好的方法可以同时绑定一个数组。

    不完全确定,但这可能会有所帮助:

    PreparedStatement pstmt = Connection.prepareStatement("DELETE FROM MyTable WHERE myPrimaryKey IN (?)");
    pstmt.setArray(1, idArray);
    

    不完全确定,但这可能会有所帮助:

    PreparedStatement pstmt = Connection.prepareStatement("DELETE FROM MyTable WHERE myPrimaryKey IN (?)");
    pstmt.setArray(1, idArray);
    

    我编写了一个类来动态生成这样的多参数查询。它目前有一些局限性(对于写作的快速性),并且还没有经过彻底的测试,但可能是一个很好的开始方法。限制:

    • 仅处理一个多参数参数(?)
    • 错误地将引号中的问号识别为参数
    • API并不漂亮,但另一种选择是编写一个完整的PreparedStatement decorator,其中包含大量的状态管理,这比我愿意投入的工作量还要多
    资料来源:

    /**
     * A PreparedStatement decorator that can bind a set of arguments
     *
     * A specialized ?? placeholder in a string can be bound to a set of
     * values instead of just single values. Currently, only one such
     * specialized placeholder is supported, and you must bind it before
     * obtaining the prepared statement.
     *
     * If you want to bind additional values to the PreparedStatement after
     * producing it, you must run the parameter index through the param()
     * method.
     *
     * Example use:
     *
     * 
     *     MultiValueBinder binder = new MultiValueBinder(
     *          "UPDATE table SET value = ? WHERE id IN (??)", conn);
     *     binder.setInts(myIds);
     *
     *     PreparedStatement stmt = binder.statement();
     *     stmt.setString(binder.param(1), "myValue");
     *
     *     ResultSet rs = stmt.executeQuery();
     *
     * Note: this class is not robust against using question marks in literal
     * strings. Don't use them :).
     */
    public class MultiValueBinder {
        private Connection connection;
        private PreparedStatement statement;
        private String sql;
    
        private int argumentsBefore = 0;
        private int setSize         = 0;
    
        public MultiValueBinder(String sql, Connection connection) {
            this.sql        = sql;
            this.connection = connection;
        }
    
        /**
         * Bind a collection of integers to the multi-valued argument
         */
        public void setInts(Collection<Integer> ints) throws SQLException {
            explodeQuery(ints.size());
            buildStatement();
            try {
    
                int i = 0;
                for (Integer integer: ints)
                    statement.setInt(1 + argumentsBefore + i++, integer);
    
            } catch (Exception ex) {
                cleanStatement();
                throw (ex instanceof SQLException) ? (SQLException) ex : new SQLException(ex);
            }
        }
    
        /**
         * Bind a collection of strings to the multi-valued argument
         */
        public void setStrings(Collection<String> strings) throws SQLException {
            explodeQuery(strings.size());
            buildStatement();
            try {
    
                int i = 0;
                for (String str: strings)
                    statement.setString(1 + argumentsBefore + i++, str);
    
            } catch (Exception ex) {
                cleanStatement();
                throw (ex instanceof SQLException) ? (SQLException) ex : new SQLException(ex);
            }
        }
    
        /**
         * Explode the multi-value parameter into a sequence of comma-separated
         * question marks.
         */
        private void explodeQuery(int size) throws SQLException {
            int mix = sql.indexOf("??");
            if (mix == -1) throw new SQLException("Query does not contain a multi-valued argument.");
            if (size == 0) throw new SQLException("Can't bind an empty collection; generated SQL won't parse.");
    
            // Count the number of arguments before the multi-marker
            argumentsBefore = 0;
            for (int i = 0; i < mix; i++) {
                if (sql.charAt(i) == '?') argumentsBefore++;
            }
            setSize = size;
    
            // Generate the exploded SQL query
            StringBuilder sb = new StringBuilder(sql.substring(0, mix)); // Start
            for (int i = 0; i < setSize; i++) {                          // ?, ?, ...
                if (i > 0) sb.append(", ");
                sb.append('?');
            }
            sb.append(sql.substring(mix + 2));                           // Remainder
            sql = sb.toString();
        }
    
        /**
         * Create the statement if it hasn't been created yet
         */
        private void buildStatement() throws SQLException {
            if (statement != null) return;
            if (sql.contains("??"))
                throw new SQLException("Multi-valued argument not bound yet.");
            statement = connection.prepareStatement(sql);
        }
    
        private void cleanStatement() {
            if (statement != null) {
                try {
                    statement.close();
                } catch (Exception ex) {
                    /* Ignore */
                }
                statement = null;
            }
        }
    
        public PreparedStatement statement() throws SQLException {
            buildStatement();
            return statement;
        }
    
        /**
         * Transform the 1-based-index of the given argument before query expansion
         * into the index after expansion.
         *
         * The ?? placeholder takes up one index slot.
         */
        public int param(int ix) {
            if (ix <= argumentsBefore) return ix;
            if (ix == argumentsBefore + 1)
                throw new RuntimeException(ix + " is the index of the multi-valued parameter.");
            return argumentsBefore + 1 + setSize;
        }
    }
    
    /**
    *可以绑定一组参数的PreparedStatement decorator
    *
    *专门的??字符串中的占位符可以绑定到一组
    *值,而不仅仅是单个值。目前,只有一家这样的公司
    *支持专用占位符,必须先绑定它
    *获取准备好的报表。
    *
    *如果要在之后将其他值绑定到PreparedStatement
    *生成它时,必须通过param()运行参数索引
    *方法。
    *
    *示例用法:
    *
    * 
    *多值活页夹=新的多值活页夹(
    *“更新表集值=?其中id位于(??),conn);
    *binder.setInts(myid);
    *
    *PreparedStatement stmt=binder.statement();
    *stmt.setString(活页夹参数(1),“myValue”);
    *
    *ResultSet rs=stmt.executeQuery();
    *
    *注意:这个类不适合在文本中使用问号
    *字符串。不要使用它们:)。
    */
    公共类多值绑定器{
    专用连接;
    私人编制的报表;
    私有字符串sql;
    private int argumentsBefore=0;
    私有int setSize=0;
    公共多值绑定器(字符串sql、连接){
    this.sql=sql;
    这个连接=连接;
    }
    /**
    *将整数集合绑定到多值参数
    */
    公共void setInts(集合ints)引发SQLException{
    explodeQuery(ints.size());
    buildStatement();
    试一试{
    int i=0;
    用于(整数:整数)
    语句.setInt(1+argumentsBefore+i++,整数);
    }捕获(例外情况除外){
    cleanStatement();
    抛出(ex instanceof SQLException)?(SQLException)ex:new SQLException(ex);
    }
    }
    /**
    *将字符串集合绑定到多值参数
    */
    公共void集合字符串(集合字符串)引发SQLException{
    explodeQuery(strings.size());
    buildStatement();
    试一试{
    int i=0;
    for(字符串str:strings)
    statement.setString(1+argumentsBefore+i++,str);
    }捕获(例外情况除外){
    cleanStatement();
    抛出(ex instanceof SQLException)?(SQLException)ex:new SQLException(ex);
    }
    }
    /**
    *将多值参数分解为逗号分隔的序列
    *问号。
    */
    私有查询(整型大小)引发SQLException{
    int mix=sql.indexOf(“??”);
    如果(mix==-1)抛出新的SQLException(“查询不包含多值参数”);
    如果(size==0)抛出新的SQLException(“无法绑定空集合;生成的SQL不会解析”);
    //计算多重标记之前的参数数
    argumentsBefore=0;
    对于(int i=0;i0)sb.追加(“,”);
    某人附加(“?”);
    }
    sb.append(sql.substring(mix+2));//余数
    sql=sb.toString();
    }
    /**
    *如果尚未创建语句,请创建该语句
    */
    私有void buildStatement()引发SQLException{
    if(statement!=null)返回;
    if(sql.contains(“??”)
    抛出新的SQLException(“多值参数尚未绑定”);
    语句=connection.prepareStatement(sql);
    }
    私有语句(){
    if(语句!=null){
    试一试{
    语句。close();
    }捕获(例外情况除外){
    /*忽略*/
    }
    语句=null;
    }
    }
    公共PreparedStatement语句()引发SQLException{
    buildStatement();
    返回语句;
    }
    /**
    *在查询扩展之前,转换给定参数的基于1的索引
    *扩展后进入索引。
    *
    *?占位符占用一个索引槽。
    */
    公共int参数(int ix){
    
    if(ix我已经编写了一个类来动态生成这样一个多参数查询。它目前有一些限制(为了编写的快速性),还没有经过彻底的测试,但可能是一个很好的入门方法。限制: