SQLite
 sql >> Baza danych >  >> RDS >> SQLite

Jak odczytać numer wersji z pliku bazy danych w systemie Android, który jest umieszczony w folderze zasobów

Nie ma jednego numeru wersji, zamiast tego numer wersji może zawierać wiele wartości.

Przypuszczam, że mówisz o wersji_użytkownika którego używa Android SDK SQLiteOpenHelper.

Istnieje również application_id , która podobnie jak user_version może być używana jako zmienna użytkownika.

Napotkałeś już SQLite_Version, więc możesz to zdyskontować.

Istnieje również data_version, jest to mało prawdopodobne, aby był to numer wersji, ponieważ ma służyć jako wskazówka, czy plik bazy danych został zmodyfikowany w czasie rzeczywistym.

Istnieje również wersja schema_version, prawdopodobnie NIE chcesz jej używać jako Ostrzeżenie:niewłaściwe użycie tej pragmy może spowodować uszkodzenie bazy danych.

wersja_użytkownika

Jak wcześniej wspomniano, prawdopodobnie mówisz o wersji_użytkownika . Pierwszą rzeczą, na którą należy zwrócić uwagę, jest to, że jest to zmienna/pole kontrolowane przez użytkownika udostępniane do użytku niestandardowego. SQlite nie używa ani nie zmienia user_version ale pozwala na jego zmianę i używanie.

Ponadto menedżery SQLite (takie jak DB Browser, Navicat itp.) nie zmienią automatycznie numeru wersji. W związku z tym musiałbyś celowo zmienić wersję_użytkownika, aby była dostępna przed skopiowaniem pliku bazy danych do folderu zasobów (zauważ, że jeśli to zrobisz i używasz podklasy SQLiteOpenHelper że onUpgrade i onDowngrade mogą być wywoływane metody).

Jeśli wersja_użytkownika nie została specjalnie zmieniona, a do bazy danych uzyskano dostęp tylko za pomocą narzędzia SQLite Manager, jego wersja_użytkownika będzie wynosić 0. Jeśli plik bazy danych został otwarty przez skopiowanie pliku bazy danych z aplikacji na Androida, która wykorzystuje podklasę SQLiteOpenHelper, będzie miał user_version 1 lub więcej (w zależności od ostatniej wartości użytej jako czwarty parametr w constrcutorze SQLiteOpenHelper). Oczywiście, jeśli user_version zostanie zmieniona programowo, taka zmiana zostanie również odzwierciedlona, ​​jeśli plik zostanie skopiowany do narzędzia SQLlite Manager.

Przed skopiowaniem pliku nazwa_użytkownika byłaby zazwyczaj zmieniana w narzędziu SQlite Manager na odpowiednią wartość.

Możesz zmienić wersję_użytkownika używając SQL PRAGMA user_version = 5; Możesz pobrać user_version używając PRAGMA user_version lub SELECT * FROM pragma_user_version;

Jeśli potrzebujesz sprawdzić wersję przed otwarciem bazy danych, możesz odczytać 4 bajty pod offsetem 60 i przekonwertować 4 bajty na liczbę całkowitą, aby sprawdzić user_version z inną wartością. W przeciwnym razie prawdopodobnie będziesz musiał skopiować plik, prawdopodobnie używając innej nazwy, z folderu zasobów, otworzyć go jako SQLiteDatabase i pobrać wersję_użytkownika za pomocą powyższego SQL, a następnie porównać go z inną wartością, zamykając plik bazy danych. Usunięcie pliku, jeśli nie jest potrzebne, w przeciwnym razie usunięcie poprzedniego pliku bazy danych, a następnie zmiana nazwy skopiowanego pliku.

Przykład

Poniżej znajduje się działający przykład (zauważ, że rzadko używam Kotlina i został on przekonwertowany przy użyciu AS studio z javy).

To używa klasy, a mianowicie SQLAssetVersionCheck który wyodrębnia numer wersji z pliku, zamiast otwierać plik jako SQLiteDatabase.

SQLAssetVersionCheck.kt :-

class SQLAssetVersionCheck
/**
 * Full SQLAssetVersionCheck Constructor - sub directories can be specified
 * @param context           Assets are part of package so use the context to get the asset file
 * @param dbName            The database name (i.e. the file name)
 * @param subDirectories    The sub-directories as per the heirarchial order
 * @param dbVersion         The database version to check against
 */
