Datenbank Update / MIX

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Datenbank Update / MIX

    Hallo


    ich hatte schon einige SQLITE Datenbankfragen welche mir "jogimuc" bei "Anfängerfragen" super beantwortet hat.
    Diese Frage ist nun aber besser hier bei Datenbank Entwicklung aufgehoben.


    Ich bin auch noch ein Android / Java Anfänger und bräuchte deswegen etwas Hilfe
    Aktuelle Situation:
    Ich habe eine Datenbank im ASSETS Folder.
    Wenn bei der Installation noch keine Vorhanden ist wird diese ins Programm /data/data/*/databases/*.db kopiert.
    Meine Datenbank hat mehrere Colums (z.B.10)
    ID1-I100 wird geblockt und teilweise (z.B ID1 - ID 20) schon mit speziellen Daten gefüllt.
    Ab ID101 kann der User selbst noch Daten hinzufügen.
    Ebenso darf er Colum 9 und 10 (nur diese) der schon mitgelieferten Daten von ID1-* abändern.
    Nun meine Frage.
    Es kommt ein App Update.
    a) Dort stelle ich auch ein Update der Datenbank zu Verfügung (z.B. ID21-ID30) sind nun auch gefüllt (diese sind erst mal nur im ASSETS Folder).
    b) der User hat selbst in der App Datenbank Daten hinzugefügt (z.B. ID101-ID150)
    c) der User hat z.B. in der ID5,ID8,ID11 die Werte in der Colum 9 und 10 abgeändert.
    Wie muss ich vorgehen damit ich die Datenbank im ASSETS Folder mit der Datenbank in der APP zusammenbringe ohne Daten vom User zu verlieren.
    Also mehr oder weniger ein Vergleich beider und die Unterschiede in der App Datenbank wieder zusammenführen.


    Geht so was überhaupt?
    Und wenn ja wie? - welche Schritte benötit man dazu.


    Danke und Gruß
  • Hallo , na da bist du ja wieder. du bist echt super aktiv in dem Forum. Grosses Lob !

    Zu deiner Antwort. Die versteh ich jetzt nicht ganz Auto_Increment gibt ja nur die ID vor (das mit der ID ist ja nicht das Problem) und Alter_table ist nach dem was ich so gelesen habe nur wenn ich eine neue Colum mit hinzufüge.
    Mir geht es ja mehr darum bei einem Update der App und der Assets Datenbank nicht die Daten der User Datenbank zu verlieren. bzw. ich will zum Schluss einen Mix aus beiden.
    Jetzt fehlt mir entweder spezielles Wissen zu deiner Antwort, oder wir reden gerade aneinander vorbei, oder meine Fragestellung oben ist unklar.
  • OK dann Kanst du nur die Datensetze selbst in der Upgrate Methode einfügen . Dazu must du die Versions nummer der Datenbank erhöhen.
    Du könnsest die neue Datenbank in den Assets speichern . Wenn es eine neu Installation deiner App ist einfach Kopieren.
    Beim Upgrate nur die neuen Datensaätze einfügen. daszu könntest du die Datenbank in den Assets öffnen und die neuen Daten ,du weist ja welche neu sind, in die AppDatenbank Kopieren besser einfügen.

    Ein einfaches Kopieren ist bei einer bestehenden Datenbank nicht mehr möglich.
    Wie gesagt dafür giebt es die upgrate Metohde und die Versionsnummer. Mit der du in der Upgate Methote prüfen kast ob es eine neue Datenbank version giebt.

    Ps. die ID Nummern stimmen dann zwar nicht meher überein ist aber eigentlich auch egal. oder du läst den user erst mit ID z.b.
    1000 beginnen. stackoverflow.com/questions/69…r-autoincrement-in-sqlite
    Dazu müstest du die ID bei deinen Einfügen auch erst wieder auf deinen Nummernkreis setzen und anschliesend zurück . Finde das einen zu grossen aufwand der nichst bringt.
    Ein Feedback auf Tipps ist auch schön. :P

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von jogimuc ()

  • Also kurz zusammengefasst.
    a) Der User kann erst daten ab ID1000 einfügen - Das hatte ich ja eh vor. (halt nur bei mir ab ID100) =OK (ich geb schon eine ID1000 in der Datenbank vor und durch Autoincrement wird dann ja ab der höchsten weiter gezählt)
    b) Ich weis genau was ich in ID1 - ID999 geändert habe = OK
    c) nun das Problem wie kann man eine ID oder eine Zelle von der Assets Datenbank in die App Datenbank kopieren. Ich weis nicht die Befehle und die Vorgehensweise.
    Also z.B kopie von ID11 zu ID11(ID11 besteht entweder schon und wird überschrieben oder wenn nicht neu erstellt.)

    Ich hab mal im Internet gesucht, aber ich werde nicht richtig schlau daraus. Finde bis jetzt auch noch nichts passendes (hängt warscheinlich noch daran wie ich suche)

    Hast du da vielleicht mal einen Beispielcode. :) :-[
    Gruß

    (Was ich gefunden habe ist z.B. sqldiff [options] database1.sqlite database2.sqlite) das wäre ja sehr einfach. Kann es aber erst am Wochenende testen.
  • also sqldiff ist ein Differenz utiliti was auf einem pc läuft kann dir nicht sagen ob das auf android verfügbar ist denke nein.
    Das mit den id Nummer ist eigentlich egal wenn du wegen einer Sortierung d eine Nummer brauchst dann füge selber eine Spalte hin zu mit einer Nummer .
    Ich meine du sollst die Datenbank in den assets öffnen daraus die neuen Daten in einen Cursor abfragen und in der app Datenbank einfügen mit insert. Die id s sind dann zwar durcheinander das macht nichts du sortiert doch selber deine Daten. Dazu ist eine Datenbank da.
    Wenn du es bis we nicht schaffst werde ich versuchen etwas Code zu schreiben.
    Wenn unbedingt die id Nummern synchron mit deinen sein müssen. Könntest du das autoinkrement für die Zeit des Updates ausschalten und dann die id selber setzen. Am ende wieder einschalten. Wie ich so sagte finde ich diesen weg nutzlos,wird auch kaum einer machen.
    Wenn du sortiert durch deine Daten scrollen willst da mache eine sortierte Abfrage der Datenbank,dann ist der Cursor sortiert.
    Die id Nummern werden nie durchgehend sein was machst du wen der User Daten löscht und wieder neue eingiebt dann werden die auch nicht in die Lücken geschrieben.
    Ein Feedback auf Tipps ist auch schön. :P

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von jogimuc ()

  • Ok, ich werde das mit der Abfrage und dem einfügen so probieren.
    Das mit den ids das die nacheinander sind hat den Grund, da ich Buttons für Vorwärts und Rückwärts habe. Da kann ich die Daten nicht Kreuz und Quer einfügen.
    Ich tu mich damit auch glaub ich leichter zu entscheiden was von mir mitgegeben wird und was vom user schon dazugefügt wurde.
    Natürlich ist es wurscht ob die ID1,ID3,ID4,ID20 von mir so kommt und der User ab ID1000,ID1001,ID1012 seine Daten hinzufügt.
    Ich hab dann nur das Problem wenn ich durch viele Updates irgendwann mal bei meinen mitgegebenen Daten bei ID999 lande.
    Deshalb der Grund alles nacheinander.(weil 999 einzelne Zeilen werde ich nie und nimmer als info mitgeben)
    Aber ich werde jetzt doch nochmal einiges durchlesen. Vielleicht hab ich immer noch was nicht richtig verstanden und dann macht es hoffentlich klick.
    Danke nochmal. Falls ich doch Probleme mit der Umsetztung habe melde ich mich nochmal.

    Gruß
  • Das mit den Plus minus Tasten weiß ich. Habe die ja da auch geholfen. Deshalb sollst du deine Datetenbank bei der Abfrage sortieren lassen. Schaue die die query answeisung an mit order by ACS sortirst du bei der Abfrage. Dein cursor ist dann sortirst egal in welcher Reihenfolge die Daten wirglich in der DB sind. Dafür must du brauchst du eins Spalte die sich sortieren läßt zb. Datum selber verwalte Index Nummer... Was dir beliebt. Schaue dir etwas SQL an. Was alles mit der SELECT Anweisung möglich ist. Das geht auch mit der query oder RAwquery Methode von Android
    Gruß Jörg
    Ein Feedback auf Tipps ist auch schön. :P
  • Ich habe heute ewig gekämpft um das mit dem Upgrade (überschreiben einer neueren Assets db Version mit der user db Version.
    Ich habe lange gesucht wie man die db Version der Assets Datenbank herausfindet - geht scheinbar nicht. Dann hatte ich immer das Problem das ich die neue Datenbankversion zwar kopiert hatte aber dann die app immer abgebrochen hat. Wusste nicht das man auch die Version

    Quellcode

    1. super(context, DATABASE_NAME, null,DATABASEVERSION );
    hier auch extra noch korrekt einstellen muss. Also das kostet echt Nerven.

    Nun aber habe ich ein neues Problem. Ich finde einfach keine Möglichkeit wie man in einem Assets Ordner die Datenbank öffnet und sie an einem Cursor übergibt. > wollte deinen Vorschlag übernehmen.
    Ich hab mir gedacht vielleicht speichere ich die Aktuelle Datenbank zwischen, kopiere dann die Assets Datenbank (überschreibe die Aktuelle) und mixe beide und hab dann eine Neue. Aber das haut auch irgendwie nicht hin. Diese Scheixx Datenbank regt mich echt langsam auf.
  • Hallo am besten du erstellst dir eine extra Klasse für das auslesen der Datenbank in den Assets. Die DB Version soltest du am besten in einer Konstanten speichern und im gesamten Projekt benutzen. Du weißt doch welche Version du in den Asssets mit giebst.
    bzw. du auch in deiner App nach dem Update verwendest.

    Dann hast du zwei DB zu gleichen Zeit geöffnet und kannst von der einen Daten abfragen( lesen in den Cursor) und anschliesend in die andere einfügen ( schreiben).
    Wenn du ein Update der App heraus giebst und in dieser die DB änderst must du immer die Version mit ändern. die DB in den Assets und die App DB solten die gleiche Version haben. Denn wenn ein User erst jetzt deine App installirt wird ja die DB aus den Assets kopiert sonst nicht. So solteste es sein.
    Die DB in den Assets brauchst du nicht kopieren wenn die app schon vorhanden installiert war.
    Zur Info die create Metohde der DB wird nur duchlaufen wenn es die Db noch nicht giebt also nur einmal.
    Später nicht wieder.
    Die upgrate Methode wird duchlaufen wenn die DB schon erstellt ist. Dort prüfst du die Versionen.
    Und fürst dort deinen Code für die änderunern an der DB aus.

    private String DB_PATH = getAssets().getLocales();
    private static String DB_NAME = "Daten.db";



    public void openDataBase() throws SQLException{

    //Open the database
    String myPath = DB_PATH + DB_NAME;
    myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);

    }
    }

    Ps. werde versuchen am WE ein par Code Zeilen zu schreiben.
    Ein Feedback auf Tipps ist auch schön. :P

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von jogimuc ()

  • Also das ist mir jetzt schon hoffentlich alles klar, aber mein Problem ist immer noch wie ich einen Cursor auf die
    Datenbank im Assets Folder bringe. (Zeile 6 )
    Ich habe nirgendwo gefunden wie ich direkt die ***assets/databases/database.db "öffnen" kann.
    Das mit den ???? ist jetzt nur Platzhalter. Kanns du mir da vielleicht mal einen Code schnippsel Zeigen wie du das machst.

    Quellcode

    1. String selectQuery = "SELECT * FROM " + TABLE_NAME;
    2. SQLiteDatabase db = this.getWritableDatabase();
    3. Cursor cursor = db.rawQuery(selectQuery, null);
    4. SQLiteDatabase dbAssets = ????.getWritableDatabase();
    5. Cursor cursorAssets = dbAssets.rawQuery(selectQuery, null);
  • So geht das nicht. erstelle dir eine neue Klasse für die dB der Assets. in etwa so
    ist aus einem alten projekt von mir . habe im momet wenig zeit.
    zugriff dbZugriff = new DBZugriff(this);



    Brainfuck-Quellcode

    1. //-----------------------------------------------------------------------------------------
    2. public class DBZugriff extends SQLiteOpenHelper {
    3. private SQLiteDatabase db;
    4. private String tabelle;
    5. static final int DatenBankVersion = 2 ;
    6. private static final String DatenBankName = getAssets()+"Db.db";
    7. private static final String TAG = DBZugriff.class.getSimpleName();
    8. DB_Datensatz datensatz;
    9. private String zeitenSQL = "CREATE TABLE Zeiten (_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
    10. "datum TEXT," +
    11. "zeitein DATE, " +
    12. )";
    13. //-----------------------------------------------------------------------------------------
    14. public DBZugriff(Context activity) {
    15. super(activity, DatenBankName, null, DatenBankVersion);
    16. Log.d(TAG, "Konstrucktor");
    17. tabelle = "Zeiten";
    18. db = this.getWritableDatabase();
    19. //db.execSQL("DROP TABLE Bemerkung");
    20. }
    21. //-----------------------------------------------------------------------------------------
    22. @Override
    23. /**
    24. * Wird nur aufgerufen, wenn eine Datenbank neu erzeugt wird
    25. */
    26. public void onCreate(SQLiteDatabase db) {
    27. try {
    28. // Tabelle anlegen
    29. db.execSQL(zeitenSQL);
    30. Log.d(TAG, "datenbank wird angelegt");
    31. }
    32. catch(Exception ex) {
    33. Log.e("carpelibrum", ex.getMessage());
    34. }
    35. }
    36. //-----------------------------------------------------------------------------------------
    37. @Override
    38. public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    39. Einstellungen pref =new Einstellungen();
    40. if(oldVersion < 2 && newVersion >= 2) {
    41. }
    42. }
    43. //-----------------------------------------------------------------------------------------
    44. /**
    45. * Hier noch evtl. eigene Aufräumarbeiten durchführen
    46. */
    47. @Override
    48. public synchronized void close() {
    49. if(db != null) {
    50. db.close();
    51. db = null;
    52. }
    53. super.close();
    54. }
    55. //
    56. /
    57. /
    58. //---------------------------------------------------------------------
    59. public Cursor leseAlleDaten() {
    60. String[] suchen ={"2000-01-01"};
    61. String[] spalten = new String[]{"_id","datum","zeitein" };
    62. return db.query(tabelle, spalten, "datum <>?",suchen, null, null, "datum ASC");
    63. }
    64. /
    65. }
    Alles anzeigen
    Ein Feedback auf Tipps ist auch schön. :P

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von jogimuc ()

  • Vielen Dank für den Code. Da sind mir nun wieder ein Paar Lichter aufgegangen.
    Aber ein Problem bleibt immer noch, und das ist mitunter ein Problem wo ich schon lange nach der Lösung suche.

    Quellcode

    1. private static final String DatenBankName = getAssets()+"Db.db";
    Nämlich nach dem "DatenBankName ".
    getAssets() funktioniert nicht. Das ist im Code "ROT" .
    Warum hat das bei dir funktioniert und bei mir nicht. Das ist ja nicht nur ein Name sondern ein "Vereichnis" + File. Ich habe schon versucht nur
    "assets/databases/database.db" herzunehmen (wo es bei mir auch abgelegt is.)
    (ohne getAssets()), das funktioniert aber auch nicht. Ich hab auch mal .db weggelassen und und und.

    Der Debugger bricht dann bei db = this.getWritableDatabase() ab. Ist ja auch klar, weil er scheinbar nichts findet.
    So, jetzt ist es 0:30 - jetzt ist Schluss :)
  • So nun meine Version.
    Die Datenbank in den Assets öffnen habe ich nicht geschaft.
    Kopiere die Db aus den Assets in den App Folder und öffne sie von dort.
    Am ende wird sie wieder gelöscht.

    Java-Quellcode

    1. public class DB_Datensatz2 {
    2. // Variablen
    3. public long id;
    4. public String datum;
    5. public int zeitein;
    6. /**
    7. * Konstruktor
    8. */
    9. public DB_Datensatz2(String datum, int zeitein ) {
    10. this.datum = datum;
    11. this.zeitein = zeitein;
    12. id = -1; // wird erst beim Einfügen in die Datenbank erzeugt
    13. }
    14. /**
    15. * Konstruktor
    16. */
    17. public DB_Datensatz2() {
    18. }
    19. }
    Alles anzeigen



    Java-Quellcode

    1. //-----------------------------------------------------------------------------------------
    2. public class DBZugriff_test extends SQLiteOpenHelper {
    3. private SQLiteDatabase db;
    4. private String tabelle="Zeiten";
    5. static final int DatenBankVersion = 2;
    6. private static final String DatenBankName = "Zeiterfassung.db";
    7. private Context activity;
    8. DB_Datensatz2 datensatz;
    9. private String zeitenSQL = "CREATE TABLE Zeiten (_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
    10. "datum TEXT," +
    11. "zeitein DATE )";
    12. //-----------------------------------------------------------------------------------------
    13. public DBZugriff_test(Context activity) {
    14. super(activity, DatenBankName, null, DatenBankVersion);
    15. db = this.getWritableDatabase();
    16. }
    17. //-----------------------------------------------------------------------------------------
    18. @Override
    19. /**
    20. * Wird nur aufgerufen, wenn eine Datenbank neu erzeugt wird
    21. */
    22. public void onCreate(SQLiteDatabase db) {
    23. try {
    24. // Tabelle anlegen
    25. db.execSQL(zeitenSQL);
    26. }
    27. catch(Exception ex) {
    28. }
    29. }
    30. //-----------------------------------------------------------------------------------------
    31. @Override
    32. public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    33. if(oldVersion < 2 && newVersion >= 2) {
    34. Cursor cu;
    35. // DB aus den Assets Kopieren
    36. try {
    37. InputStream inputStream = activity.getAssets().open("Zeiterfassung.db");
    38. String outFileName = activity.getDatabasePath("Zeiterfassung_kopy.db").toString();
    39. OutputStream outputStream = new FileOutputStream(outFileName);
    40. byte[]buff = new byte[1024];
    41. int length = 0;
    42. while ((length = inputStream.read(buff)) > 0) {
    43. outputStream.write(buff, 0, length);
    44. }
    45. outputStream.flush();
    46. outputStream.close();
    47. Log.w("MainActivity","DB copied");
    48. }catch (Exception e) {
    49. e.printStackTrace();
    50. }
    51. SQLiteDatabase assetDb = activity.openOrCreateDatabase(activity.getDatabasePath("Zeiterfassung_kopy.db").toString(),activity.MODE_PRIVATE, null);
    52. String[] spalten = new String[]{"_id","datum","zeitein" };
    53. String ein ="1";
    54. String aus ="2";
    55. cu = assetDb.query(tabelle,
    56. spalten,
    57. "_id >= '"+ein+"'AND _id <= '"+aus+"' ",
    58. null,
    59. null,
    60. null,
    61. "_id ASC");
    62. if (cu.getCount() != 0) {
    63. cu.moveToFirst();
    64. do {
    65. datensatz = new DB_Datensatz2(cu.getString(1), cu.getInt(2));
    66. ContentValues daten = erzeugeDatenObjekt(datensatz);
    67. assetDb.insert(tabelle, null, daten);
    68. } while (cu.moveToNext());
    69. File file = new File(activity.getDatabasePath("Zeiterfassung_kopy.db").toString());
    70. boolean deleted = file.delete();
    71. }
    72. }
    73. }
    74. //-----------------------------------------------------------------------------------------
    75. /**
    76. * Hier noch evtl. eigene Aufräumarbeiten durchführen
    77. */
    78. @Override
    79. public synchronized void close() {
    80. if(db != null) {
    81. db.close();
    82. db = null;
    83. }
    84. super.close();
    85. }
    86. //-----------------------------------------------------------------------------------------
    87. public long datensatzEinfügen(DB_Datensatz2 datensatz) {
    88. try {
    89. ContentValues daten = erzeugeDatenObjekt(datensatz);
    90. return db.insert(tabelle, null, daten);
    91. }
    92. catch(Exception ex) {
    93. return -1;
    94. }
    95. }
    96. //---------------------------------------------------------------------
    97. public Cursor leseDatensatzTag(String suchString)
    98. {
    99. //String.valueOf
    100. String[] suchen ={suchString};
    101. String[] spalten = new String[]{"_id","datum","zeitein" };
    102. Cursor cu;
    103. cu = db.query(tabelle, spalten,"datum=?",
    104. suchen ,
    105. null, null, null);
    106. return cu;
    107. }
    108. //---------------------------------------------------------------------
    109. public Cursor leseAlleDaten() {
    110. String[] suchen ={"2000-01-01"};
    111. String[] spalten = new String[]{"_id","datum","zeitein" };
    112. return db.query(tabelle, spalten, "datum <>?",suchen, null, null, "datum ASC");
    113. }
    114. //-----------------------------------------------------------------------------------------
    115. private ContentValues erzeugeDatenObjekt(DB_Datensatz2 datensatz) {
    116. ContentValues daten = new ContentValues();
    117. if(datensatz.datum != null) daten.put("datum", datensatz.datum);
    118. daten.put("zeitein", datensatz.zeitein);
    119. return daten;
    120. }
    121. }
    Alles anzeigen
    Ein Feedback auf Tipps ist auch schön. :P

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von jogimuc ()

  • ansonsten hättest du noch die Möglichkeit die Datensätze die du hinzufügen willst dierekt aus dem Code einzugeben oder sie in einer txt in den asset zu speichern.

    Eine direkte pathangabe zu den wusste hat bei mir auch nicht geklappt. Deshalb über den assetmanager und virtuellen path.
    Ein Feedback auf Tipps ist auch schön. :P