14

JDBC を使用して Apache Derby DB のスキーマ内のすべてのテーブルを削除するにはどうすればよいですか?

4

11 に答える 11

7

ブログに感謝します:

ステップ1:

SQL ステートメントを実行しますが、スキーマ名 'APP' を次の 2 つのスキーマ名に置き換えることを忘れないでください。

SELECT
'ALTER TABLE '||S.SCHEMANAME||'.'||T.TABLENAME||' DROP CONSTRAINT '||C.CONSTRAINTNAME||';'
FROM
    SYS.SYSCONSTRAINTS C,
    SYS.SYSSCHEMAS S,
    SYS.SYSTABLES T
WHERE
    C.SCHEMAID = S.SCHEMAID
AND
    C.TABLEID = T.TABLEID
AND
S.SCHEMANAME = 'APP'
UNION
SELECT 'DROP TABLE ' || schemaname ||'.' || tablename || ';'
FROM SYS.SYSTABLES
INNER JOIN SYS.SYSSCHEMAS ON SYS.SYSTABLES.SCHEMAID = SYS.SYSSCHEMAS.SCHEMAID
where schemaname='APP';

ステップ2:

上記の実行の結果は一連の SQL ステートメントであり、それらを SQL エディターにコピーして実行すると、制約とテーブルが削除されます。

于 2014-04-06T04:58:54.123 に答える
5

これを行う実際のコードについては、Derby ディストリビューションの Derby テスト スイート セクションにあるCleanDatabaseTestSetup.javaを確認してください。

于 2009-11-14T15:32:05.087 に答える
3

あなたが実行するJavaで少しメソッドを実行します

DROP TABLE [tablename]

tablenameパラメータによって渡されます。

そして、クエリによって形成されたレコードセットをループする別の方法

SELECT tablename FROM SYSTABLES

最初のメソッドを呼び出します。

ダービーの最新のドキュメント

于 2008-10-05T09:58:09.727 に答える
1

ほとんどのdbプロバイダーはDROPTABLE*(または同様のもの)を許可していないと思います。

最善の方法は、テーブルを表示してから、結果セットを介してループ内で各削除を実行することだと思います。

HTH。

于 2008-10-05T09:44:49.160 に答える
0

より簡単な解決策は、JDBCを使用して「dropdatabasefoo」を実行してから「createdatabasefoo」を実行することです。ただし、これにより、DB内のすべてのオブジェクト(つまり、テーブルだけでなく)が削除されます。

于 2008-10-05T23:20:04.007 に答える
0

JDBCを使用すると、データベースに依存しない方法でタスクを解決できます。

  1. 接続を開きます
  2. DatabaseMetaDataを取得します
  3. これを使用して、データベースJavaDoc内のすべてのテーブルを一覧表示します
  4. 結果セットを反復処理し、テーブルごとにDROPTABLEを起動します
于 2008-10-05T10:31:08.613 に答える
0

JDBC ではなくコマンド プロンプトから作業している場合は、これで作業を開始できます。

SELECT 'DROP TABLE ' || schemaname ||'.' || tablename || ';'
FROM SYS.SYSTABLES
INNER JOIN SYS.SYSSCHEMAS ON SYS.SYSTABLES.SCHEMAID = SYS.SYSSCHEMAS.SCHEMAID
;
于 2012-12-18T07:55:28.263 に答える
0

http://squirrel-sql.sourceforge.net/から Squirrel SQL をダウンロードします。

データベースに接続します。

TABLE ノードを展開します。

削除するテーブルを選択します。

右クリックして選択 -> スクリプト -> テーブル スクリプトのドロップ

生成されたクエリを実行する

レコードの削除を選択して、選択したテーブルを空にすることもできます。

于 2013-11-17T15:41:20.003 に答える
0
  1. Derby DB システム カタログからスキーマとテーブル名を生成する必要があります。
  2. すべてのテーブルをリレーションで並べ替えます。
  3. すべてのテーブルを削除するための Java ステートメントを生成する
  4. autoCommit() メソッドを使用して、このメソッドを false に設定します。エラーが発生した場合の手動コミットまたはロールバック トランザクション用。
  5. Javaプロセスを実行します。幸運を。
于 2008-10-05T15:48:51.047 に答える
0