(context: Context, val databaseName: String, subDirectories: Array<String>?, dbVersion: Int) {
    val assetPath: String
    var databaseVersion: Int = 0
        private set
    var result: Int = 0
        private set


    init {
        assetPath = applySubDirectories(databaseName, subDirectories)
        Log.d("SQLAVC", "Looking for Asset $assetPath")
        var stage = 0
        try {
            val `is` = context.assets.open(assetPath)
            stage++
            // Get the first 64 bytes of the header
            val v = ByteArray(64)
            `is`.read(v, 0, 64)
            // only interested in the 4 bytes from offset 60 so get them
            val v2 = ByteArray(4)
            for (i in 60..63) {
                v2[i - 60] = v[i]
            }
            stage++
            // Done with the InputStream so close it
            `is`.close()
            // Extarct the stored DBVersion
            databaseVersion = ByteBuffer.wrap(v2).int
            if (databaseVersion < dbVersion) {
                result = ASSETVERSIONLOW

            }
            if (databaseVersion > dbVersion) {
                result = ASSETVERSIONHIGH
            }
            if (databaseVersion == dbVersion) {
                result = ASSETVERSIONMATCH
            }

        } catch (e: IOException) {
            e.printStackTrace()
            when (stage) {
                0 -> result = ASSETNOTFOUND
                1 -> result = ASSETIOERROR
            }
        }

    }

    constructor(context: Context, dbName: String, dbVersion: Int) : this(context, dbName, null, dbVersion) {}

    private fun applySubDirectories(dbname: String, subDirectories: Array<String>?): String {
        val base = StringBuffer("")
        var firstdirectory = true
        if (subDirectories != null) {
            for (d in subDirectories) {
                if (!firstdirectory) {
                    base.append(File.separatorChar)
                }
                firstdirectory = false
                base.append(d)
            }
        }
        if (base.length > 0) {
            base.append(File.separatorChar)
        }
        base.append(dbname)
        return base.toString()
    }

    companion object {

        val ASSETNOTFOUND = -2
        val ASSETIOERROR = -3
        val ASSETVERSIONMATCH = 0
        val ASSETVERSIONHIGH = 1
        val ASSETVERSIONLOW = -1
    }
}

A oto Aktywność, która używa powyższej klasy dwukrotnie, aby spróbować sprawdzić wersję w testdb plik.

  • Pierwsze użycie nie powoduje znalezienia pliku bazy danych testdb jak szuka w aktywach folder (nie podkatalog baz danych).

  • Drugie użycie znajduje testdb plik jako podkatalog bazy danych jest określony (3. parametr pełnego konstruktora), znajdujący się w assets/databases/ folder, tj. assets/databases/testdb :-

Aktywność główna.kt :-

class MainActivity : AppCompatActivity() {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val db_version_to_check_against = 100

        var mAVC1 = SQLAssetVersionCheck(this, "testdb", 100)

        var result = ""
        when (mAVC1.result) {
            SQLAssetVersionCheck.ASSETIOERROR -> result = "IO ERROR detected - check the Log"
            SQLAssetVersionCheck.ASSETNOTFOUND -> result = "The Asset, for Database " + mAVC1.databaseName + " was not located at  " + mAVC1.assetPath
            SQLAssetVersionCheck.ASSETVERSIONHIGH -> result = "The Asset was located and the version number being " +
                    mAVC1.databaseVersion.toString() +
                    " was higher than the version to be checked which was " +
                    db_version_to_check_against.toString()
            SQLAssetVersionCheck.ASSETVERSIONLOW -> result = "The Asset was located and the version number being " +
                    mAVC1.databaseVersion.toString() +
                    " was lower than the version to be checked which was " +
                    db_version_to_check_against.toString()
            SQLAssetVersionCheck.ASSETVERSIONMATCH -> result = "The Asset version and the version to be check ed are the same."
        }
        Log.d("ASSETVERSIONCHECK", "The result of the version check was - $result")

        var mAVC2 = SQLAssetVersionCheck(this, "testdb", arrayOf("databases"), db_version_to_check_against)
        result = ""
        when (mAVC2.result) {
            SQLAssetVersionCheck.ASSETIOERROR -> result = "IO ERROR detected - check the Log"
            SQLAssetVersionCheck.ASSETNOTFOUND -> result = "The Asset, for Database " + mAVC2.databaseName + " was not located at  " + mAVC2.assetPath
            SQLAssetVersionCheck.ASSETVERSIONHIGH -> result = "The Asset was located and the version number being " +
                    mAVC2.databaseVersion.toString() +
                    " was higher than the version to be checked which was " +
                    db_version_to_check_against.toString()
            SQLAssetVersionCheck.ASSETVERSIONLOW -> result = "The Asset was located and the version number being " +
                    mAVC2.databaseVersion.toString() +
                    " was lower than the version to be checked which was " +
                    db_version_to_check_against.toString()
            SQLAssetVersionCheck.ASSETVERSIONMATCH -> result = "The Asset version and the version to be check ed are the same."
        }
        Log.d("ASSETVERSIONCHECK", "The result of the version check was - $result")
    }
}

