FOREIGN KEY约束失败(代码787)[NO ANDROID ROOM]

问题描述 投票:2回答:1

我在Android Studio上有一个Android项目,该项目的数据库有3个表,一个有两个FK。我想我看到了所有带有解决方案的代码,以及对我有用的任何工作。

这是错误:

E/SQLiteDatabase: Error inserting idTipoFK=TYP-20f4c0ba-8aa7-47c9-9cd8-19861f93f2dd idUserFK=US-c8a20dae-5492-4243-9560-aaf458f3f2d5 adjuntoImg=imagen titulo=titulo idEntrada=ENT-13a62bd7-28ef-46f6-b9b3-b534a0c813ae texto=texto fecha=09-12-2019.12:27:01 adjuntoAudio=audio
android.database.sqlite.SQLiteConstraintException: FOREIGN KEY constraint failed (code 787)
    at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
    at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:782)
    at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
    at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
    at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1474)
    at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1343)
    at dam.proyecto.nasciturus.Database.OperacionesDataBase.insertarEntry(OperacionesDataBase.java:102)
    at dam.proyecto.nasciturus.Actividades.ListarActivity$4.onClick(ListarActivity.java:116)
    at android.view.View.performClick(View.java:5637)
    at android.view.View$PerformClick.run(View.java:22429)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6119)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

确定,我的数据库:

public class DataBase extends SQLiteOpenHelper
{
    //VARIABLES DE CONEXION
      private static final String BASE_DATOS = "nascitur.db";
      private static final int VERSION_ACTUAL = 4;
      private Context contexto;

    //METODOS PARA CONECTAR Y CERRAR A LA BBDD



    public DataBase(Context contexto)
    {
        super(contexto, BASE_DATOS, null, VERSION_ACTUAL);
        this.contexto = contexto;
    }

    @Override
    public void onOpen(SQLiteDatabase db)
    {
        super.onOpen(db);
        if(!db.isReadOnly())
        {
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
            {
                db.setForeignKeyConstraintsEnabled(true);
            }
            else
            {
                db.execSQL("PRAGMA foreign_keys=ON");
            }
        }
    }
    public void onCreate(SQLiteDatabase db)
    {

        db.execSQL("CREATE TABLE "+ConstantesInterfaces.UserID.TABLA_USER+"("+BaseColumns._ID+" text primary key autoincrement,"
                +ConstantesInterfaces.UserID.ID+" text not null unique, "+ConstantesInterfaces.UserID.USUARIO+" text not null, "+ConstantesInterfaces.UserID.PASSWORD+" text not null)");
        db.execSQL("CREATE TABLE "+ConstantesInterfaces.TypeID.TABLA_TYPE+" ("+BaseColumns._ID+" text primary key autoincrement,"
                +ConstantesInterfaces.TypeID.ID+" text not null unique, "+ConstantesInterfaces.TypeID.TIPO+" text not null)");
        db.execSQL("CREATE TABLE "+ConstantesInterfaces.EntradasID.TABLA_ENTRY+" ("+BaseColumns._ID+" text primary key autoincrement,"+ConstantesInterfaces.EntradasID.ID+" text not null unique, "
                +ConstantesInterfaces.EntradasID.FECHA+" date not null, "+ConstantesInterfaces.EntradasID.TITULO+" text, "+ConstantesInterfaces.EntradasID.TEXTO+" text, "
                +ConstantesInterfaces.EntradasID.ADJUNTOIMG+" text,"+ConstantesInterfaces.EntradasID.ADJUNTOAUDIO+" text,"
                +ConstantesInterfaces.EntradasID.ID_USER+" text not null, "+ConstantesInterfaces.EntradasID.ID_TIPO+" text not null, FOREIGN KEY("
                +ConstantesInterfaces.EntradasID.ID_USER+") REFERENCES "+ConstantesInterfaces.UserID.TABLA_USER+
                " ("+ConstantesInterfaces.UserID.ID+") ON DELETE CASCADE, FOREIGN KEY("+ConstantesInterfaces.EntradasID.ID_TIPO+") REFERENCES "
                +ConstantesInterfaces.TypeID.TABLA_TYPE+" ("+ConstantesInterfaces.TypeID.ID+") ON DELETE CASCADE)");

    }
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
    {
        db.execSQL("DROP TABLE IF EXISTS "+ ConstantesInterfaces.UserID.TABLA_USER);
        db.execSQL("DROP TABLE IF EXISTS "+ ConstantesInterfaces.TypeID.TABLA_TYPE);
        db.execSQL("DROP TABLE IF EXISTS "+ ConstantesInterfaces.EntradasID.TABLA_ENTRY);
        onCreate(db);
    }
}