毎回 SQL を手動でコピーして貼り付けることなく、すべてのスキーマをプログラムで削除したい場合は、org.apache.derbyTesting.junit.CleanDatabaseTestSetupおよびorg.apache.derbyTesting.junit.JDBCから持ち上げたコードを次に示します。dropAllSchemas(connection); を呼び出すだけです。

public static void dropAllSchemas(Connection conn) throws SQLException {
    DatabaseMetaData dmd = conn.getMetaData();
    SQLException sqle = null;
    // Loop a number of arbitary times to catch cases
    // where objects are dependent on objects in
    // different schemas.
    for (int count = 0; count < 5; count++) {
        // Fetch all the user schemas into a list
        List<String> schemas = new ArrayList<String>();
        ResultSet rs = dmd.getSchemas();
        while (rs.next()) {
            String schema = rs.getString("TABLE_SCHEM");
            if (schema.startsWith("SYS"))
                continue;
            if (schema.equals("SQLJ"))
                continue;
            if (schema.equals("NULLID"))
                continue;
            schemas.add(schema);
        }
        rs.close();
        // DROP all the user schemas.
        sqle = null;
        for (String schema : schemas) {
            try {
                dropSchema(dmd, schema);
            } catch (SQLException e) {
                sqle = e;
            }
        }
        // No errors means all the schemas we wanted to
        // drop were dropped, so nothing more to do.
        if (sqle == null)
            return;
    }
    throw sqle;
}


/**
 * Constant to pass to DatabaseMetaData.getTables() to fetch
 * just tables.
 */
public static final String[] GET_TABLES_TABLE = new String[] {"TABLE"};
/**
 * Constant to pass to DatabaseMetaData.getTables() to fetch
 * just views.
 */
public static final String[] GET_TABLES_VIEW = new String[] {"VIEW"};
/**
 * Constant to pass to DatabaseMetaData.getTables() to fetch
 * just synonyms.
 */
public static final String[] GET_TABLES_SYNONYM =
    new String[] {"SYNONYM"};
/**
 * Drop a database schema by dropping all objects in it
 * and then executing DROP SCHEMA. If the schema is
 * APP it is cleaned but DROP SCHEMA is not executed.
 * 
 * TODO: Handle dependencies by looping in some intelligent
 * way until everything can be dropped.
 * 

 * 
 * @param dmd DatabaseMetaData object for database
 * @param schema Name of the schema
 * @throws SQLException database error
 */
