2012-11-09 14 views
48

के रूप में दस्तावेज में वाक्य रचना डालने या अद्यतन है बनाने के लिए देखा जा सकता है: INSERT OR REPLACE INTO <table> (<columns>) VALUES (<values>), मेरे सवाल का कोई समारोह है कि निम्नलिखित विलय है?एंड्रॉयड SQLite सम्मिलित या अद्यतन

public long insert (String table, String nullColumnHack, ContentValues values) 
public int update (String table, ContentValues values, String whereClause, String[] whereArgs) 

या इसे एक तैयार SQL कथन और rawQuery के साथ किया जाना है?

एंड्रॉयड में एक डालने या अद्यतन करने के लिए सर्वोत्तम प्रथाओं क्या है?

+2

आप किसी विशेष पंक्ति .. पूर्व पर अद्यतन कह सकते हैं। ___ अपडेट करें जहां rowId = 4 .. और यदि अद्यतन 0 देता है .. आपको पता है कि आपके पास वह पंक्ति नहीं है, तो बस इसे डालें। – dymmeh

उत्तर

3

SQLiteDatabase.replace() शायद आप के लिए क्या देख रहे है। मैंने कोशिश नहीं की है लेकिन डॉक्टर कहते हैं कि यह नई डाली गई पंक्ति की पंक्ति आईडी देता है, इसलिए यह काम कर सकता है।

41
इस

अपने विधि SQLiteDatabase.insertWithOnConflict() है। समझने के लिए यह SQLite

+19

प्रश्न के अनुसार काम करने के लिए इस विधि को 'CONFLICT_REPLACE' ध्वज के साथ बुलाया जाना चाहिए। –

+0

क्या यह अपडेट नहीं होना चाहिए WithOnConflict, ताकि आप एक खंड को परिभाषित कर सकें? – NikkyD

+3

@NikkyD 'updateWithOnConflict' अगर यह अस्तित्व में नहीं है तो एक नई पंक्ति नहीं डालेगा। जहां 'insertWithOnConflict' इस प्रकार काम करता है: यदि पंक्ति मौजूद है (संघर्ष) इसे अद्यतन करें, यदि नहीं (कोई संघर्ष नहीं) एक नया डालें। जो मुझे लगता है वह सवाल क्या है। – kdehairy

71

पर this document का उल्लेख करता है मुझे विश्वास है कि आप कैसे करने के लिए सम्मिलित करें नई पंक्तियाँ पूछ या अपने मौजूदा पंक्तियों एक कदम में अद्यतन कर रहे हैं। हालांकि यह एक भी कच्चे एसक्यूएल के रूप में this answer में चर्चा में संभव है, मैंने पाया यह आसान conflictAlgorithm के लिए CONFLICT_IGNORE का उपयोग कर SQLiteDatabase.insertWithOnConflict() का उपयोग कर एंड्रॉयड में दो चरणों में यह करने के लिए कि।

ContentValues initialValues = new ContentValues(); 
initialValues.put("_id", 1); // the execution is different if _id is 2 
initialValues.put("columnA", "valueNEW"); 

int id = (int) yourdb.insertWithOnConflict("your_table", null, initialValues, SQLiteDatabase.CONFLICT_IGNORE); 
if (id == -1) { 
    yourdb.update("your_table", initialValues, "_id=?", new String[] {"1"}); // number 1 is the _id here, update to variable for your code 
} 

इस उदाहरण मानता है कि तालिका कुंजी स्तंभ "_ id" के लिए सेट कर दिया जाता है, कि तुम रिकॉर्ड _ id पता है, और वहाँ पहले से ही # 1 (_ id = 1, Columna = "valueA", columnB = पंक्ति है कि "VALUE अरब")। यहाँ CONFLICT_REPLACE और CONFLICT_IGNORE साथ insertWithOnConflict का उपयोग कर

  • CONFLICT_REPLACE दूसरे कॉलम के मौजूदा मूल्यों के ऊपर लिख देगा शून्य पर (यानी। ColumnB शून्य हो जाएगा और परिणाम _ id हो जाएगा = 1, Columna = "valueNEW" अंतर है, columnB = शून्य)। परिणामस्वरूप आप मौजूदा डेटा खो देते हैं और मैं इसे अपने कोड में उपयोग नहीं करता हूं।
  • CONFLICT_IGNORE आपकी मौजूदा पंक्ति # 1 के लिए SQL INSERT को छोड़ देगा और आप SQL को अन्य सभी कॉलम की सामग्री को संरक्षित करने के अगले चरण में इस पंक्ति को अद्यतन करेंगे (यानी परिणाम _id = 1, columnA = "valueNEW" होगा, कॉलम बी = "वैल्यूबी")।

जब आप डालने के लिए नई पंक्ति # 2 जो अभी मौजूद नहीं है प्रयास करते हैं, कोड केवल पहले बयान insertWithOnConflict में एसक्यूएल सम्मिलित करें निष्पादित करेंगे (यानी। परिणाम _ id हो जाएगा = 2, Columna = "valueA" , कॉलम बी = न्यूल)।

this bug से सावधान रहें जो SQLiteDatabase.CONFLICT_IGNORE को API10 (और शायद API11) पर खराब होने का कारण बन रहा है। जब मैं एंड्रॉइड 2.2 पर परीक्षण करता हूं तो क्वेरी -1 के बजाय 0 लौट रही है।

