我需要以编程方式在数据存储区中生成序列,但需要能够检测它们的存在而不是在它们已经存在的情况下创建。有人知道提取这些信息所需的JDBC元数据吗?
对DatabaseMetadata进行粗略扫描并未发现合适的方法;我可以获取所有表/视图和关联的键/索引等,但不能获取该模式的序列。有没有人知道一种方法,最好是数据库独立的,但如果没有,那么对于尽可能多的数据库(想想oracle有一个user_sequence表?但这只是一个数据库,我需要支持其他人)。
提前致谢
答案 0 :(得分:2)
使用JDBC检查是否存在SEQUENCE的任何方法?
答案很简单。
对SEQUENCE
元数据的支持不是JDBC规范的一部分。如果要查找此信息,则需要使代码知道它正在处理的数据库类型,并针对用于表示数据库模式的供应商特定表执行相关查询,等等。
您可能能够找到第三方Java库来执行此操作...但我不知道。
实际上,从理论上讲,您可以通过尝试创建具有相同名称的SEQUENCE
来测试CREATE
是否存在。但是你会遇到各种其他问题,例如处理SEQUENCE
的不同语法,删除你创建的CREATE
作为测试,诊断特定于供应商的错误代码以确定{ {1}}失败了。您可能最好不要查询特定于供应商的架构表。
答案 1 :(得分:2)
您可以使用hibernate方言api来检索序列。见:http://docs.jboss.org/hibernate/orm/3.2/api/org/hibernate/dialect/Dialect.html
从下面的示例中,您可以看到如何使用方言来获取序列详细信息
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();
}
}
}
}
答案 2 :(得分:1)
我所知道的并没有任何直接的方法。因为每个数据库都有自己的生成/处理序列的方式。当它在Oracle中的序列时,它是 auto_incriment (不是序列但接近它或者在某些结果上有相同的结果)在mysql中,标识列在< strong> SQL Server 等
我会做这样的事情 - 你必须建立一个界面:
interface ISequenceChecker{ // or some name which suits you
SequenceObject getSequence();
}
不同数据库/商店的实施(以下给出oracle的E.G):
public class OracleSequenceChecker implements ISequenceChecker{
OracleSequenceObject getSequence(){
// some jdbc or similar call
// to get SELECT SEQUENCE_NAME.NEXTVAL FROM DUAL
}
}
答案 3 :(得分:1)
你没有。每个RDBMS都有您自己的方式来存储您的metada信息。其中一些可能与其他类似,但你很难在thoose表上找到完全相同的信息。
您可以做的最好的事情是某种数据字典来识别RDBMS,并从那里转到字典上的特定配置以获取此信息。
这个想法是有一个存储数据库的表,如果它支持序列,那么另一个表具有加载序列信息所需的配置,如序列表,序列列等。
然后实现一种获取此信息的方法。我会去@avijendr回答(他在我写这篇文章时发帖)
答案 4 :(得分:0)
我使用Postgres 9,Java 8和JDBC 4.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
所以对于Postgres JDBC Driver,有一个表类型&#34; SEQUENCE&#34;。
然后我像这样使用java.sql.DatabaseMetaData#getTables:
字符串目录=&#34;&#34;;
String tableNamePattern =&#34;%&#34 ;;
字符串schemaPattern =&#34; my_schema&#34 ;;
ResultSet tablesRS = cnx.getMetaData()。getTables(catalog,schemaPattern,tableNamePattern,new String [] {&#34; SEQUENCE&#34;});
tablesRS.getString("TABLE_NAME")
给出了每个序列的名称。
我制作了一个实用工具类ExtractMetadataUtil来测试它(在GitHub上)。