SQLite का उपयोग करके Android में विदेशी कुंजी की कमी? कैस्केड हटाएं


91

मेरे पास दो टेबल हैं: ट्रैक और वेपॉइंट, एक ट्रैक में कई वेपॉइंट हो सकते हैं, लेकिन एक वेपॉइंट केवल 1 ट्रैक को सौंपा गया है।

जिस तरह से पॉइंट टेबल में मेरे पास "trackidfk" नामक एक कॉलम है, जो एक ट्रैक बनाने के बाद track_ID को सम्मिलित करता है, हालांकि मैंने इस कॉलम पर विदेशी कुंजी बाधाओं को सेट नहीं किया है।

जब मैं एक ट्रैक हटाता हूं जिसे मैं असाइन किए गए वेपॉइंट को हटाना चाहता हूं, क्या यह संभव है? मैंने ट्रिगर का उपयोग करने के बारे में पढ़ा, लेकिन मुझे नहीं लगता कि वे Android में समर्थित हैं।

वेपॉइंट्स टेबल बनाने के लिए:

public void onCreate(SQLiteDatabase db) {
    db.execSQL( "CREATE TABLE " + TABLE_NAME 
                + " (" 
                + _ID         + " INTEGER PRIMARY KEY AUTOINCREMENT, " 
                + LONGITUDE   + " INTEGER," 
                + LATITUDE    + " INTEGER," 
                + TIME        + " INTEGER,"
                + TRACK_ID_FK + " INTEGER"
                + " );"
              );

    ...
}

जवाबों:


237

डिलीट कैस्केड के साथ विदेशी प्रमुख बाधाएं समर्थित हैं, लेकिन आपको उन्हें सक्षम करने की आवश्यकता है।
मैंने सिर्फ अपने SQLOpenHelper में निम्नलिखित जोड़ा है , जो कि चाल करने के लिए लगता है।

@Override
public void onOpen(SQLiteDatabase db) {
    super.onOpen(db);
    if (!db.isReadOnly()) {
        // Enable foreign key constraints
        db.execSQL("PRAGMA foreign_keys=ON;");
    }
}

मैंने अपना संदर्भ स्तंभ इस प्रकार घोषित किया।

mailbox_id INTEGER REFERENCES mailboxes ON DELETE CASCADE

59
जिसका अर्थ है कि यह केवल Android 2.2 Froyo जो SQLite 3.6.22 के बाद से काम करता है
Intrications

@RedPlanet - ऐसा इसलिए है क्योंकि इस बाधा को लागू करने का एकमात्र समय है जब डेटाबेस में कुछ लिखा जाता है। (आप इस बाधा को नहीं तोड़ सकते हैं यदि आप सभी डीबी से पढ़ते हैं) इसके अलावा, फिल, ऑनऑन विधि के बजाय, संभवतः ऑनकोनफिगर विधि में इसे करना बेहतर है। स्रोत: developer.android.com/reference/android/database/sqlite/...
Aneem

12
Google राइटिंग PRAGMAस्टेटमेंट्स की अनुशंसा करता है , onConfigure()लेकिन इसके लिए API स्तर 16 (Android 4.1) की आवश्यकता होती है, और तब तक आप बस कॉल कर सकते हैं setForeignKeyConstraintsEnabled
पैंग

एक भी में विदेशी कुंजी की कमी सक्षम करने पर विचार करना पड़ सकता है onCreate/ onDowngrade/ onUpgradeहै, जो पहले कर रहे हैं onOpenAndroid 4.1.1 में स्रोत कोड देखें ।
पैंग

1
@ नेट को कॉल सहित सुपर सही कार्यक्षमता सुनिश्चित करता है यदि एक मध्यवर्ती वर्ग को कार्यान्वित वर्ग और उसके माता-पिता के बीच पेश किया जाता है।
tbm


26

जैसा कि e.shishkin की पोस्ट एपीआई 16 से कहती है कि आपको SqLiteOpenHelper.onConfigure(SqLiteDatabase)विधि का उपयोग करते हुए विदेशी प्रमुख बाधाओं को सक्षम करना चाहिएdb.setForeignKeyConstraintsEnabled(boolean)

@Override
public void onConfigure(SQLiteDatabase db){
    db.setForeignKeyConstraintsEnabled(true);
}

10

अधिक पूर्ण उत्तर के साथ प्रश्न का उत्तर देने के लिए कभी पुराना न हों।

@Override public void onOpen(SQLiteDatabase db) {
    super.onOpen(db);
    if (!db.isReadOnly()) {
        setForeignKeyConstraintsEnabled(db);
    }
    mOpenHelperCallbacks.onOpen(mContext, db);
}

private void setForeignKeyConstraintsEnabled(SQLiteDatabase db) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
        setForeignKeyConstraintsEnabledPreJellyBean(db);
    } else {
        setForeignKeyConstraintsEnabledPostJellyBean(db);
    }
}

private void setForeignKeyConstraintsEnabledPreJellyBean(SQLiteDatabase db) {
    db.execSQL("PRAGMA foreign_keys=ON;");
}

@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void setForeignKeyConstraintsEnabledPostJellyBean(SQLiteDatabase db) {
    db.setForeignKeyConstraintsEnabled(true);
}