आप रिकॉर्ड कुंजी _ id पता नहीं है या आप एक शर्त है कि एक संघर्ष नहीं बनाएगा है, तो आप तर्क को अपडेट करने या INSERT को उल्टा कर सकते हैं। यह UPDATE के दौरान आपकी रिकॉर्ड कुंजी _id रखेगा या INSERT के दौरान एक नया रिकॉर्ड _id बनाएगा।

int u = yourdb.update("yourtable", values, "anotherID=?", new String[]{"x"}); 
if (u == 0) { 
    yourdb.insertWithOnConflict("yourtable", null, values, SQLiteDatabase.CONFLICT_REPLACE); 
} 

उपरोक्त उदाहरण मानता है कि आपके सिर्फ उदाहरण के लिए रिकॉर्ड में टाइमस्टैम्प मूल्य अपडेट करना चाहते हैं। यदि आप पहले डालें WithOnConflict को कॉल करते हैं, तो टाइमस्टैम्प स्थिति में अंतर के कारण INSERT नया रिकॉर्ड _id बनाएगा।

+0

CONFLICT_IGNORE के बजाय CONFLICT_REPLACE का उपयोग करना आसान होगा, जैसा कि अन्य ने उल्लेख किया है। – aleb

+4

@aleb - CONFLICT_IGNORE और CONFLICT_REPLACE के बीच एक बड़ा अंतर है जब क्वेरी तालिका में सभी कॉलम निर्दिष्ट नहीं करती है। जब आप CONFLICT_REPLACE का उपयोग करते हैं, तो क्वेरी उन सभी कॉलमों में नल मान डालती है जिनके पास ContentValues ​​चर में निर्दिष्ट कोई मान नहीं है। मेरे मामले में, मुझे शेष चार के मूल्य को जानने के बिना केवल पांच में से एक कॉलम अपडेट करना होगा। CONFLICT_REPLACE का उपयोग करके अन्य चार स्तंभों को मानों को मिटाने के लिए मजबूर किया गया। – theczechsensation

+0

ठीक है, जानना अच्छा है, लेकिन सवाल "INSERT या स्थानांतरित करें" के बारे में था – aleb

4

आप अपनी तालिका के स्तंभों है कि यह अद्वितीय एक पंक्ति बनाने की पहचान करने की जरूरत है।

उदाहरण: _ id, नाम, काम,,

कॉलम नाम और काम कर रहे हैं hours_worked जब आप की पहचान यह इस विधि का उपयोग:

private int getID(String name, String job){ 
    Cursor c = dbr.query(TABLE_NAME,new String[]{"_id"} "name =? AND job=?",new String[]{name,job},null,null,null,null); 
    if (c.moveToFirst()) //if the row exist then return the id 
     return c.getInt(c.getColumnIndex("_id")); 
    return -1; 
} 

अपनी कक्षा में:

public void insertOrUpdate(String name, String job){ 
    ContentValues values = new ContentValues(); 
    values.put("NAME",name); 
    values.put("JOB",job); 

    int id = getID(name,job); 
    if(id==-1) 
     db.insert(TABLE_NAME, null, values); 
    else 
     db.update(TABLE_NAME, values, "_id=?", new String[]{Integer.toString(id)}); 
} 
+2

प्रश्न एक फ़ंक्शन के बारे में है जो सम्मिलित करें और अपडेट फ़ंक्शंस को विलय करता है, तो इसका उपयोग कैसे करें। – aleb

+0

@aleb इससे मुझे बहुत मदद मिली। –

6

SQLiteDatabase.replace() यह करता है, यह मूल रूप से कॉल करता है:

insertWithOnConflict(table, nullColumnHack, initialValues, CONFLICT_REPLACE); 

बहुत खराब दस्तावेज बहुत स्पष्ट नहीं है।

2

मुझे एक ही समस्या थी, लेकिन मुझे एहसास हुआ कि मेरे ऑब्जेक्ट में पहले से ही एक आईडी है, इसे अपडेट किया जाना चाहिए और जब उसके पास कोई आईडी नहीं है तो इसे डाला जाना चाहिए ताकि यह समस्या हल करने के लिए मैंने जो कदम उठाया है,

1- में अपनी वस्तु getId पूर्णांक का उपयोग करें या ईद प्रारंभ कैसे आप फिट देखें: यहाँ मेरी कोड

public Integer getId() { 
    return id; 
} 

2- जांच डालने या अद्यतन करने के बाद आप डाल के लिए अपनी पद्धति में आईडी है ContentValues ​​में सब कुछ:

if(myObject.getId()!= null){ 
     int count = db.update(TABLE_NAME,myContentValues,ID + " = ? ", 
       new String[]{String.valueOf(myObject.getId())}); 
     if(count<=0){ 
      //inserting content values to db 
      db.insert(TABLE_NAME, null, myContentValues); 
     } 
    } else { 
     db.insert(TABLE_NAME, null, myContentValues); 
    } 

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

उम्मीद है कि इससे मदद मिलती है।

0

के बारे में क्या replaceOrThrow (स्ट्रिंग तालिका, स्ट्रिंग nullColumnHack, ContentValues ​​initialValues)

डॉक्स कहते हैं ... डेटाबेस में एक पंक्ति की जगह के लिए सुविधा विधि। यदि कोई पंक्ति पहले से मौजूद नहीं है तो एक नई पंक्ति डालें।

मूल रूप से यह कहता है insertWithOnConflict

संबंधित मुद्दे