как создать таблицу, если она не существует с помощью Derby Db

Я новичок в apache derby и я не могу заставить работать

    CREATE TABLE IF NOT EXISTS table1 ...

как можно достичь в MySql etc. Я получаю 'Syntax error: Encountered "NOT" at line 1, column 17.', когда я пытаюсь запустить этот SQL заявление в

9 ответов


создать таблицу, поймать SQLException и проверьте код состояния SQL.

полный список кодов ошибок можно найти здесь но я не смог найти Table <value> already exists; Это, наверное X0Y68. код, который вам нужен, это X0Y32.

просто запустите код один раз и распечатайте код ошибки. Не забудьте добавить тест, чтобы убедиться, что код работает; таким образом, вы можете поймать изменения в коде ошибки (не должно произойти ...).

в моих проектах, я обычно добавьте вспомогательный класс со статическими методами, чтобы я мог написать:

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

другой вариант-запустить SELECT против таблицы и проверьте код состояния (который должен быть 42X05). Но это вторая команда, которую вам нужно отправить, и она не предлагает никакой дополнительной информации.

что хуже, он может потерпеть неудачу по другим причинам, чем "таблица не существует", поэтому" создать и игнорировать ошибку " лучше IMO.


Derby не поддерживает этот sql-оператор.
В моей программе Я анализирую все таблицы из базы данных в набор и проверяю, существует ли там таблица. Вот так:

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

чтобы проверить, существует ли таблица:

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

чтобы показать все таблицы 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");
    }

выполняемый запрос не поддерживается 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-указать имя таблицы в верхнем регистре, иначе вы не сможете найти имя таблицы в метаданных.


после Аарон 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;
    }
}

другое решение с 2 условиями:

  • готов drop table перед созданием каждый раз, с тем же присутствием в a .sql-файл

  • используют весну и, следовательно, готовы использовать весна-теста как зависимость Maven, ваша жизнь может стать намного проще с его @Sql аннотации

Итак, сначала добавьте это как зависимость от вашего пом:

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

во-вторых, предполагая, что у вас есть sql, который падает, создает таблицу a в файле прямоугольник.в SQL:

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

указанного config атрибут value у @SqlConfig имеет магию, которая заставляет его пропустить падение ошибки оператора в случае, если таблица не существует. Я считаю, что он был написан специально для этих типов баз данных, которые не поддерживают ЕСЛИ СУЩЕСТВУЕТ для создания dropping / table (который derby действительно должен, даже если он не является частью стандарта 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. Другое дело, чтобы сделать правильную ошибку обращение.

  2. убедитесь, что класс скомпилирован и помещен в путь к классам виртуальной машины, в которой будет работать база данных.

  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, 
    -- (i.e. 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();
        }

окружите оператор create с помощью try-catch.и убедитесь, что комментарий е.printstacktace(); если он уже существует, он не показывает ошибку, иначе он создает таблицу..!!