Подтвердить что ты не робот

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

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

    CREATE TABLE IF NOT EXISTS table1 ...

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

Ответ 2

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

Ответ 3

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

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

Ответ 4

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

Ответ 5

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

См. также

Ответ 6

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

Ответ 7

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

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

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

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

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

Во-вторых, если у вас есть sql, который падает, создается таблица a в файле 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", [email protected] (errorMode=ErrorMode.IGNORE_FAILED_DROPS))
public class BlahTest { 
...
}

Указанное значение атрибута конфигурации @SqlConfig имеет волшебство, которое заставляет его пропускать ошибки оператора drop в случае, если таблица не существует. Я полагаю, что было написано специально для этих типов баз данных, которые не поддерживают IF EXISTS для создания drop/table (что действительно должно быть, даже если оно не является частью стандарта SQL на данный момент)

Ответ 8

Вот решение, которое вы можете script в SQL.

  • Создайте класс следующим образом:

    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. Другое дело было бы сделать правильную обработку ошибок.

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

  • Напишите свой SQL script:

    -- 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 turtles all the way down
    
    drop procedure CreateIfNotExists;
    
  • ???

  • прибыль

Ответ 9

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