Wynik (log):-

2019-02-19 13:11:34.473 19058-19058/com.example.so54741423assetdbversioning D/SQLAVC: Looking for Asset testdb
2019-02-19 13:11:34.473 19058-19058/com.example.so54741423assetdbversioning W/System.err: java.io.FileNotFoundException: testdb
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.content.res.AssetManager.nativeOpenAsset(Native Method)
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.content.res.AssetManager.open(AssetManager.java:744)
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.content.res.AssetManager.open(AssetManager.java:721)
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at com.example.so54741423assetdbversioning.SQLAssetVersionCheck.<init>(SQLAssetVersionCheck.kt:31)
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at com.example.so54741423assetdbversioning.SQLAssetVersionCheck.<init>(SQLAssetVersionCheck.kt:67)
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at com.example.so54741423assetdbversioning.MainActivity.onCreate(MainActivity.kt:17)
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.app.Activity.performCreate(Activity.java:7136)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.app.Activity.performCreate(Activity.java:7127)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:106)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.os.Looper.loop(Looper.java:193)
2019-02-19 13:11:34.476 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:6669)
2019-02-19 13:11:34.476 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
2019-02-19 13:11:34.476 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
2019-02-19 13:11:34.476 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
2019-02-19 13:11:34.476 19058-19058/com.example.so54741423assetdbversioning D/ASSETVERSIONCHECK: The result of the version check was - The Asset, for Database testdb was not located at  testdb




2019-02-19 13:11:34.476 19058-19058/com.example.so54741423assetdbversioning D/SQLAVC: Looking for Asset databases/testdb
2019-02-19 13:11:34.477 19058-19058/com.example.so54741423assetdbversioning D/ASSETVERSIONCHECK: The result of the version check was - The Asset was located and the version number being 5 was lower than the version to be checked which was 100
  • Pierwsza próba nie znajduje pliku (wyświetlany jest wyjątek, który został wyłapany) i wyświetla wiersz Wynikiem sprawdzania wersji był - Zasób bazy danych testdb nie znajdował się w testdb do wyświetlenia.

  • Druga próba działa i daje Wynik sprawdzania wersji był następujący:Zasób został zlokalizowany, a numer wersji równy 5 był niższy niż wersja do sprawdzenia, która wynosiła 100

  • Dodano odstęp pustych linii, aby oddzielić drugą próbę od pierwszej.

Dodatkowe

Po użyciu narzędzia SQLite Manager (Navicat) i użyciu :-

PRAGMA user_version = 101;

Następnie kopiowanie pliku (po zamknięciu połączenia w Navicat) do folderu asset (więc mam dwa pliki testdb) to wynik to :-

2019-02-19 13:50:09.874 19253-19253/com.example.so54741423assetdbversioning D/SQLAVC: Looking for Asset testdb
2019-02-19 13:50:09.874 19253-19253/com.example.so54741423assetdbversioning D/ASSETVERSIONCHECK: The result of the version check was - The Asset was located and the version number being 101 was higher than the version to be checked which was 100
2019-02-19 13:50:09.874 19253-19253/com.example.so54741423assetdbversioning D/SQLAVC: Looking for Asset databases/testdb
2019-02-19 13:50:09.874 19253-19253/com.example.so54741423assetdbversioning D/ASSETVERSIONCHECK: The result of the version check was - The Asset was located and the version number being 5 was lower than the version to be checked which was 100
  • tj. nowy plik ma wersję user_version 101, więc pierwszy znajduje plik, drugi znajduje plik (user_version 5) jak poprzednio.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak wstawić dużą ilość danych do bazy danych sqlite w systemie Android

  2. Formatuj wyniki zapytania SQLite jako tabelę HTML

  3. przechowywanie danych w bazie danych za pomocą edycji tekstu i przycisku

  4. Jak usunąć określone wiersze w bazie danych SQLite?

  5. Nie można zaktualizować wiersza w Sqlite w systemie Android, ale nie zgłasza żadnego błędu