简体   繁体   English

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

[英]how to create table if it doesn't exist using Derby Db

I am new to apache derby and I cant seem to make work我是apache derby的新手,我似乎无法工作

    CREATE TABLE IF NOT EXISTS table1 ...

as can be achieved in MySql etc. I am getting a 'Syntax error: Encountered "NOT" at line 1, column 17.'可以在MySql等中实现。我收到'Syntax error: Encountered "NOT" at line 1, column 17.' , when I try to run this SQL statement in my Java program. ,当我尝试在我的Java程序中运行此SQL语句时。

I checked in the documentation page for Derby Db Create Statements , but couldn't find such an alternative.我检查了Derby Db Create Statements的文档页面,但找不到这样的替代方法。

Create the table, catch the SQLException and check SQL status code.创建表,捕获SQLException并检查 SQL 状态码。

The full list of error codes can be found here but I couldn't find Table <value> already exists ;可以在 此处找到完整的错误代码列表,但我找不到Table <value> already exists it's probably X0Y68 .它可能是X0Y68 The code you need is X0Y32 .您需要的代码是X0Y32

Just run the code once and print the error code.只需运行一次代码并打印错误代码。 Don't forget to add a test to make sure the code works;不要忘记添加测试以确保代码有效; this way, you can catch changes in the error code (should not happen...).这样,您可以捕获错误代码中的更改(不应该发生......)。

In my projects, I usually add a helper class with static methods so I can write:在我的项目中,我通常使用 static 方法添加一个助手 class 以便我可以编写:

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

Another option is to run a SELECT against the table and check the status code (which should be 42X05 ).另一种选择是对表运行SELECT并检查状态代码(应该是42X05 )。 But that's a second command you need to send and it doesn't offer any additional information.但这是您需要发送的第二条命令,它不提供任何附加信息。

What's worse, it can fail for other reasons than "Table doesn't exist", so the "create-and-ignore-error" is better IMO.更糟糕的是,除了“表不存在”之外,它可能会因其他原因而失败,因此“创建并忽略错误”是更好的 IMO。

Derby does not support that sql-statement. Derby 不支持该 sql 语句。
In my program I parse all the Tables from the Database into a Set and check if the table exists there.在我的程序中,我将数据库中的所有表解析为一个集合并检查表是否存在于那里。 Like this:像这样:

  private Set<String> getDBTables(Connection targetDBConn) throws SQLException
  {
    Set<String> set = new HashSet<String>();
    DatabaseMetaData dbmeta = targetDBConn.getMetaData();
    readDBTable(set, dbmeta, "TABLE", null);
    readDBTable(set, dbmeta, "VIEW", null);
    return set;
  }

  private void readDBTable(Set<String> 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());
    }
  }

the query you are executing does not supported by Derby db. Derby db 不支持您正在执行的查询。 Instead, if you know the name of the table you can find if table exists or not quite easily.相反,如果您知道表的名称,则可以很容易地找到表是否存在。

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 is to specify name of the table in Uppercase else you won't be able to find table name in metadata. Catch 是以大写形式指定表名,否则您将无法在元数据中找到表名。

to check if table is exist:检查表是否存在:

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");
}

to show all tables name:显示所有表名称:

    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");
    }

Following Aaron Digulla 's lead with a DerbyUtils class to check if the table exists, this is the solution I came up with:Aaron Digulla的带领下,使用DerbyUtils class 检查表是否存在,这是我想出的解决方案:

Calling class调用 class

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;
    }
}

See also也可以看看

I know this was marked with an answer but in case anyone wanted another way of checking I wanted to post anyway.我知道这标有答案,但如果有人想要另一种检查方式,我还是想发布。 Here I check the table metadata with a method that returns a boolean, true if exists, false if it doesn't.在这里,我使用返回 boolean 的方法检查表元数据,如果存在则为 true,如果不存在则为 false。 Hope it helps others if they are looking.希望它可以帮助其他人,如果他们正在寻找。

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;
    }
}

Another solution with 2 conditions:另一种具有两个条件的解决方案:

  • Willing to drop table before creating each time, with the same being present in a.sql file愿意在每次创建之前删除表,相同的存在于 a.sql 文件中

  • Are using Spring and hence willing to use spring-test as a Maven dependency, your life can become much simpler with it's @Sql annotation正在使用 Spring 并因此愿意使用spring-test作为 Maven 依赖项,使用@Sql注释可以让您的生活变得更加简单