public static void dropSchema(DatabaseMetaData dmd, String schema) throws SQLException{     
    Connection conn = dmd.getConnection();
    Statement s = dmd.getConnection().createStatement();

    // Triggers
    PreparedStatement pstr = conn.prepareStatement(
            "SELECT TRIGGERNAME FROM SYS.SYSSCHEMAS S, SYS.SYSTRIGGERS T "
            + "WHERE S.SCHEMAID = T.SCHEMAID AND SCHEMANAME = ?");
    pstr.setString(1, schema);
    ResultSet trrs = pstr.executeQuery();
    while (trrs.next()) {
        String trigger = trrs.getString(1);
        s.execute("DROP TRIGGER " + escape(schema, trigger));
    }
    trrs.close();
    pstr.close();

    // Functions - not supported by JDBC meta data until JDBC 4
    // Need to use the CHAR() function on A.ALIASTYPE
    // so that the compare will work in any schema.
    PreparedStatement psf = conn.prepareStatement(
            "SELECT ALIAS FROM SYS.SYSALIASES A, SYS.SYSSCHEMAS S" +
            " WHERE A.SCHEMAID = S.SCHEMAID " +
            " AND CHAR(A.ALIASTYPE) = ? " +
            " AND S.SCHEMANAME = ?");
    psf.setString(1, "F" );
    psf.setString(2, schema);
    ResultSet rs = psf.executeQuery();
    dropUsingDMD(s, rs, schema, "ALIAS", "FUNCTION");        

    // Procedures
    rs = dmd.getProcedures((String) null,
            schema, (String) null);
    
    dropUsingDMD(s, rs, schema, "PROCEDURE_NAME", "PROCEDURE");
    
    // Views
    rs = dmd.getTables((String) null, schema, (String) null,
            GET_TABLES_VIEW);
    
    dropUsingDMD(s, rs, schema, "TABLE_NAME", "VIEW");
    
    // Tables
    rs = dmd.getTables((String) null, schema, (String) null,
            GET_TABLES_TABLE);
    
    dropUsingDMD(s, rs, schema, "TABLE_NAME", "TABLE");
    
    // At this point there may be tables left due to
    // foreign key constraints leading to a dependency loop.
    // Drop any constraints that remain and then drop the tables.
    // If there are no tables then this should be a quick no-op.
    ResultSet table_rs = dmd.getTables((String) null, schema, (String) null,
            GET_TABLES_TABLE);

    while (table_rs.next()) {
        String tablename = table_rs.getString("TABLE_NAME");
        rs = dmd.getExportedKeys((String) null, schema, tablename);
        while (rs.next()) {
            short keyPosition = rs.getShort("KEY_SEQ");
            if (keyPosition != 1)
                continue;
            String fkName = rs.getString("FK_NAME");
            // No name, probably can't happen but couldn't drop it anyway.
            if (fkName == null)
                continue;
            String fkSchema = rs.getString("FKTABLE_SCHEM");
            String fkTable = rs.getString("FKTABLE_NAME");

            String ddl = "ALTER TABLE " +
                escape(fkSchema, fkTable) +
                " DROP FOREIGN KEY " +
                escape(fkName);
            s.executeUpdate(ddl);
        }
        rs.close();
    }
    table_rs.close();
    conn.commit();
            
    // Tables (again)
    rs = dmd.getTables((String) null, schema, (String) null,
            GET_TABLES_TABLE);        
    dropUsingDMD(s, rs, schema, "TABLE_NAME", "TABLE");

    // drop UDTs
    psf.setString(1, "A" );
    psf.setString(2, schema);
    rs = psf.executeQuery();
    dropUsingDMD(s, rs, schema, "ALIAS", "TYPE");        

    // drop aggregates
    psf.setString(1, "G" );
    psf.setString(2, schema);
    rs = psf.executeQuery();
    dropUsingDMD(s, rs, schema, "ALIAS", "DERBY AGGREGATE");        
    psf.close();

    // Synonyms - need work around for DERBY-1790 where
    // passing a table type of SYNONYM fails.
    rs = dmd.getTables((String) null, schema, (String) null,
            GET_TABLES_SYNONYM);
    
    dropUsingDMD(s, rs, schema, "TABLE_NAME", "SYNONYM");
            
    // sequences
    if ( sysSequencesExists( conn ) )
    {
        psf = conn.prepareStatement
            (
             "SELECT SEQUENCENAME FROM SYS.SYSSEQUENCES A, SYS.SYSSCHEMAS S" +
             " WHERE A.SCHEMAID = S.SCHEMAID " +
             " AND S.SCHEMANAME = ?");
        psf.setString(1, schema);
        rs = psf.executeQuery();
        dropUsingDMD(s, rs, schema, "SEQUENCENAME", "SEQUENCE");
        psf.close();
    }

    // Finally drop the schema if it is not APP
    if (!schema.equals("APP")) {
        s.executeUpdate("DROP SCHEMA " + escape(schema) + " RESTRICT");
    }
    conn.commit();
    s.close();
}

    /**
 * Return true if the SYSSEQUENCES table exists.
 */
private static boolean sysSequencesExists( Connection conn ) throws SQLException
{
    PreparedStatement ps = null;
    ResultSet rs =  null;
    try {
        ps = conn.prepareStatement
            (
             "select count(*) from sys.systables t, sys.sysschemas s\n" +
             "where t.schemaid = s.schemaid\n" +
             "and ( cast(s.schemaname as varchar(128)))= 'SYS'\n" +
             "and ( cast(t.tablename as varchar(128))) = 'SYSSEQUENCES'" );
        rs = ps.executeQuery();
        rs.next();
        return ( rs.getInt( 1 ) > 0 );
    }
    finally
    {
        if ( rs != null ) { rs.close(); }
        if ( ps != null ) { ps.close(); }
    }
}

/**
 * Escape a non-qualified name so that it is suitable
 * for use in a SQL query executed by JDBC.
 */
public static String escape(String name)
{
    StringBuffer buffer = new StringBuffer(name.length() + 2);
    buffer.append('"');
    for (int i = 0; i < name.length(); i++) {
        char c = name.charAt(i);
        // escape double quote characters with an extra double quote
        if (c == '"') buffer.append('"');
        buffer.append(c);
    }
    buffer.append('"');
    return buffer.toString();
}   

