2011-03-16 11 views
5

मैं माइग्रेशन फ़ंक्शन पर काम कर रहा हूं। यह पुरानी तालिका से डेटा पढ़ता है और इसे नए में डाल देता है। कम प्राथमिकता वाले पृष्ठभूमि थ्रेड में काम करने वाली सभी चीज़ें।sqlite और 'बाधा विफल' त्रुटि एक ही समय में चयन और डालने के दौरान

छद्म कोड में मेरे कदम।

sqlite3_prepare_stmt (select statement) 
sqlite3_prepare_stmt (insert statement) 

while (sqlite3_step (select statement) == SQLITE_ROW) 
{ 
    get data from select row results 
    sqlite3_bind select results to insert statement 
    sqlite3_step (insert statement) 
    sqlite3_reset (insert statement) 
} 

sqlite3_reset (select statement) 

मैं हमेशा हो रही है sqlite3_step (insert statement) पर 'बाधा विफल' त्रुटि। यह खुश क्यों है और मैं इसे कैसे ठीक कर सकता हूं?

यूपीडी: जैसा कि मुझे समझ में आता है कि खुशी है क्योंकि पृष्ठभूमि धागे मुख्य धागे में डीबी हैंडल खोला जाता है। अब अनुमान लगा रहा है।

UPD2:

sqlite> select sql from sqlite_master where tbl_name = 'tiles'; 
CREATE TABLE tiles('pk' INTEGER PRIMARY KEY, 'data' BLOB, 'x' INTEGER, 'y' INTEGER, 'z' INTEGER, 'importKey' INTEGER) 
sqlite> select sql from sqlite_master where tbl_name = 'tiles_v2'; 
CREATE TABLE tiles_v2 (pk int primary key, x int, y int, z int, layer int, data blob, timestamp real) 
+0

अद्यतन के लिए धन्यवाद। मैंने अपना जवाब संपादित किया और कुछ और उपयोगी (मुझे उम्मीद है) जानकारी जोड़ा। –

उत्तर

7

यह शायद अपने डालने बयान नई तालिका में एक बाधा उल्लंघन कर रहा है इसका मतलब है। एक प्राथमिक कुंजी बाधा, एक अद्वितीय बाधा, एक विदेशी कुंजी बाधा हो सकती है (यदि आप PRAGMA foreign_keys = ON; का उपयोग कर रहे हैं), और इसी तरह।

आप या तो बाधा छोड़कर, डेटा को सही करने या डेटा छोड़कर इसे ठीक करते हैं। बाधा को छोड़ना आम तौर पर एक बुरी बात है, लेकिन यह आवेदन पर निर्भर करता है।

क्या सेट के बजाए एक समय में डेटा एक पंक्ति की प्रतिलिपि बनाने का एक अनिवार्य कारण है?

INSERT INTO new_table 
SELECT column_list FROM old_table; 

यदि आपको बाधा की पहचान करने में मदद की ज़रूरत है, तो अपना मूल प्रश्न संपादित करें, और इन दो SQLite क्वेरीज़ के आउटपुट को पोस्ट करें।

select sql from sqlite_master where tbl_name = 'old_table_name'; 
select sql from sqlite_master where tbl_name = 'new_table_name'; 

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

मुझे लगता है कि कुछ अलग तरीकों से हो सकता है।

  • पुरानी तालिका में 'पीके' कॉलम में डुप्लिकेट मान हैं।
  • आपके माइग्रेशन कोड जो आपके नए तालिका में डेटा डालने से पहले डुप्लिकेट मान को बदलता या इंजेक्ट करता है।
  • एक और प्रक्रिया, संभवतः पर एक अलग कंप्यूटर पर चल रही है, आपके ज्ञान के बिना डेटा अपडेट कर रही है।
  • अन्य कारणों से मैंने अभी तक नहीं सोचा है। :-)

आप यह निर्धारित कर सकते हैं कि इस क्वेरी को चलाकर पुरानी तालिका में 'पीके' के डुप्लिकेट मान हैं या नहीं।

select pk 
from old_table_name 
group by pk 
having count() > 1; 

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

+1

संख्या। मैं विदेशी_की का उपयोग नहीं कर रहा हूँ। और एक और धागा है जो आवेषण सफलतापूर्वक करता है। अब मैं हमेशा एक ही डेटा के साथ सम्मिलित भरना भी हूं। और स्थिति में बदलाव नहीं आया। दूसरा धागा हमेशा डेटा डालने में असफल रहा है। म्यूटेक्स द्वारा संरक्षित आवेषण, इसलिए एक बार में केवल एक ही संभव है। –

+0

SQLite से SQL DDL निकालने के लिए दिशानिर्देश जोड़े गए। अपना मूल प्रश्न संपादित करें, और उन दो प्रश्नों के परिणाम डालें। यूपीडी में –

+0

मैंने जोड़ा कि मैं एक ही डेटा के साथ 2 थ्रेड में कई बार सम्मिलित करने की कोशिश कर रहा हूं। पहला धागा (जहां sqlite3 * खोला गया था) हमेशा ठीक काम करता है, दूसरे में डालें काम नहीं किया। जैसा कि आप टेबल स्कीमा से देख सकते हैं - पीके दोनों टेबलों में अद्वितीय है। –

1

बस मामले में किसी को भी यहां भूमि की तलाश में "बाधा में विफल रहा है" त्रुटि संदेश, सुनिश्चित करें कि आपके Id स्तंभ के प्रकार INTEGER, नहीं INTEGER (0, 15) या कुछ है या नहीं।

पृष्ठभूमि

अपने तालिका प्रकार INTEGER साथ Id नाम है, और प्राथमिक कुंजी के रूप में स्थापित एक स्तंभ है, तो SQLite में निर्मित स्तंभ RowId के लिए एक उपनाम के रूप में यह व्यवहार करता है। यह कॉलम एक ऑटो-वृद्धि कॉलम की तरह काम करता है। मेरे मामले में, यह कॉलम कुछ टेबल डिज़ाइनर (शायद विजुअल स्टूडियो के लिए SQLite लोगों द्वारा बनाई गई) तक ठीक काम कर रहा था। INTEGER से INTEGER (0, 15) पर कॉलम प्रकार बदल गया और अचानक मेरे एप्लिकेशन ने Constraint failed अपवाद फेंकना शुरू कर दिया।

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