微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

当我在数据库浏览器上查看我的数据库时,为什么我的外键没有显示?我输入错了吗?

如何解决当我在数据库浏览器上查看我的数据库时,为什么我的外键没有显示?我输入错了吗?

    package com.example.database;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.sqliteDatabase;
import android.database.sqlite.sqliteOpenHelper;

public class DatabaseHelper extends sqliteOpenHelper {
    //making db and setting tables 1-6 names
    private static final int DATABASE_VERSION = 4;
    private static final String DATABASE_NAME = "contacts.db";
    private static final String TABLE1_NAME = "contacts";
    private static final String TABLE2_NAME = "Uinfo";
    private static final String TABLE3_NAME = "exercises";
    private static final String TABLE4_NAME = "calories";
    private static final String TABLE5_NAME = "calendar";
    // private static final String TABLE6_NAME = "settings";

    //these are for table 1
    private static final String COLUMN_ID = "id";
    private static final String COLUMN_EMAIL = "email";
    private static final String COLUMN_PASS = "pass";
    private static final String COLUMN_UNAME = "uname";
    private static final String COLUMN_NAME = "name";

    //for table 2
    private static final String COLUMN_ID2 = "id2";
    private static final String COLUMN_AGE = "age";
    private static final String COLUMN_WEIGHT = "weight";
    private static final String COLUMN_HEIGHT = "height";
    private static final String COLUMN_SEX = "sex";
    private static final String COLUMN_FK_CONTACTS_ID = "id";
    // private static final String COLUMN_FK_SETTINGS_ID = "id_6";
    private static final String COLUMN_FK_CALENDAR_ID = "id5";

 //creating tables
    private static final String TABLE_CREATE = "create table " + TABLE1_NAME +
            " (id integer primary key AUTOINCREMENT not null," +
            " name text not null," +
            " email text not null," +
            " pass text not null," +
            " uname text not null);";

    private static final String TABLE2_CREATE = "create table " + TABLE2_NAME +
            "(id2 integer primary key AUTOINCREMENT not null," +
            " age text not null," +
            " weight text not null," +
            " height text not null," +
            " sex text not null," +
            " FOREIGN KEY ("+ COLUMN_ID2 +") REFERENCES  "+TABLE1_NAME+"("+COLUMN_ID+")," +
            " FOREIGN KEY ("+ COLUMN_ID2 +") REFERENCES  "+TABLE5_NAME+"("+COLUMN_ID5+"));";
    //" FOREIGN KEY ("+ COLUMN_ID2 +") REFERENCES  "+TABLE6_NAME+"("+COLUMN_ID6+"));";

基本上外键在查看时不会出现在数据库中。 我试过加入

"id integer not null"

在第一个外键行之前,这使数据库停止向该表写入数据。我已经更新了数据库版本,看看这是否也会有所作为,但无济于事。 我叫错了吗?我可能只是错过了在外键进入的列中写入的正确方法。虽然我不确定它会如何以正确的方式插入。

解决方法

我认为您的问题是对 FOREIGN KEY .... 子句的作用的误解。

它不会创建用于存储外键的列。相反,它添加了一个约束(规则),表明正在创建的表中的列必须包含在 REFERENCES 之后指定的表(列)中的现有值。

这些陈述是正确的,实际上确实创建了外键约束;如将显示的那样。

考虑以下内容(通过使用您提供的 Android Studio 运行代码(加上代码以使其可用),从而创建数据库和所需的表)

  • 在创建 Uinfo 表(以及其他表)并从 TABLE2_CREATE 变量复制值时使用 DEBUG 停止,获得的值是:-
    • create table Uinfo(id2 integer primary key AUTOINCREMENT not null,age text not null,weight text not null,height text not null,sex text not null,FOREIGN KEY (id2) REFERENCES contacts(id),FOREIGN KEY (id2) REFERENCES calendar(id5));

将此值放入 SQLite 工具 (navicat) 中,然后运行以下 SQL:-

create table contacts (id integer primary key AUTOINCREMENT not null,name text not null,email text not null,pass text not null,uname text not null);
CREATE TABLE calendar(id5 INTEGER PRIMARY KEY,other TEXT);
create table Uinfo(id2 integer primary key AUTOINCREMENT not null,FOREIGN KEY (id2) REFERENCES  calendar(id5));


SELECT * FROM Uinfo;
INSERT INTO Uinfo VALUES(null,10,5.6,70,'Female');

结果:-

enter image description here

显然 INSERT 没有插入数据。查看日志显示:-

create table Uinfo(id2 integer primary key AUTOINCREMENT not null,FOREIGN KEY (id2) REFERENCES  calendar(id5))
> OK
> Time: 0.074s


SELECT * FROM Uinfo
> OK
> Time: 0s


INSERT INTO Uinfo VALUES(null,'Female')
> FOREIGN KEY constraint failed
> Time: 0s 

所以添加了外键约束。

在测试 Android 应用程序中执行等效操作是使用以下代码进行的:-

public class MainActivity extends AppCompatActivity {
    DatabaseHelper DBHelper;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DBHelper = new DatabaseHelper(this);
        SQLiteDatabase db = DBHelper.getWritableDatabase();
        db.execSQL("INSERT INTO Uinfo VALUES(null,'Female')");
        Log.d("DBINFO","After the first insert");
        db.execSQL("PRAGMA foreign_keys = true");
        db.execSQL("INSERT INTO Uinfo VALUES(null,"After the second insert");
    }
}

结果:-

2021-04-24 15:34:27.954 5644-5644/a.a.so67224090javafknotshowing D/DBINFO: After the first insert
2021-04-24 15:34:27.955 5644-5644/a.a.so67224090javafknotshowing D/AndroidRuntime: Shutting down VM
2021-04-24 15:34:27.957 5644-5644/a.a.so67224090javafknotshowing E/AndroidRuntime: FATAL EXCEPTION: main
    Process: a.a.so67224090javafknotshowing,PID: 5644
    java.lang.RuntimeException: Unable to start activity ComponentInfo{a.a.so67224090javafknotshowing/a.a.so67224090javafknotshowing.MainActivity}: android.database.sqlite.SQLiteConstraintException: FOREIGN KEY constraint failed (code 787 SQLITE_CONSTRAINT_FOREIGNKEY)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
     Caused by: android.database.sqlite.SQLiteConstraintException: FOREIGN KEY constraint failed (code 787 SQLITE_CONSTRAINT_FOREIGNKEY)
        at android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount(Native Method)
        at android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:748)
        at android.database.sqlite.SQLiteSession.executeForChangedRowCount(SQLiteSession.java:754)
        at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:64)
        at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1770)
        at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1698)
        at a.a.so67224090javafknotshowing.MainActivity.onCreate(MainActivity.java:20)
        at android.app.Activity.performCreate(Activity.java:7136)
        at android.app.Activity.performCreate(Activity.java:7127)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:193) 
        at android.app.ActivityThread.main(ActivityThread.java:6669) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 

应用程序因异常而崩溃,异常消息为 FOREIGN KEY constraint failed (code 787 SQLITE_CONSTRAINT_FOREIGNKEY)

但是日志还包含D/DBINFO: After the first insert

即第一个 INSERT 没有导致异常,它是 THE IMPORTANT db.execSQL("PRAGMA foreign_keys = true");

之后的第二个

如果没有这一行(或等效行),那么 Android 上的默认设置(与默认 SQLite 一样)是关闭外键处理。以上打开外键处理。

因此,如果您的问题更多的是外键什么都不做,那么这可能是原因。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。