如果使用Derby Db不存在表,如何创建表

我是apache derby新手,我似乎无法开展工作

  CREATE TABLE IF NOT EXISTS table1 ... 

可以在MySql等中实现。我收到'Syntax error: Encountered "NOT" at line 1, column 17.' ,当我尝试在我的Java程序中运行此SQL语句时。

我查看了Derby Db Create Statements的文档页面,但找不到这样的替代方法。

创建表,捕获SQLException并检查SQL状态代码。

可在此处找到错误代码的完整列表, 但我找不到Table already exists ; 它可能是X0Y68 你需要的代码是X0Y32

只需运行一次代码并打印错误代码即可。 不要忘记添加测试以确保代码有效; 这样,您可以捕获错误代码中的更改(不应该发生…)。

在我的项目中,我通常使用静态方法添加一个辅助类,所以我可以写:

 } catch( SQLException e ) { if( DerbyHelper.tableAlreadyExists( e ) ) { return; // That's OK } throw e; } 

另一种选择是对表运行SELECT并检查状态代码(应为42X05 )。 但这是您需要发送的第二个命令,它不提供任何其他信息。

更糟糕的是,它可能由于“表不存在”之外的其他原因而失败,因此“创建并忽略错误”是更好的IMO。

Derby不支持sql语句。
在我的程序中,我将数据库中的所有表解析为一个集合,并检查表中是否存在该表。 喜欢这个:

  private Set getDBTables(Connection targetDBConn) throws SQLException { Set set = new HashSet(); DatabaseMetaData dbmeta = targetDBConn.getMetaData(); readDBTable(set, dbmeta, "TABLE", null); readDBTable(set, dbmeta, "VIEW", null); return set; } private void readDBTable(Set set, DatabaseMetaData dbmeta, String searchCriteria, String schema) throws SQLException { ResultSet rs = dbmeta.getTables(null, schema, null, new String[] { searchCriteria }); while (rs.next()) { set.add(rs.getString("TABLE_NAME").toLowerCase()); } } 

检查表是否存在:

 Connection con = DriverManager.getConnection(url); ResultSet res = con.getMetaData().getTables(null, Schema_Name, table_name.toUpperCase(), null);//Default schema name is "APP" if(res.next()) { //do some thing; }else{ JOptionPane.showMessageDialog(null, table_name +" not exist"); } 

显示所有表名称:

  Connection con = DriverManager.getConnection(url); ResultSet res = con.getMetaData().getTables(null, Schema_Name, "%", null);//Default schema name is "APP" while(res.next()) { JOptionPane.showMessageDialog(null, res.getString(3) + " is exist");//Show table name }else{ JOptionPane.showMessageDialog(null, table_name +" not exist"); } 

Derby db不支持您正在执行的查询。 相反,如果你知道表的名称,你可以找到表,或者不是很容易。

 public boolean isTableExist(String sTablename) throws SQLException{ if(connection!=null) { DatabaseMetaData dbmd = connection.getMetaData(); ResultSet rs = dbmd.getTables(null, null, sTablename.toUpperCase(),null); if(rs.next()) { System.out.println("Table "+rs.getString("TABLE_NAME")+"already exists !!"); } else { System.out.println("Write your create table function here !!!"); } return true; } return false; } 

Catch是以大写forms指定表的名称,否则您将无法在元数据中找到表名。

Aaron Digulla领导DerbyUtils类以检查表是否存在之后,这是我提出的解决方案:

打电话给上课

 public void createTable(String name) { Connection connection = null; PreparedStatement preparedStatement = null; try { connection = daoFactory.getConnection(); String sql = String.format(SQL_CREATE_TABLE, name); preparedStatement = connection.prepareStatement(sql, Statement.NO_GENERATED_KEYS); preparedStatement.execute(); } catch (SQLException e) { if(DerbyUtils.tableAlreadyExists(e)) { //check if the exception is because of pre-existing table. logger.info("Talbe " + name + " already exists. No need to recreate"); } else { logger.error(e.getMessage() + " : " + e.getStackTrace()); } } finally { close(connection, preparedStatement); //DAOUtils silently closes } } 

DerbyUtils

 public class DerbyUtils { public DerbyUtils() { //empty constructor -- helper class } public static boolean tableAlreadyExists(SQLException e) { boolean exists; if(e.getSQLState().equals("X0Y32")) { exists = true; } else { exists = false; } return exists; } } 

也可以看看

我知道这标有答案但是如果有人想要另一种方式检查我想要发帖。 在这里,我使用返回布尔值的方法检查表元数据,如果存在则返回true,否则返回false。 如果他们正在寻找,希望它能帮助他人。

 private static Connection conn = null; private static Statement st = null; private static ResultSet rs = null; private static DatabaseMetaData dmd; public Boolean firstTime() { try { dmd = conn.getMetaData(); rs = dmd.getTables(null, "APP", "LOGIN", null); return !rs.next(); } catch (SQLException ex) { Logger.getLogger(Database.class.getName()).log(Level.SEVERE, null, ex); return false; } } 

另外两个条件的解决方案:

  • 愿意在每次创建之前删除表 ,同时存在于.sql文件中

  • 使用Spring并因此愿意使用spring-test作为Maven依赖,使用它的@Sql注释可以简化你的生活

所以,首先将它作为依赖项添加到你的pom:

   org.springframework spring-test 4.2.5.RELEASE test  

其次,假设你有一个丢弃的sql,在一个文件rectangle.sql中创建表a:

 DROP TABLE rectangles; CREATE TABLE rectangles ( id INTEGER NOT NULL PRIMARY KEY, width INTEGER NOT NULL, height INTEGER NOT NULL ); 

你有一个测试类BlahTest应该运行这个sql,然后再做它要运行的测试,只需在你的类中添加以下@Sql注释:

 import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.jdbc.Sql; import org.springframework.test.context.jdbc.SqlConfig; import org.springframework.test.context.jdbc.SqlConfig.ErrorMode; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes=XyzClientConfig.class) @Sql(scripts="/sql/ddl/rectangle.sql", config=@SqlConfig (errorMode=ErrorMode.IGNORE_FAILED_DROPS)) public class BlahTest { ... } 

指定的配置属性值的@SqlConfig具有使其在表不存在时跳过drop语句错误的魔力。 我相信它是专门针对这些类型的数据库编写的,这些数据库不支持用于删除/创建表的IF EXISTS (德比真的应该,即使它现在不是SQL标准的一部分)

这是一个可以在SQL中编写脚本的解决方案。

  1. 创建如下所示的类:

     package user.fenris.spring.extensions; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.SingleConnectionDataSource; public class SqlCreateIfNotExists { private static Log log = LogFactory.getLog(SqlCreateIfNotExists.class); public static void createTableIfNotExists(String tablename, String ddl) throws SQLException { Connection conn = DriverManager.getConnection("jdbc:default:connection"); if (conn != null) { JdbcTemplate template = new JdbcTemplate(new SingleConnectionDataSource(conn, true)); int count = template.queryForInt("select count(*) from SYS.SYSTABLES where TABLENAME = ?", tablename); log.debug("Count: " + count); if (count == 0) { log.debug("Executing sql statement: " + ddl); template.execute(sql); } else { log.debug("Table exists. Skipping sql execution..."); } } } 

    }

    注意 :您不必使用spring,您可以直接在JDBC中编写它,但是您必须知道如何正确地执行它。 (留给读者练习)。 此外,您可以重写此操作以从ddl参数中解析出表名。 另一件事是做正确的error handling。

  2. 确保编译该类并将其放置在将运行数据库的VM的类路径中。

  3. 编写SQL脚本:

     -- 2K for ddl statement should be enough. You want more? Seriously? create procedure CreateTableIfNotExists(in tablename varchar(128), in ddl varchar(2048)) PARAMETER STYLE JAVA MODIFIES SQL DATA language java external name 'user.fenris.spring.extensions.SqlCreateIfNotExists.createTableIfNotExists'; call CreateTableIfNotExists('TABLE_NAME_MUST_BE_ALL_CAPS', 'create table TABLE_NAME_MUST_BE_ALL_CAPS (entry_id int generated always as identity not null, entry_timestamp timestamp, username varchar(128) not null, note varchar(1024) not null, primary key (entry_id))'); -- you don't have to drop this, but you would have to create a similar -- procedure to create the CreateTableIfNotExists procedure, -- (ie CreateProcedureIfNotExists) but then it's turtles all the way down drop procedure CreateIfNotExists; 
  4. ???

  5. 利润
 try { connection.createStatement().execute("create table channels(channel varchar(20),topic varchar(20))"); } catch (Exception e) { // TODO Auto-generated catch block // e.printStackTrace(); } 

通过try-catch覆盖create语句,并确保注释e.printstacktace(); 如果它已经存在它不会显示错误,否则它会创建表.. !!