Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/324.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检查序列的存在?_Java_Sql_Jdbc_Sequence - Fatal编程技术网

Java 有没有办法使用JDBC检查序列的存在?

Java 有没有办法使用JDBC检查序列的存在?,java,sql,jdbc,sequence,Java,Sql,Jdbc,Sequence,我需要以编程方式在数据存储中生成序列,但需要能够检测序列的存在,而不是在序列已经存在时创建序列。有人知道提取此信息所需的JDBC元数据吗 粗略的扫描并不能找到合适的方法;我可以得到所有的表/视图和相关的键/索引等,但不能得到该模式的序列。是否有人知道一种方法,最好是独立于数据库的,但如果不知道,则尽可能多地使用数据库(想想oracle有一个user_sequence表?但这只是一个数据库,我需要支持其他数据库) 提前谢谢据我所知,没有任何直接的方法。因为每个数据库都有自己的生成/处理序列的方法。

我需要以编程方式在数据存储中生成序列,但需要能够检测序列的存在,而不是在序列已经存在时创建序列。有人知道提取此信息所需的JDBC元数据吗

粗略的扫描并不能找到合适的方法;我可以得到所有的表/视图和相关的键/索引等,但不能得到该模式的序列。是否有人知道一种方法,最好是独立于数据库的,但如果不知道,则尽可能多地使用数据库(想想oracle有一个user_sequence表?但这只是一个数据库,我需要支持其他数据库)


提前谢谢

据我所知,没有任何直接的方法。因为每个数据库都有自己的生成/处理序列的方法。当它在Oracle中是序列时,它在mysql中是自动加入的(不是一个序列,但与它很接近,或者实现了一些相同的结果),在SQL Server中是标识列,等等

我会做这样的事情-您必须制作一个接口:

interface ISequenceChecker{ // or some name which suits you
    SequenceObject getSequence();
}
不同数据库/存储的实现(例如,下面给出的oracle):

有没有办法使用JDBC检查序列的存在

答案是否定的

序列
元数据的支持不是JDBC规范的一部分。如果要查找此信息,需要让代码知道它正在处理的数据库类型,并对用于表示数据库模式的特定于供应商的表执行相关查询,等等

您可能会找到一个第三方Java库来实现这一点。。。但我不知道有一个



实际上,从理论上讲,您可以通过尝试创建一个同名序列来测试序列是否存在。但是,还有其他各种各样的问题,比如处理
创建
的不同语法,删除作为测试创建的
序列
,诊断特定于供应商的错误代码以确定
创建
失败的原因。您最好查询特定于供应商的模式表。

您不需要。每个RDBMS都有自己的方式来存储metada信息。其中一些可能与其他类似,但您很难在这些表中找到完全相同的信息

您所能做的最好的事情是使用某种数据字典来识别RDBMS,并从中转到字典上的特定配置以获取此信息

其想法是有一个表来存储数据库,如果它支持序列,那么另一个表具有加载序列信息所需的配置,如序列表、序列列等


然后实现一种获取此信息的方法。我会选择@avijendr-answer(他在我写这篇文章时发布了它)

您可以使用hibernate方言api来检索序列。见:

从下面的示例中,您可以看到如何使用方言获取序列详细信息

