2010-09-27 4 views
33

Ich habe ein Standard-Tutorial für den Aufbau einer Datenbank mit Android gefolgt. Ich habe eine Klasse namens DbHelper erstellt, die SQLiteOpenHelper erweitert. Ich habe den Erstellungshandler überschrieben, um eine Zeichenfolge auszuführen.Mehrere Anweisungen mit SQLiteDatabase.execSQL ausführen

@Override 
public void onCreate(SQLiteDatabase db) { 
    db.execSQL(DbDefinitions.DB_CREATE); 
} 

DbDefinitions.DB_CREATE ist eine statische Zeichenfolge, die ich erstellt habe.

public static final String TABLE_MESSAGES = "messages"; 
public static final String TABLE_FRIENDS = "friends"; 

public static final String STATE_OK = "STATE_OK"; 

public static final String DB_CREATE = 
    "create table " + TABLE_MESSAGES + " (_id integer primary key, user_id integer not null, created_on integer, subject text not null, summary text not null, messagetext text null, read integer not null, status text not null default '" + STATE_OK + "'); " + 
    "create table " + TABLE_FRIENDS + " (_id integer primary key, user_id integer not null, friend_id integer not null, created_on integer, status text not null default '" + STATE_OK + "');"; 

Ich möchte 1 String verwenden, um mehrere SQL-Anweisungen auszuführen. Wie kann ich dies tun, da SQLiteDatabase.execSQL nur 1 Anweisung erlaubt?

Antwort

36

Das ist nicht möglich mit den Standardmethoden, die mit Android kommt. Also, wenn Sie Batch von mehreren SQL-Anweisungen ausführen möchten, müssen Sie Ihr eigenes Dienstprogramm erstellen, um dies zu tun. Zum Beispiel können Sie so etwas wie diese:

public void executeBatchSql(String sql){ 
    // use something like StringTokenizer to separate sql statements 
    for each sql statement{ 
     database.execSQL(oneStatement); 
    } 
} 

Obwohl, was ich tun würde so etwas wie diese:

String sql1 = "create bla bla bla;"; 
String sql2 = "create foo bar;"; 
String[] statements = new String[]{sql1, sql2}; 

// then 
for(String sql : statements){ 
    database.execSQL(sql); 
} 
+0

Danke, genau das, was ich funktioniert wie ein Zauber benötigt. –

+4

was ist, wenn das ';' ist in einem Textfeld? –

+1

Das **; ** am Ende der SQL-Anweisungen ist völlig nutzlos. –

0

Aus der Dokumentation von SQLiteDatabase und meiner Erfahrung in der Vergangenheit denke ich, dass es nicht möglich ist. Aber warum teilen Sie es nicht einfach in einzelne Anweisungen auf? Es ist wirklich kein Problem in Ihrem Beispiel. Oder benötigen Sie es für einen anderen Anwendungsfall?

16

Nun, in meinem Fall, ich bin Executing Abfragen aus einer Datei, die ich als Asset gespeichert Dies ist die Lösung, die ich verwendet + -

String script = readAsset(CREATE_SCRIPT);//readAsset is a method i use to get the file contents 
try { 
    String[] queries = script.split(";"); 
for(String query : queries){ 
     db.execSQL(query); 
    } 
} catch (Exception e) { 
    ..... 

EDIT

In meinem Fall waren die Abfragen einfache Einfügeabfragen, über die ich die volle Kontrolle hatte. Das Problem wurde jedoch bei Abfragen mit ";" In ihnen.

@TWiStErRob schlägt

script.split(";$");// $ meaning end of line. You will need to use RegexOption.MULTILINE for this to work 

oder

script.split(";\n");// but you will need to ensure that each query is on a different line 
+6

Ich bin neu in der Java- und Android-Entwicklung, aber Ihre Lösung kann in der Zeile script.split() fehlschlagen, wenn Ihre gespeicherten Anweisungen ein Semikolon als Teil eines Textwerts enthalten (z. B. auf dem Standardwert einer Spaltendefinition) – jon

+0

Sie sind Definitiv richtig. Ich glaube nicht, dass es sich um eine Java- oder Android-Sache handelt, sondern um ein Regex-Problem. Ich bin kein Regex-Guru, also kann ich dir nicht das genaue Ding geben, aber mit einer Regex, die überprüft, ob das Semikolon am Ende der Anweisung funktioniert. Dies funktioniert für mich, da mein Skript hauptsächlich die verschiedenen Tabellen erstellt. – frostymarvelous

+0

danke !, es hat funktioniert! – OWADVL

0

wir haben viele greate Antworten hier verwendet wird. und hier ist meine Lösung für mehrere Einfügeanweisungen, jedoch habe ich eine Datei in Assets nicht in der Zeile verwendet, jede Zeile in dieser Datei ist eine Insert-Anweisung.

try { 
     in = getAssets().open("InsertStatemets.SQL"); 
     BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 
     line = reader.readLine(); 

     while (line != null){ 
      db.execSQL(line); 
      Log.e("Insert Statement", line); 
     } 

    } catch (Exception e) { 

    } 
0

so etwas wie dieses Versuchen:

try { 
     InputStream is = this.context.getAssets().open("script.sql"); 
     BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 
     String line; 
     while ((line = reader.readLine()) != null) { 
      Log.i("SQL Script", line); 
      if (!line.isEmpty() && !line.trim().startsWith("--")) 
       db.execSQL(line); 
     } 
    } catch (IOException e) { 
     Log.e("SQL Script", e.getMessage()); 
    } 
    Log.i("SQL Script", "script executed"); 
Verwandte Themen