和插入方法:

public void insertarEntry(Entry entrada) {
        SQLiteDatabase db = baseDatos.getWritableDatabase();

        // Generar Pk
        String idEntrada = ConstantesInterfaces.EntradasID.generarIdEntrada();

        ContentValues valores = new ContentValues();
        valores.put(ConstantesInterfaces.EntradasID.ID, idEntrada);
        valores.put(ConstantesInterfaces.EntradasID.FECHA, entrada.fecha);
        valores.put(ConstantesInterfaces.EntradasID.TITULO, entrada.titulo);
        valores.put(ConstantesInterfaces.EntradasID.TEXTO, entrada.texto);
        valores.put(ConstantesInterfaces.EntradasID.ADJUNTOIMG, entrada.adjuntoImg);
        valores.put(ConstantesInterfaces.EntradasID.ADJUNTOAUDIO, entrada.adjuntoAudio);
        valores.put(ConstantesInterfaces.EntradasID.ID_USER, entrada.idUsuario);
        valores.put(ConstantesInterfaces.EntradasID.ID_TIPO, entrada.idTipo);

        // Insertar entrada
        db.insert(ConstantesInterfaces.EntradasID.TABLA_ENTRY, null, valores);

    }

最后,这是我作为参数发送给方法的对象:

Entry entrada = new Entry(ConstantesInterfaces.EntradasID.generarIdEntrada(),fecha, "titulo","texto",adjuntoImg, "audio"  ,usuario , tipo);
OperacionesDataBase db = OperacionesDataBase.obtenerInstancia(getApplicationContext());
db.insertarEntry(entrada);
android android-studio android-sqlite sqliteopenhelper android-database
1个回答
0
投票

通过使用FORIEGN KEYS定义一列或多列,您正在定义一条规则(约束),该规则说该列只能包含一个或多个值,这些值或为父表的一个或多个列中的一个或多个值。 >

正在使用:-

...... FOREIGN KEY("
                +ConstantesInterfaces.EntradasID.ID_USER+") REFERENCES "+ConstantesInterfaces.UserID.TABLA_USER+
                " ("+ConstantesInterfaces.UserID.ID+") ON DELETE CASCADE, FOREIGN KEY("+ConstantesInterfaces.EntradasID.ID_TIPO+") REFERENCES "
                +ConstantesInterfaces.TypeID.TABLA_TYPE+" ("+ConstantesInterfaces.TypeID.ID+") ON DELETE CASCADE)");