public static void main(String[] args) {
        Connection jdbcConnection = null;
        try {
            jdbcConnection = DriverManager.getConnection("", "", "");
            String sequenceName = "xyz" ; // name of sequence for check
        System.out.println("Check Sequence :" + checkSequenceName(sequenceName, jdbcConnection));
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
        if(jdbcConnection != null) {
            try {
                jdbcConnection.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

public static boolean checkSequenceName(String sequenceName, Connection conn) throws JDBCConnectionException, SQLException {
    DialectResolver dialectResolver = new StandardDialectResolver();
    Dialect dialect =  dialectResolver.resolveDialect(conn.getMetaData());

    if ( dialect.supportsSequences() ) {
        String sql = dialect.getQuerySequencesString();
        if (sql!=null) {

            Statement statement = null;
            ResultSet rs = null;
            try {
                statement = conn.createStatement();
                rs = statement.executeQuery(sql);

                while ( rs.next() ) {
                    if(sequenceName.equals(rs.getString(1))) {
                        return true;
                    }
                }
            }
            finally {
                if (rs!=null) rs.close();
                if (statement!=null) statement.close();
            }

        }
    }
    return false;
}
如果您不想使用hibernate,那么您必须定制特定于顺序的实现。 自定义实现的示例代码

interface SequenceQueryGenerator {
    String getSelectSequenceNextValString(String sequenceName);
    String getCreateSequenceString(String sequenceName, int initialValue, int incrementSize); 
    String getDropSequenceStrings(String sequenceName); 
    String getQuerySequencesString(); 
}


class OracleSequenceQueryGenerator implements SequenceQueryGenerator {

    @Override
    public String getSelectSequenceNextValString(String sequenceName) {
        return "select " + getSelectSequenceNextValString( sequenceName ) + " from dual";
    }

    @Override
    public String getCreateSequenceString(String sequenceName,
            int initialValue, int incrementSize) {
        return "create sequence " + sequenceName +  " start with " + initialValue + " increment by " + incrementSize;
    }

    @Override
    public String getDropSequenceStrings(String sequenceName) {
        return "drop sequence " + sequenceName;
    }

    @Override
    public String getQuerySequencesString() {
        return "select sequence_name from user_sequences";
    }

}


class PostgresSequenceQueryGenerator implements SequenceQueryGenerator {

    @Override
    public String getSelectSequenceNextValString(String sequenceName) {
        return "select " + getSelectSequenceNextValString( sequenceName );
    }

    @Override
    public String getCreateSequenceString(String sequenceName,
            int initialValue, int incrementSize) {
        return "create sequence " + sequenceName + " start " + initialValue + " increment " + incrementSize;
    }

    @Override
    public String getDropSequenceStrings(String sequenceName) {
        return "drop sequence " + sequenceName;
    }

    @Override
    public String getQuerySequencesString() {
        return "select relname from pg_class where relkind='S'";
    }

}


public boolean checkSequence (String sequenceName, SequenceQueryGenerator queryGenerator, Connection conn) throws SQLException {
        String sql = queryGenerator.getQuerySequencesString();
        if (sql!=null) {

            Statement statement = null;
            ResultSet rs = null;
            try {
                statement = conn.createStatement();
                rs = statement.executeQuery(sql);

                while ( rs.next() ) {
                    if(sequenceName.equals(rs.getString(1))) {
                        return true;
                    }
                }
            }
            finally {
                if (rs!=null) rs.close();
                if (statement!=null) statement.close();
            }

        }
        return false;
    }

public static void main(String[] args) {
        Connection jdbcConnection = null;
        try {
            jdbcConnection = DriverManager.getConnection("", "", "");
            String sequenceName = "xyz" ; // name of sequence for check
            System.out.println(checkSequence(sequenceName, new OracleSequenceQueryGenerator(), jdbcConnection));
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if(jdbcConnection != null) {
                try {
                    jdbcConnection.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
}

我用Postgres9、Java8和JDBC4.2进行了测试

为了检索序列列表,我做了以下工作:

  • 首先,列出实体类型
  • 结果是:

     * FOREIGN TABLE
     * INDEX
     * MATERIALIZED VIEW
     * SEQUENCE
     * SYSTEM INDEX
     * SYSTEM TABLE
     * SYSTEM TOAST INDEX
     * SYSTEM TOAST TABLE
     * SYSTEM VIEW
     * TABLE
     * TEMPORARY INDEX
     * TEMPORARY SEQUENCE
     * TEMPORARY TABLE
     * TEMPORARY VIEW
     * TYPE
     * VIEW
    
    因此,对于PostgresJDBC驱动程序,有一个表类型“SEQUENCE”

  • 然后我就这样用,

    字符串catalog=“”
    字符串tableNamePattern=“%”
    String schemaPattern=“my_schema”
    ResultSet tablers=cnx.getMetaData().getTables(目录、schemaPattern、tableNamePattern、新字符串[]{“序列”})

  • tablers.getString(“TABLE_NAME”)
    给出找到的每个序列的名称


    我制作了一个实用程序类来测试它(在GitHub上)。

    您使用的是什么数据库?正如我所说的,我需要支持很多数据库,我使用H2(它有创建序列…如果不存在的话),但这是非标准的,但需要支持所有支持序列的公共RDBMS(SQLServer、PostgreSQL、Oracle、H2、NuoDB、Derby、Firebird等)可能重复@NeilStockton-如果你真的阅读了Oracle特定问题的答案,你会意识到他们也回答了你更一般的问题。但我也在下面为您解答了。@NeilStockton-1)如果您希望得到关于如何查询数据库模式的答案,您应该问一下。。。不是“JDBC可以做到”。2) 最新的JDBCAPI是公开的。你不需要问这么多问题就可以找到他们。谢谢你的回复。是的,每个数据存储都有一个变体可能是我的选择。顺便说一句,MySQL中的“auto increment”并不等同于(SQL)序列,后者是一个独立的命名值生成器,而auto increment是特定列的标识,没有名称。有支持标识(自动递增)和顺序的RDBMS,因此有区别。谢谢Neil。我知道它不是等价的,但它是最接近的,否则你必须使用联锁或类似的东西(但仍然不是顺序)。除了我上面提到的,我想不出别的解决办法。快乐的黑客!在Hibernate>=4.x中,有必要将
    Connection.getMetaData
    包装到
    数据库MetadataDialogResolutionInfo适配器中。如果
    方言.get…String
    方法返回null,我建议抛出异常,因为
    null
    不是文档化的返回值。
     * FOREIGN TABLE
     * INDEX
     * MATERIALIZED VIEW
     * SEQUENCE
     * SYSTEM INDEX
     * SYSTEM TABLE
     * SYSTEM TOAST INDEX
     * SYSTEM TOAST TABLE
     * SYSTEM VIEW
     * TABLE
     * TEMPORARY INDEX
     * TEMPORARY SEQUENCE
     * TEMPORARY TABLE
     * TEMPORARY VIEW
     * TYPE
     * VIEW