So, firstly adding this as a dependency to your pom:因此,首先将此作为依赖项添加到您的 pom 中:

           <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>4.2.5.RELEASE</version>
                <scope>test</scope>
            </dependency>

Secondly, assuming you have an sql that drops, creates table a in a file rectangle.sql :其次,假设您有一个 sql 下降,在文件rectangle.sql中创建表 a :

DROP TABLE rectangles;

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

And you have a test class BlahTest that should run this sql before doing whatever test it is to run, simply add the following @Sql annotation to your class:并且您有一个测试 class BlahTest 应该运行这个 sql,然后再执行它要运行的任何测试,只需将以下@Sql注释添加到您的 class 中:

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 { 
...
}

The specified config attribute value's @SqlConfig has the magic that makes it skip the drop statement errors in case the table doesn't exist.指定的配置属性值的@SqlConfig具有使其跳过 drop 语句错误的魔力,以防表不存在。 I believe it's been written to specifically target these types of databases that don't support IF EXISTS for dropping / table creation (which derby really should, even if it's not part of the SQL standard at the moment)我相信它是专门针对这些类型的数据库而编写的,这些类型的数据库不支持IF EXISTS用于删除/表创建(derby 确实应该这样做,即使它目前不属于 SQL 标准)

Here is a solution that will you can script in SQL.这是一个解决方案,您可以在 SQL 中编写脚本。

  1. Create a Class like the following:创建一个 Class,如下所示:

     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..;"); } } }

    } }

    Note : you don't have to use spring, you can write it in straight JDBC, but then you have to know how to do it correctly.注意:你不必使用spring,你可以直接写JDBC,但是你必须知道如何正确地做。 (Left as an exercise for the reader). (留给读者练习)。 Also, you could rewrite this to parse out the table name from the ddl parameter.此外,您可以重写它以从 ddl 参数中解析出表名。 Another thing would be to do proper error handling.另一件事是进行适当的错误处理。

  2. Make sure the class is compiled and placed in the classpath of the VM the database will be running in.确保 class 已编译并放置在将运行数据库的 VM 的类路径中。

  3. Write your SQL script:编写您的 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. profit利润
try {
            connection.createStatement().execute("create table channels(channel varchar(20),topic varchar(20))");
        } catch (Exception e) {
            // TODO Auto-generated catch block
        //  e.printStackTrace();
        }

Surround the create statement by try-catch.and make sure comment the e.printstacktace();用 try-catch 包围创建语句。并确保注释 e.printstacktace(); if it is already exists it does not show error,otherwise it create table..!!如果它已经存在它不会显示错误,否则它会创建表..!!

This answer is way late, but it might be helpful for someone.这个答案太晚了,但它可能对某人有帮助。

The following Java (standard JDBC) code can be used to check whether a table exists or not, and if it does then it can be created;下面的Java(标准JDBC)代码可以用来检查表是否存在,如果存在则可以创建;

String query = "SELECT TRUE FROM SYS.SYSTABLES WHERE TABLENAME = ? AND TABLETYPE = 'T'"; // Leave TABLETYPE out if you don't care about it
PreparedStatement ps = connection.prepareStatement(query);
ps.setString(1, "TABLE_NAME"); // Must be in capitals
ResultSet rs = ps.executeQuery();
if ( rs.next() && rs.getBoolean(1) )
{
    // Table exists
}
else
{
    // Table does NOT exist ... create it
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用Derby创建内存数据库表? - How to create an in-memory database table using Derby? 即使数据库不存在,也可以使用 Hibernate 动态创建 PostgreSQL 数据库 - Create PostgreSQL database on the fly using Hibernate even if the DB doesn't exist 在derby中对表进行描述和选择不使用与create相同的列顺序 - describe and select on table in derby doesn't use same column order as create 停止Tomcat不会删除Derby db.lck - Stopping Tomcat Doesn't Delete Derby db.lck Java DB(又名Derby)无法从备份中还原数据库 - Java DB (aka Derby) doesn't restore database from a backup 架构“DB”不存在 - Schema “DB” Doesn't exist 不成功:更改表添加约束:创建时表不存在 - Unsuccessful: alter table add constraint: Table doesn't exist on create 我正在尝试使用Java derby EmbeddedDriver创建表,但我不明白这些错误是什么意思? - I am trying to create a table using java derby EmbeddedDriver but i don't understand what these errors mean? 如果不存在,则在oracle数据库中自动创建表 - Automatically create a table in oracle database if it doesn't exist HIbernate不会创建另一个数据库中已经存在的表 - HIbernate doesn't create table that already exist in another database
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM