簡體   English   中英

我想創建一個 SQLite 數據庫,如圖像中所示,我該怎么做? 我只想知道如何創建鏈接列以鏈接數據庫?

[英]I want to create a SQLite database like in the images how do I do it? I just want to know how to I create the link column so as to link databases?

數據庫 1

數據庫 2

我想知道如何將一個數據庫鏈接到另一個數據庫。 例如,days 表中的 Apps 列應打開具有以下日期的 Apps 表的一個實例。

您可以打開其中一個數據庫,然后ATTACH另一個數據庫。

將所有表都放在一個數據庫中會更簡單。 擁有一個包含所有表的數據庫將允許您通過利用外鍵約束(即鏈接確實鏈接)來強制引用完整性。

利用 SQLiteOpenHelper 子類附加的示例

以下是通過單個數據庫助手(SQliteOpenHelper 的子類)附加第二個數據庫的示例,這兩個數據庫都基於您的模式。

  • 與主數據庫的 SQLiteOpenHelper 一樣,如果第二個數據庫不存在,它將與表一起創建。

數據庫助手

class DatabaseHelper extends SQLiteOpenHelper {

    public static final String DBNAME = "database1";
    public static final int DBVERSION = 1;
    public static final String OTHER_DBNAME = "database2";
    public static final String ATTACH_SCHEMA = "a1";

    public static final String TB_DAYTABLE = "daytable";
    public static final String COL_DATE_DAYTABLE = "date";
    public static final String COL_TOTALTIME_DAYTABLE = "totaltime";
    public static final String COl_UNLOCKCOUNTS_DAYTABLE = "unlockcounts";
    public static final String COL_APPS_DAYTABLE = "apps";

    public static final String TB_APPS = "apps";
    public static final String COl_NAME_APPS = "name";
    public static final String COl_TOTALTIME_APPS = "totaltime";
    public static final String COl_COUNTS_APPS = "counts";
    public static final String COL_TIMELINE_APPS = "timeline";

    public static final String TB_TIMELINE = "timeline";
    public static final String COL_STARTTIME_TIMELINE = "starttime";
    public static final String COL_ENDTIME_TIMELINE = "endtime";
    public static final String COL_TOTALTIME_TIMELINE = "totaltime";


    private static volatile DatabaseHelper instance;
    private SQLiteDatabase db;

    private DatabaseHelper(@Nullable Context context) {
        super(context, DBNAME, null, DBVERSION);
        db = this.getWritableDatabase();
        db.execSQL("ATTACH DATABASE '" + context.getDatabasePath(OTHER_DBNAME) + "' AS " + ATTACH_SCHEMA);
        Cursor csr = db.query(ATTACH_SCHEMA + ".sqlite_master",new String[]{"name"},"name=?",new String[]{TB_TIMELINE},null,null,null);
        if (!csr.moveToFirst()) {
            createAttachedTables(db);
        }
    }

    public static DatabaseHelper getInstance(Context context) {
        if (instance == null) {
            instance = new DatabaseHelper(context);
        }
        return instance;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE IF NOT EXISTS " + TB_DAYTABLE + " (" +
                COL_DATE_DAYTABLE + " TEXT " +
                "," + COL_TOTALTIME_DAYTABLE + " INTEGER " +
                "," + COl_UNLOCKCOUNTS_DAYTABLE + " INTEGER " +
                "," + COL_APPS_DAYTABLE + " INTEGER " +
                ")" );
        db.execSQL("CREATE TABLE IF NOT EXISTS " + TB_APPS + " (" +
                COl_NAME_APPS + " TEXT " +
                "," + COl_TOTALTIME_APPS + " INTEGER " +
                "," + COl_COUNTS_APPS + " INTEGER " +
                "," + COL_TIMELINE_APPS + " TEXT " +
                ")");
    }

    private void createAttachedTables(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE IF NOT EXISTS " + ATTACH_SCHEMA + "." + TB_TIMELINE + "(" +
                COL_STARTTIME_TIMELINE + " TEXT " +
                "," + COL_ENDTIME_TIMELINE + " TEXT " +
                "," + COL_TOTALTIME_TIMELINE + " INTEGER " +
                ")");
        db.execSQL("CREATE TABLE IF NOT EXISTS " + ATTACH_SCHEMA + "." + TB_APPS + "(" +
                COl_NAME_APPS + " TEXT " +
                "," + COl_TOTALTIME_APPS + " INTEGER " +
                "," + COl_COUNTS_APPS + " INTEGER " +
                "," + COL_TIMELINE_APPS + " TEXT " +
                ")");
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }
}

