【问题标题】:Inner delete query sqlite内部删除查询sqlite
【发布时间】:2016-03-08 07:42:00
【问题描述】:

我有一个数据库和事件表和时间表。我已将事件与时间表联系起来。事件具有时间表键列。现在我想删除一个时间表,当时间表被删除时,引用到相应时间表的事件应该被删除。这个怎么做?

我当前的删除查询是这个,它只删除表而不是事件。

    public void deleteTable(TimeTable timeTable) {
    SQLiteDatabase db = this.getWritableDatabase();
    db.delete(TABLE_TIME_TABLE, KEY_TIME_TABLE_ID + " = ?",
            new String[]{String.valueOf(timeTable.getId())});
    db.close();
}

数据库助手

     public class DatabaseHelper extends SQLiteOpenHelper {



    private static final String TABLE_TIME_TABLE = "timetables";
    private static final String KEY_TABLE_TITLE = "tabletitle";
    private static final String KEY_TIME_TABLE_ID = "timetableid";
    private static final String KEY_TABLE_COLOR = "tablecolor";
    private static final String KEY_STATUS = "status";


    private static final String TABLE_EVENTS = "event";
    private static final String KEY_ID = "id";
    private static final String KEY_TITLE = "title";
    private static final String KEY_START_HOURS = "starthours";
    private static final String KEY_START_MINS = "startmins";
    private static final String KEY_END_HOURS = "endhours";
    private static final String KEY_END_MINS = "endmins";

    private static final String KEY_FROM_DATE = "datefrom";
    private static final String KEY_TO_DATE = "dateto";
    private static final String KEY_LOCATION = "location";
    private static final String KEY_DAY_OF_WEEK = "dayofweek";
    private static final String KEY_NOTIFICATION_TIME = "notification";

    private static final String KEY_COLOR = "color";


    private Context context;

    public DatabaseHelper(Context context) {
        super(context, Constants.DATABASE_NAME, null, Constants.DATABASE_VERSION);
        //3rd argument to be passed is CursorFactory instance
        this.context = context;
    }

    // Creating Tables
    @Override
    public void onCreate(SQLiteDatabase db) {


        createTable(db);

    }

    public void createDatabase(){
        context.deleteDatabase(Constants.DATABASE_NAME + ".db");
        SQLiteDatabase db = this.getReadableDatabase();
    }


    public void createTable(SQLiteDatabase db){
        String CREATE_EVENTS_TABLE = "CREATE TABLE " + TABLE_EVENTS + "("
                + KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
                + KEY_TITLE + " TEXT,"
                + KEY_FROM_DATE + " DATE,"
                + KEY_TO_DATE + " DATE,"
                + KEY_DAY_OF_WEEK + " TEXT,"
                + KEY_LOCATION + " TEXT,"
                + KEY_NOTIFICATION_TIME + " DATE,"
                + KEY_TIME_TABLE_ID + " TEXT" + ")";

        db.execSQL(CREATE_EVENTS_TABLE);

        String CREATE_TIME_TABLE = "CREATE TABLE " + TABLE_TIME_TABLE + "("
                + KEY_TIME_TABLE_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
                + KEY_TABLE_TITLE + " TEXT,"
                + KEY_STATUS + " TEXT,"
                + KEY_TABLE_COLOR + " TEXT" + ")";

        db.execSQL(CREATE_TIME_TABLE);
    }

    // Upgrading database
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Drop older table if existed
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_EVENTS);
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_TIME_TABLE);
        context.deleteDatabase(Constants.DATABASE_NAME + ".db");

        createTable(db);


        // Create tables again
        //onCreate(db);
    }

}

我尝试了这个内部删除查询,但它不起作用:

  public void delete(TimeTable t,int id)
{
    SQLiteDatabase db = this.getWritableDatabase();

    db.execSQL(" DELETE FROM " + TABLE_TIME_TABLE + " WHERE " + KEY_TIME_TABLE_ID + " == " + id + " IN "

    + " ( " + " SELECT * FROM " + TABLE + " WHERE " + KEY_TIME_TABLE_ID + " == " + id + " ) ");

    db.close();

}

有人可以帮忙吗?

谢谢你..

【问题讨论】:

    标签: android database android-sqlite inner-join sql-delete


    【解决方案1】:

    有两种方法可以解决这个问题。 第一个选项:修改您的 deleteTable(TimeTable timeTable) 函数以删除父记录和子记录。 最好先使用父 ID 删除子记录(事件),然后使用相同 ID 删除父记录(时间表)。这是一个示例。

    public void deleteTable(TimeTable timeTable) {
        SQLiteDatabase db = this.getWritableDatabase();
        db.delete(TABLE_EVENTS, KEY_TIME_TABLE_ID + " = ?",//KEY_TIME_TABLE_ID is a foreign key 
                new String[]{String.valueOf(timeTable.getId())});
        db.delete(TABLE_TIME_TABLE, KEY_TIME_TABLE_ID + " = ?",
                new String[]{String.valueOf(timeTable.getId())});
        db.close();
    }
    

    您可能希望在事件表中将 KEY_TIME_TABLE_ID 命名为 FK_TIME_TABLE_ID 使代码更具可读性。

    第二个选项:在创建表时用delete cascade定义外键(您也可以更改现有表并添加它们)。

    String CREATE_EVENTS_TABLE = "CREATE TABLE " + TABLE_EVENTS + "("
            + KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
            + KEY_TITLE + " TEXT,"
            + KEY_FROM_DATE + " DATE,"
            + KEY_TO_DATE + " DATE,"
            + KEY_DAY_OF_WEEK + " TEXT,"
            + KEY_LOCATION + " TEXT,"
            + KEY_NOTIFICATION_TIME + " DATE,"
            + KEY_TIME_TABLE_ID + " TEXT,"
            + " FOREIGN KEY (" + KEY_ID + ") references "
            + TABLE_TIME_TABLE + "(" + KEY_TIME_TABLE_ID + ") ON DELETE CASCADE)";
    

    注意:sqlite 默认不支持外键,因此每次连接数据库时都运行以下查询。

    PRAGMA foreign_keys = ON
    

    这会启用外键

    【讨论】:

    • 首选第一个选项.. 效果很好。谢谢你.. @hyena
    【解决方案2】:

    删除引用您要删除的时间表条目的事件。类似的东西:

    DELETE FROM EVENTS WHERE TIMETABLE_ID=...
    

    【讨论】:

    • 我试过这个:public void deleteEvents(int id) { SQLiteDatabase db = this.getWritableDatabase(); db.execSQL("DELETE * FROM " + TABLE + " WHERE " + KEY_TIME_TABLE_ID + " == " + id ); }
    • 不工作...在 * @Ridcully 附近出现语法错误
    • 删除 * -- 它的 DELETE FROM ...,而不是 DELETE * FROM ...;还有,它的 = 而不是 ==。
    • 并且可以使用delete方法代替execSQL():db.delete(TABLE, KEY_TIME_TABLE_ID + "=?", new String[] {id})
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-08
    • 1970-01-01
    • 2017-08-05
    • 2020-08-01
    • 2011-06-23
    • 2015-03-25
    • 1970-01-01
    相关资源
    最近更新 更多