как создать таблицу, если она не существует, используя Derby Db - PullRequest
26 голосов
/ 03 мая 2011

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

    CREATE TABLE IF NOT EXISTS table1 ...

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

Я зарегистрировался на странице документации для Derby Db Создание операторов , но не смог найти такую ​​альтернативу.

Ответы [ 9 ]

25 голосов
/ 03 мая 2011

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

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

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

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

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

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

Что еще хуже, она может потерпеть неудачу по другим причинам, чем «Таблица не существует», поэтому «создать иignore-error "лучше IMO.

12 голосов
/ 03 мая 2011

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());
    }
  }
4 голосов
/ 11 марта 2016

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

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");
    }
2 голосов
/ 31 января 2015

Я знаю, что это было помечено ответом, но в случае, если кто-то хочет другой способ проверки, я все равно хотел опубликовать.Здесь я проверяю метаданные таблицы с помощью метода, который возвращает логическое значение, 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 голосов
/ 17 сентября 2014

После Аарона Дигуллы с классом 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;
    }
}

Смотри также

2 голосов
/ 26 марта 2014

выполняемый запрос не поддерживается 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;
}

Поймать - указать имя таблицы в верхнем регистре, иначе вы выиграли 'невозможно найти имя таблицы в метаданных.

1 голос
/ 23 ноября 2017

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

  • Желание удалить таблицу перед каждым созданием, при этом то же самое присутствует в файле .sql

  • Используя Spring и, следовательно, желая использовать spring-test в качестве зависимости Maven, ваша жизнь может стать намного проще с ее @ Sql аннотацией

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

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

Во-вторых, если у вас есть SQL, который падает, создает таблицу в файле rectangle.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 значение атрибута @ SqlConfig обладает магией, которая заставляет его пропустить ошибки оператора отбрасывания в случае, если таблица не существует. Я полагаю, что он был написан специально для этих типов баз данных, которые не поддерживают IF EXISTS для удаления / создания таблиц (что действительно должно делать дерби, даже если он не является частью стандарта SQL в данный момент)

0 голосов
/ 21 февраля 2014
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.and и обязательно прокомментируйте e.printstacktace (); если он уже существует, он не показывает ошибку, в противном случае он создает таблицу .. !!

0 голосов
/ 23 мая 2013

Вот решение, которое вы можете написать в 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...");              
            }
        }       
    }
    

    }

    Примечание : вам не нужно использовать пружину, вы можете написать это прямо на 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. выгода
...