Helper 已在 Activity (MainActivity) 中使用以下內容進行了測試(附加第二個數據庫並創建表):-

public class MainActivity extends AppCompatActivity {

    private DatabaseHelper db;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        db = DatabaseHelper.getInstance(this);
    }
}

結果

在 Android Studio 的數據庫檢查器中打開數據庫並從兩個模式(即各自的 sqlite_master 表)中提取數據,然后可以看到以下內容:-

在此處輸入圖像描述

即附加了 2 個數據庫,並且所有 4 個表都存在。

使用 database_list PRAGMA 顯示:-

在此處輸入圖像描述

即再次兩個數據庫


額外的

考慮到您的問題似乎是,您想要存儲應用程序使用數據。 我相信兩張桌子就足夠了。

也就是說,APPS 表似乎是重復的,因此不需要。 其次,統計解鎖計數、總時間等可以通過僅存儲鏈接到相應應用程序的開始和結束時間來計算。

因此,可以使用類似於以下內容的模式來確定值:-

在此處輸入圖像描述

  • 其中紅線顯示從使用情況到相應應用程序的鏈接。

現在假設應用表包含:-

在此處輸入圖像描述

使用表包含:-

在此處輸入圖像描述

然后是一個查詢,例如:-

SELECT 
    date(usage.startdatetime) AS date, 
    app.appname, count(*) AS unlocks, 
    time(sum(strftime('%s',usage.enddatetime)  -  strftime('%s',usage.startdatetime) ),'unixepoch') AS elapsedtime 
FROM app JOIN usage ON app._id = usage.applink 
GROUP BY date(usage.startdatetime),app._id 
ORDER BY date(usage.startdatetime)  ASC,appname ASC

將返回以下結果:-

在此處輸入圖像描述

  • 如您所見,總時間和解鎖次數是即時計算的(即無需存儲這些值)。

示例 2 - Android 的 2 表解決方案:-

數據庫助手AltDBHelper :-

class AltDBHelper extends SQLiteOpenHelper {

    public static final String DBNAME = "appusage.db";
    public static final int DBVERSION = 1;

    private static SQLiteDatabase db;
    private static volatile AltDBHelper instance;


    private AltDBHelper(@Nullable Context context) {
        super(context, DBNAME, null, DBVERSION);
        db = this.getWritableDatabase();
    }

    public static AltDBHelper getInstance(Context context) {
        if (instance == null) {
            instance = new AltDBHelper(context);
        }
        return instance;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(AppTable.getCreateSQL());
        db.execSQL(UsageTable.getCreateSQL());
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int i, int i1) {

    }

    /*
        Insert an App into the database
     */
    public long insert(String appName) {
        ContentValues cv = new ContentValues();
        cv.put(AppTable.APPNAME,appName);
        return AltDBHelper.db.insert(AppTable.TBNAME,null,cv);
    }

    /*
        Query to return the Date, App, Number of unlocks and Sum of the Elapsed times (total time)
        by each day by each App
    *   Based upon the query :-
    * SELECT
    *   app.appname,
    *   date(usage.startdatetime),
    *   time(sum(strftime('%s',enddatetime) - strftime('%s',startdatetime)),'unixepoch')
    * FROM usage JOIN app ON app._id = usage.applink
    * GROUP BY date(startdatetime),app._id
    * ORDER BY date(startdatetime),app.appName
    *
     */
    public static final String DATE = "date";
    private static final String DATE_COL_EXPRESSION = "date(" + UsageTable.STARTDATETIME_QUALIFIED + ") AS " + DATE;
    
    public static final String APPUNLOCKS = "unlocks";
    private static final String APPUNLOCKS_COL_EXPRESSION = "count(*) AS " + APPUNLOCKS;
    
    public static final String ELAPSEDTIME = "elapsedtime";
    private static final String ELAPSEDTIME_EXPRESSION =
            "time(" +
                "sum(" +
                        "strftime('%s'," + UsageTable.ENDDATETIME_QUALIFIED + ") " +
                        " - " +
                        " strftime('%s'," + UsageTable.STARTDATETIME_QUALIFIED + ") " +
                    ")" +
                ",'unixepoch'" +
            ")" +
        " AS " + ELAPSEDTIME;