/**
 * Escape a schema-qualified name so that it is suitable
 * for use in a SQL query executed by JDBC.
 */
public static String escape(String schema, String name)
{
    return escape(schema) + "." + escape(name);
}


/**
 * DROP a set of objects based upon a ResultSet from a
 * DatabaseMetaData call.
 * 
 * TODO: Handle errors to ensure all objects are dropped,
 * probably requires interaction with its caller.
 * 
 * @param s Statement object used to execute the DROP commands.
 * @param rs DatabaseMetaData ResultSet
 * @param schema Schema the objects are contained in
 * @param mdColumn The column name used to extract the object's
 * name from rs
 * @param dropType The keyword to use after DROP in the SQL statement
 * @throws SQLException database errors.
 */
private static void dropUsingDMD(
        Statement s, ResultSet rs, String schema,
        String mdColumn,
        String dropType) throws SQLException
{
    String dropLeadIn = "DROP " + dropType + " ";
    
    // First collect the set of DROP SQL statements.
    ArrayList<String> ddl = new ArrayList<String>();
    while (rs.next())
    {
        String objectName = rs.getString(mdColumn);
        String raw = dropLeadIn + escape(schema, objectName);
        if (
            "TYPE".equals( dropType )  ||
            "SEQUENCE".equals( dropType ) ||
            "DERBY AGGREGATE".equals( dropType )
            )
        { raw = raw + " restrict "; }
        ddl.add( raw );
    }
    rs.close();
    if (ddl.isEmpty())
        return;
            
    // Execute them as a complete batch, hoping they will all succeed.
    s.clearBatch();
    int batchCount = 0;
    for (Iterator i = ddl.iterator(); i.hasNext(); )
    {
        Object sql = i.next();
        if (sql != null) {
            s.addBatch(sql.toString());
            batchCount++;
        }
    }

    int[] results;
    boolean hadError;
    try {
        results = s.executeBatch();
        //Assert.assertNotNull(results);
        //Assert.assertEquals("Incorrect result length from executeBatch", batchCount, results.length);
        hadError = false;
    } catch (BatchUpdateException batchException) {
        results = batchException.getUpdateCounts();
        //Assert.assertNotNull(results);
        //Assert.assertTrue("Too many results in BatchUpdateException", results.length <= batchCount);
        hadError = true;
    }
    
    // Remove any statements from the list that succeeded.
    boolean didDrop = false;
    for (int i = 0; i < results.length; i++)
    {
        int result = results[i];
        if (result == Statement.EXECUTE_FAILED)
            hadError = true;
        else if (result == Statement.SUCCESS_NO_INFO || result >= 0) {
            didDrop = true;
            ddl.set(i, null);
        }
        //else
            //Assert.fail("Negative executeBatch status");
    }
    s.clearBatch();
    if (didDrop) {
        // Commit any work we did do.
        s.getConnection().commit();
    }

    // If we had failures drop them as individual statements
    // until there are none left or none succeed. We need to
    // do this because the batch processing stops at the first
    // error. This copes with the simple case where there
    // are objects of the same type that depend on each other
    // and a different drop order will allow all or most
    // to be dropped.
    if (hadError) {
        do {
            hadError = false;
            didDrop = false;
            for (ListIterator<String> i = ddl.listIterator(); i.hasNext();) {
                String sql = i.next();
                if (sql != null) {
                    try {
                        s.executeUpdate(sql);
                        i.set(null);
                        didDrop = true;
                    } catch (SQLException e) {
                        hadError = true;
                    }
                }
            }
            if (didDrop)
                s.getConnection().commit();
        } while (hadError && didDrop);
    }
}

PS: このコードは、データベースを DROP ALL OBJECTS をサポートする H2 からサポートしないApache Derby に移行したときに役立ちました(頭痛の種)。H2 から移行した唯一の理由は、完全なインメモリ データベースであり、サーバーの RAM に対して大きくなりすぎたため、Apache Derby を試すことにしました。H2 は Derby よりもはるかに簡単で使いやすいため、強くお勧めします。H2 を使い続けるための RAM を買う余裕がないのは悲しいことです。ところで、Derby の LIMIT または UPSERT の欠如の影響を受ける人は、LIMIT の代わりにFETCH NEXTを代用することに関するこの記事と、正しくMERGE INTOを使用することに関するこの記事を参照してください。

于 2022-01-14T04:24:40.613 に答える