您在说

  • a)根据ConstantesInterfaces.EntradasID.ID_USER的列具有一个规则,该规则规定ConstantesInterfaces.EntradasID.ID_USER列的值[[MUST

    是任何行的ConstantesInterfaces.UserID.ID列中存在的值ConstantesInterfaces.UserID.TABLA_USER表的
  • b)根据ConstantesInterfaces.EntradasID.ID_TIPO的列具有一个规则,该规则规定ConstantesInterfaces.EntradasID.ID_TIPO列的值[[MUST
  • 是任何以下项的ConstantesInterfaces.TypeID.ID列中存在的值ConstantesInterfaces.TypeID.TABLA_TYPE表的行。

    如果未遵守上述规则,则结果将为

    FOREIGN KEY约束失败

因此,您需要在父表中插入行,以便可以引用它们<< BEFORE插入到ConstantesInterfaces.EntradasID.TABLA_ENTRY表中。ConstantesInterfaces.UserID.TABLA_USER表中的ConstantesInterfaces.UserID.ID列中必须有一个值为

US-c8a20dae-5492-4243-9560-aaf458f3f2d5

的行

AND

ConstantesInterfaces.TypeID.TABLA_TYPE表中需要有一行,其ConstantesInterfaces.TypeID.TIPO列中的值<< [TYP-20f4c0ba-8aa7-47c9-9cd8-19861f93f2dd。

注意

您提供的代码似乎存在严重问题。所有三个表定义都有/使用:-

text primary key autoincrement

这是无效的SQL,因为您可以

ONLY将

AUTOINCREMENT

integer primary key
一起使用。使用text primary key autoincrement将导致错误。

示例/测试

确定一个包括所有三个表的插入方法的DataBase.java:-public long insertEntry(String id,String fecha,String title, String to, String image,String audio, String userIdReference, String typeIdReference) { long rv = -1; try { ContentValues cv = new ContentValues(); cv.put(ConstantesInterfaces.EntradasID.ID, id); cv.put(ConstantesInterfaces.EntradasID.FECHA, fecha); cv.put(ConstantesInterfaces.EntradasID.TITULO, title); cv.put(ConstantesInterfaces.EntradasID.TEXTO, to); cv.put(ConstantesInterfaces.EntradasID.ADJUNTOIMG, image); cv.put(ConstantesInterfaces.EntradasID.ADJUNTOAUDIO, audio); cv.put(ConstantesInterfaces.EntradasID.ID_USER, userIdReference); cv.put(ConstantesInterfaces.EntradasID.ID_TIPO, typeIdReference); rv = this.getWritableDatabase().insertOrThrow(ConstantesInterfaces.EntradasID.TABLA_ENTRY, null, cv); } catch (SQLiteException e) { e.printStackTrace(); } return rv; } public long insertType(String id, String type) { ContentValues cv = new ContentValues(); cv.put(ConstantesInterfaces.TypeID.ID,id); cv.put(ConstantesInterfaces.TypeID.TIPO,type); return this.getWritableDatabase().insert(ConstantesInterfaces.TypeID.TABLA_TYPE,null,cv); } public long insertUser(String id, String userName, String password) { ContentValues cv = new ContentValues(); cv.put(ConstantesInterfaces.UserID.ID,id); cv.put(ConstantesInterfaces.UserID.USUARIO,userName); cv.put(ConstantesInterfaces.UserID.PASSWORD,password); return this.getWritableDatabase().insert(ConstantesInterfaces.UserID.TABLA_USER,null,cv); }

请注意insertEntry如何使用

insertOrThrow,以便可以捕获错误并可以尝试随后的attemtpos。

并在活动中附加以下代码:-
    public class MainActivity extends AppCompatActivity { DataBase mDB; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String userid = "US-c8a20dae-5492-4243-9560-aaf458f3f2d5"; String typeid = "TYP-20f4c0ba-8aa7-47c9-9cd8-19861f93f2dd"; Log.d("FKTESTINFO","Stage 1 - Instantiating database instance"); mDB = new DataBase(this); //DatabaseUtils.dumpCursor(mDB.getWritableDatabase().query("sqlite_master",null,null,null,null,null,null)); Log.d("FKTESTINFO","Stage 2 - INSERT attempt 1"); mDB.insertEntry("w","x","y","x","img","audio",userid,typeid); // FAIL as Type nor User exist Log.d("FKTESTINFO","Stage 3 - INSERT attempt 2"); mDB.insertUser(userid,"Fred","password"); mDB.insertEntry("w","x","y","x","img","audio",userid,typeid); // FAIL as Type does not exist Log.d("FKTESTINFO","Stage 4 - INSERT attempt 3"); mDB.insertType(typeid,"My Type"); mDB.insertEntry("w","x","y","x","img","audio",userid,typeid); // FAIL as Type does not exist Log.d("FKTESTINFO","Stage 5 - All Completed"); } }
  • 结果表明,直到同时添加了引用的类型和引用的用户之后,条目插入才起作用:-2019-12-10 13:42:47.547 D/FKTESTINFO: Stage 1 - Instantiating database instance 2019-12-10 13:42:47.547 D/FKTESTINFO: Stage 2 - INSERT attempt 1 2019-12-10 13:42:47.567 W/System.err: android.database.sqlite.SQLiteConstraintException: FOREIGN KEY constraint failed (code 787 SQLITE_CONSTRAINT_FOREIGNKEY) 2019-12-10 13:42:47.567 W/System.err: at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method) 2019-12-10 13:42:47.567 W/System.err: at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:879) 2019-12-10 13:42:47.567 W/System.err: at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:790) 2019-12-10 13:42:47.567 W/System.err: at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:88) 2019-12-10 13:42:47.567 W/System.err: at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1599) 2019-12-10 13:42:47.567 W/System.err: at android.database.sqlite.SQLiteDatabase.insertOrThrow(SQLiteDatabase.java:1494) 2019-12-10 13:42:47.567 W/System.err: at a.so59250186foreignkeys.DataBase.insertEntry(DataBase.java:135) 2019-12-10 13:42:47.567 W/System.err: at a.so59250186foreignkeys.MainActivity.onCreate(MainActivity.java:26) 2019-12-10 13:42:47.567 W/System.err: at android.app.Activity.performCreate(Activity.java:7802) 2019-12-10 13:42:47.567 W/System.err: at android.app.Activity.performCreate(Activity.java:7791) 2019-12-10 13:42:47.567 W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299) 2019-12-10 13:42:47.567 W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245) 2019-12-10 13:42:47.568 W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409) 2019-12-10 13:42:47.568 W/System.err: at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 2019-12-10 13:42:47.568 W/System.err: at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 2019-12-10 13:42:47.568 W/System.err: at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 2019-12-10 13:42:47.568 W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) 2019-12-10 13:42:47.568 W/System.err: at android.os.Handler.dispatchMessage(Handler.java:107) 2019-12-10 13:42:47.568 W/System.err: at android.os.Looper.loop(Looper.java:214) 2019-12-10 13:42:47.568 W/System.err: at android.app.ActivityThread.main(ActivityThread.java:7356) 2019-12-10 13:42:47.568 W/System.err: at java.lang.reflect.Method.invoke(Native Method) 2019-12-10 13:42:47.568 W/System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 2019-12-10 13:42:47.568 W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 2019-12-10 13:42:47.568 D/FKTESTINFO: Stage 3 - INSERT attempt 2 2019-12-10 13:42:47.572 W/System.err: android.database.sqlite.SQLiteConstraintException: FOREIGN KEY constraint failed (code 787 SQLITE_CONSTRAINT_FOREIGNKEY) 2019-12-10 13:42:47.572 W/System.err: at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method) 2019-12-10 13:42:47.572 W/System.err: at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:879) 2019-12-10 13:42:47.572 W/System.err: at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:790) 2019-12-10 13:42:47.572 W/System.err: at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:88) 2019-12-10 13:42:47.572 W/System.err: at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1599) 2019-12-10 13:42:47.572 W/System.err: at android.database.sqlite.SQLiteDatabase.insertOrThrow(SQLiteDatabase.java:1494) 2019-12-10 13:42:47.573 W/System.err: at a.so59250186foreignkeys.DataBase.insertEntry(DataBase.java:135) 2019-12-10 13:42:47.573 W/System.err: at a.so59250186foreignkeys.MainActivity.onCreate(MainActivity.java:30) 2019-12-10 13:42:47.573 W/System.err: at android.app.Activity.performCreate(Activity.java:7802) 2019-12-10 13:42:47.573 W/System.err: at android.app.Activity.performCreate(Activity.java:7791) 2019-12-10 13:42:47.573 W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299) 2019-12-10 13:42:47.573 W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245) 2019-12-10 13:42:47.573 W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409) 2019-12-10 13:42:47.573 W/System.err: at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 2019-12-10 13:42:47.573 W/System.err: at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 2019-12-10 13:42:47.573 W/System.err: at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 2019-12-10 13:42:47.573 W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) 2019-12-10 13:42:47.574 W/System.err: at android.os.Handler.dispatchMessage(Handler.java:107) 2019-12-10 13:42:47.574 W/System.err: at android.os.Looper.loop(Looper.java:214) 2019-12-10 13:42:47.574 W/System.err: at android.app.ActivityThread.main(ActivityThread.java:7356) 2019-12-10 13:42:47.574 W/System.err: at java.lang.reflect.Method.invoke(Native Method) 2019-12-10 13:42:47.574 W/System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 2019-12-10 13:42:47.574 W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 2019-12-10 13:42:47.574 D/FKTESTINFO: Stage 4 - INSERT attempt 3 2019-12-10 13:42:47.585 D/FKTESTINFO: Stage 5 - All Completed
© www.soinside.com 2019 - 2024. All rights reserved.