    private static final String APPSTATS_TABLE =
            AppTable.TBNAME + " JOIN " + UsageTable.TBNAME +
                    " ON " +
                    AppTable.APPID_QUALIFIED + " = " +
                    UsageTable.APPLINK_QUALIFIED;


    private static final String DATEPART_GROUPBY = "date(" + UsageTable.STARTDATETIME_QUALIFIED + ")";
    private static final String APPPART_GROUPBY = AppTable.APPID_QUALIFIED;
    private static final String GROUPBY = DATEPART_GROUPBY + "," + APPPART_GROUPBY;
    public Cursor getAppDailyStatsAsCursor(Long id) {
        String whereClause = null;
        String[] whereArgs = null;
        if (id != null) {
            whereClause = AppTable.APPID_QUALIFIED + "=?";
            whereArgs = new String[]{String.valueOf(id)};
        }
        return AltDBHelper.db.query(
                APPSTATS_TABLE,
                new String[]{
                        DATE_COL_EXPRESSION,
                        AppTable.APPNAME_QUALIFIED,
                        APPUNLOCKS_COL_EXPRESSION,
                        ELAPSEDTIME_EXPRESSION
                },
                whereClause,
                whereArgs,
                GROUPBY,
                null,
                "date(" + UsageTable.STARTDATETIME_QUALIFIED + ") " + " ASC" + "," + AppTable.APPNAME + " ASC"
        );
    }

    /* The App Table name and column definitions */
    public static final class AppTable {
        public static final String TBNAME = "app";
        public static final String APPID = BaseColumns._ID;
        public static final String APPID_QUALIFIED = TBNAME + "." + APPID;
        public static final String APPID_UNIQUE = TBNAME+APPID;
        public static final String APPNAME = "appname";
        public static final String APPNAME_QUALIFIED = TBNAME + "." + APPNAME;

        public static String getCreateSQL() {
            return "CREATE TABLE IF NOT EXISTS " + TBNAME + "(" +
                    APPID + " INTEGER PRIMARY KEY " +
                    "," + APPNAME + " TEXT UNIQUE " +
                    ")";
        }
    }

    /* The Usage table name and column definitions also method for inserting rows (alternative) */
    public static final class UsageTable {

        public static final String TBNAME = "usage";
        public static final String USAGEID = BaseColumns._ID;
        public static final String USAGEID_QUALIFIED = TBNAME + "." + USAGEID;
        public static final String USAGEID_UNIQUE = TBNAME + USAGEID;
        public static final String APPLINK = "applink";
        public static final String APPLINK_QUALIFIED = TBNAME + "." + APPLINK;
        public static final String STARTDATETIME = "startdatetime";
        public static final String STARTDATETIME_QUALIFIED = TBNAME + "." + STARTDATETIME;
        public static final String ENDDATETIME = "enddatetime";
        public static final String ENDDATETIME_QUALIFIED = TBNAME + "." + ENDDATETIME;

        public static String getCreateSQL() {
            return "CREATE TABLE IF NOT EXISTS " + TBNAME + "(" +
                    USAGEID + " INTEGER PRIMARY KEY" +
                    "," + APPLINK + " INTEGER REFERENCES " + AppTable.TBNAME + "(" + AppTable.APPID + ") ON DELETE CASCADE ON UPDATE CASCADE" +
                    "," + STARTDATETIME + " TEXT " +
                    "," + ENDDATETIME + " TEXT " +
                    ")";
        }

        public static long insert(long appId, String startDateTime, String endDateTime) {
            ContentValues cv = new ContentValues();
            cv.put(APPLINK,appId);
            cv.put(STARTDATETIME,startDateTime);
            cv.put(ENDDATETIME,endDateTime);
            return AltDBHelper.db.insert(TBNAME,null,cv);
        }
    }
}

在活動中使用上述內容, MainActivity產生與上述附加部分相同的結果:-

public class MainActivity extends AppCompatActivity {

    private DatabaseHelper db;
    private AltDBHelper altdb;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        db = DatabaseHelper.getInstance(this); /* The original answer  attaching a second database */

        /* using alternative with just 2 tables */
        altdb = AltDBHelper.getInstance(this); /* get an Instance of the DBHelper */