6

जो भी @ एफिल का उल्लेख किया है वह अच्छा है। लेकिन आप विदेशी को सेट करने के लिए डेटाबेस में उपलब्ध एक अन्य डिफ़ॉल्ट विधि का उपयोग कर सकते हैं। यह सेट है ForeignKeyConstraintsEnabled (सत्य)।

@Override
public void onOpen(SQLiteDatabase db) {
    super.onOpen(db);
    if (!db.isReadOnly()) {
        // Enable foreign key constraints
        db.execSQL("PRAGMA foreign_keys=ON;"); 
              //(OR)
        db.setForeignKeyConstraintsEnabled (true)
    }
}

डॉक्स के लिए SQLiteDatabase.setForeignKeyConstraintsEnabled देखें


3
आपके द्वारा पोस्ट किया गया दस्तावेज़ बताता है: A good time to call this method is right after calling openOrCreateDatabase(File, SQLiteDatabase.CursorFactory) or in the onConfigure(SQLiteDatabase) callback. इसलिए इसके बजाय onOpen, onConfigureसही जगह है।
पॉल Woitaschek

4

मुझे नहीं लगता कि SQLite बॉक्स से बाहर का समर्थन करता है। मैं अपने ऐप्स में क्या कर रहा हूं:

  1. लेन-देन बनाएँ
  2. विवरण डेटा हटाएं (आपके उदाहरण में वेपॉइंट)
  3. मास्टर डेटा हटाएं (आपके उदाहरण में ट्रैक)
  4. सफलता पर लेनदेन करें

इस तरह मुझे यकीन है कि या तो सभी डेटा हटा दिए गए हैं या कोई भी नहीं है।


लेकिन क्या आप एक विधि का उपयोग करके दोनों तालिकाओं से हटा रहे हैं?
jcrowson

हां, मैं एपीआई से नोट्स के नमूने के साथ बहुत अधिक गया। जब मैं हटाऊंगा कि आपके मामले में क्या ट्रैक होगा, तो मैं लेन-देन बनाता हूं, ट्रैक और वेपाइंट हटाता हूं और लेनदेन करता हूं। यह सब एक बार में है।
थोरस्टन डिटमार

4

ट्रिगर एंड्रॉइड द्वारा समर्थित हैं और उस प्रकार का कैस्केड डिलीट साइक्लाइट द्वारा समर्थित नहीं है। Android पर ट्रिगर का उपयोग करने का एक उदाहरण यहां पाया जा सकता है । यद्यपि थोरस्टेन के रूप में लेनदेन का उपयोग करना संभवतः ट्रिगर के रूप में आसान है।


3

एंड्रॉयड 1.6 में SQLite संस्करण 3.5.9 है, इसलिए यह विदेशी कुंजी का समर्थन नहीं करता है ...

http://www.sqlite.org/foreignkeys.html "यह दस्तावेज़ SQLite संस्करण 3.6.19 में प्रस्तुत SQL विदेशी कुंजी बाधाओं के लिए समर्थन का वर्णन करता है।"

Froyo में यह SQLite संस्करण 3.6.22 है, इसलिए ...

संपादित करें: sqlite संस्करण देखने के लिए: adb shell sqlite3 -version


तो क्या इस तरह की बाधाओं को दूर करने का कोई तरीका है .. मेरा मतलब है कि साइक्लाइट संस्करण को अपग्रेड करने का कोई तरीका है .. क्योंकि हमें एंड्रॉइड 2.1 के लिए सॉफ़्टवेयर संस्करण का समर्थन करना होगा, जिसका वर्गाकार संस्करण 3.5.9 ऊपर है
NullPointerException

नहीं, आपको खुद ही सब कुछ संभालना होगा :(
GBouerat

1

एंड्रॉइड 2.2 और इसके बाद के संस्करण में SQLite में "डिलीट कैस्केड" वाली विदेशी कुंजियाँ समर्थित हैं। लेकिन उनका उपयोग करते समय सावधान रहें: कभी-कभी एक स्तंभ पर एक विदेशी कुंजी को निकालते समय एक त्रुटि की सूचना दी जाती है, लेकिन वास्तविक समस्या बाल तालिका में या तो एक अन्य स्तंभ विदेशी कुंजी बाधा में निहित है, या किसी अन्य तालिका thet इस तालिका को संदर्भित करती है।

SQLite की तरह लग रहा है जब उनमें से एक फायरिंग सभी बाधाओं की जाँच करता है। यह वास्तव में प्रलेखन में उल्लिखित है। डीडीएल बनाम डीएमएल बाधा जाँच।


0

यदि आप Android कक्ष का उपयोग कर रहे हैं, तो नीचे दिखाए अनुसार करें।

Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
    .addCallback(object : RoomDatabase.Callback() {
        // Called when the database has been opened.
        override fun onOpen(db: SupportSQLiteDatabase) {
            super.onOpen(db)
            //True to enable foreign key constraints
            db.setForeignKeyConstraintsEnabled(true)
        }

        // Called when the database is created for the first time. 
        override fun onCreate(db: SupportSQLiteDatabase) {
            super.onCreate(db)
        }
    }).build()
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.