        /* Add data for App1 along with some usage data */
        long a1 = altdb.insert("App1");
        AltDBHelper.UsageTable.insert(a1,"2021-01-01 15:30:00","2021-01-01 16:00:00");
        AltDBHelper.UsageTable.insert(a1,"2021-01-01 17:21:34","2021-01-01 19:33:12");
        AltDBHelper.UsageTable.insert(a1,"2021-01-02 09:11:27","2021-01-02 09:15:28");
        AltDBHelper.UsageTable.insert(a1,"2021-01-03 00:00:00","2021-01-03 05:00:59");

        /* Likewise for App2 */
        long a2 = altdb.insert("App2");
        AltDBHelper.UsageTable.insert(a2,"2021-01-01 13:04:27","2021-01-01 13:06:07");
        AltDBHelper.UsageTable.insert(a2,"2021-01-03 12:51:51","2021-01-03 12:55:55");
        AltDBHelper.UsageTable.insert(a2,"2021-01-02 03:33:30","2021-01-02 03:33:35");
        AltDBHelper.UsageTable.insert(a2,"2021-01-02 01:01:01","2021-01-02 01:03:04");
        AltDBHelper.UsageTable.insert(a2,"2021-01-01 14:25:36","2021-01-01 15:26:37");

        /* Add just App3 with no usage data */
        long a3 = altdb.insert("App3");

        /* Get the Daily App Usage */
        Cursor csr = altdb.getAppDailyStatsAsCursor(null);
        DatabaseUtils.dumpCursor(csr); /* Dump the Cursor (just to show what the Cursor contains) */
        csr.close(); /* done with the Cursor so close it */
    }
}
  • 可以看出,顯示如何附加數據庫的原始代碼已被保留。

第一次運行上述程序時(並非設計為重新運行,因為它只是一個演示),Cursor 的轉儲如下:-

2021-05-30 18:29:23.739 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@9ba4107
2021-05-30 18:29:23.742 I/System.out: 0 {
2021-05-30 18:29:23.742 I/System.out:    date=2021-01-01
2021-05-30 18:29:23.743 I/System.out:    appname=App1
2021-05-30 18:29:23.743 I/System.out:    unlocks=2
2021-05-30 18:29:23.743 I/System.out:    elapsedtime=02:41:38
2021-05-30 18:29:23.744 I/System.out: }
2021-05-30 18:29:23.744 I/System.out: 1 {
2021-05-30 18:29:23.744 I/System.out:    date=2021-01-01
2021-05-30 18:29:23.744 I/System.out:    appname=App2
2021-05-30 18:29:23.745 I/System.out:    unlocks=2
2021-05-30 18:29:23.745 I/System.out:    elapsedtime=01:02:41
2021-05-30 18:29:23.745 I/System.out: }
2021-05-30 18:29:23.746 I/System.out: 2 {
2021-05-30 18:29:23.746 I/System.out:    date=2021-01-02
2021-05-30 18:29:23.746 I/System.out:    appname=App1
2021-05-30 18:29:23.747 I/System.out:    unlocks=1
2021-05-30 18:29:23.747 I/System.out:    elapsedtime=00:04:01
2021-05-30 18:29:23.747 I/System.out: }
2021-05-30 18:29:23.747 I/System.out: 3 {
2021-05-30 18:29:23.748 I/System.out:    date=2021-01-02
2021-05-30 18:29:23.748 I/System.out:    appname=App2
2021-05-30 18:29:23.749 I/System.out:    unlocks=2
2021-05-30 18:29:23.749 I/System.out:    elapsedtime=00:02:08
2021-05-30 18:29:23.749 I/System.out: }
2021-05-30 18:29:23.749 I/System.out: 4 {
2021-05-30 18:29:23.750 I/System.out:    date=2021-01-03
2021-05-30 18:29:23.750 I/System.out:    appname=App1
2021-05-30 18:29:23.750 I/System.out:    unlocks=1
2021-05-30 18:29:23.750 I/System.out:    elapsedtime=05:00:59
2021-05-30 18:29:23.751 I/System.out: }
2021-05-30 18:29:23.751 I/System.out: 5 {
2021-05-30 18:29:23.751 I/System.out:    date=2021-01-03
2021-05-30 18:29:23.751 I/System.out:    appname=App2
2021-05-30 18:29:23.751 I/System.out:    unlocks=1
2021-05-30 18:29:23.752 I/System.out:    elapsedtime=00:04:04
2021-05-30 18:29:23.752 I/System.out: }
2021-05-30 18:29:23.752 I/System.out: <<<<<

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM