2013-06-18 21 views
5

मैं डेटाबेस (समान तालिका) में कुछ पंक्तियां डालने के लिए CodeIgniter में एक छोटी सी विधि चला रहा हूं। मैं देखना चाहता हूं कि लेनदेन के अंदर कौन सा सम्मिलन विफल रहा है (खिताब की सरणी लौटकर)। मेरे कोड है:कोडनिर्देशक, लेनदेन में त्रुटि ट्रैकिंग

$failure = array(); //the array where we store what failed 
$this->db->trans_start(); 
foreach ($data as $ressourceCsv){ //data is an array of arrays to feed the database 
    $this->ajout_ressource($ressourceCsv); //method to insert (basically, just an insert with active record) 
    if (($this->db->_error_message())!=null) { 
      $failure[] = $ressourceCsv['title']; 
    } 
} 
$this->db->trans_complete(); 
return $failure; 

तथ्य यह है कि अगर मैं इसे किसी लेन-देन नहीं बनाते हैं (कोई $ this-> db-> ट्रांस _...), यह पूरी तरह से काम करता है और मैं कुछ युक्त एक सरणी है खिताब। लेकिन लेनदेन के साथ, सरणी में पहली त्रुटि के बाद से प्रत्येक शीर्षक शामिल है। क्या लेन-देन को रोलबैक करने के कारण केवल उस प्रविष्टि से शीर्षक प्राप्त करने का कोई तरीका है?

मैं भी साथ की कोशिश की है:

$failure = array(); //the array where we store what failed 
$this->db->trans_start(); 
foreach ($data as $ressourceCsv){ //data is an array of arrays to feed the database 

    if (!$this->ajout_ressource($ressourceCsv)) { //active record insertion return true 
      $failure[] = $ressourceCsv['title']; // if successful 
    } 
} 
$this->db->trans_complete(); 
return $failure; 

उत्तर

1

मुझे विश्वास है कि एक बार एक त्रुटि एक सौदे के अंदर होता है, तो आप किसी भी अधिक डीबी mods से पहले रोलबैक किया जा सकता है चाहिए। इससे आप जो व्यवहार देख रहे हैं उसे समझाएंगे। पहली त्रुटि के बाद, लेनदेन "निरस्त" होता है और आप अपना लूप जारी रखते हैं, जिससे प्रत्येक आगामी SQL कमांड विफल हो जाता है।

db=# select * from test1; 
id | foo | bar 
----+-----+----- 
(0 rows) 

db=# begin; 
BEGIN 
db=# insert into test1 (foo, bar) values (1, 'One'); 
INSERT 0 1 
db=# insert into test1 (foo, bar) values (Oops); 
ERROR: column "oops" does not exist 
LINE 1: insert into test1 (foo, bar) values (Oops); 
              ^
db=# insert into test1 (foo, bar) values (2, 'Two'); 
ERROR: current transaction is aborted, commands ignored until end of transaction block 
db=# select * from test1; 
ERROR: current transaction is aborted, commands ignored until end of transaction block 
db=# commit; 
ROLLBACK 
ace_db=# select * from test1; 
id | foo | bar 
----+-----+----- 
(0 rows) 

db=# 

नोट ऐसा लगता है कि "प्रतिबद्ध" एक "रोलबैक" यदि कोई त्रुटि (यह एक टाइपो नहीं था।)

भी था BTW करता है:: जांच करने के लिए $this->db->trans_status() === FALSE का उपयोग यह इस प्रकार समझा जा सकता है लेनदेन के दौरान एक त्रुटि के लिए।

अद्यतन: यहां कुछ (untested) एक सौदे में यह करने के लिए कोड ताकि आवेषण दूसरों के द्वारा नहीं देखा जाता है जब तक आप तैयार हैं क्या है:

$failure = array(); //the array where we store what failed 
$done = false; 
do { 
    $this->db->trans_begin(); 
    foreach ($data as $key => $ressourceCsv){ //data is an array of arrays to feed the database 
     $this->ajout_ressource($ressourceCsv); //method to insert (basically, just an insert with active record) 
     if ($this->db->trans_status() === false) { // an insert failed 
      $failure[] = $ressourceCsv['title']; // save the failed title 
      unset($data[$key]);     // remove failed insert from data set 
      $this->db->trans_rollback();   // rollback the transaction 
      break;         // retry the insertion 
     } 
    } 
    $done = true;         // completed without failure 
} while (count($data) and ! $done);    // keep going until no data or success 

/* 
* Two options (uncomment one): 
* 1. Commit the successful inserts even if there were failures. 

$this->db->trans_commit(); 

* 2. Commit the successful inserts only if no failures. 

if (count($failure)) { 
    $this->db->trans_rollback(); 
} else { 
    $this->db->trans_commit(); 
} 
*/ 

return $failure; 
+0

ठीक है, यदि ऐसा है तो मैं इसे ठीक है, मिलता है लेनदेन की बहुत संरचना मुझे वांछित होने की अनुमति नहीं देती है। इसके अलावा मैं $-- db-> trans_status() === गलत का उपयोग नहीं कर सकता क्योंकि मैं वास्तव में एक कथन में लेनदेन लाइनों को लपेटता हूं (मैं हमेशा लेनदेन का उपयोग नहीं कर रहा हूं)। मेरी समस्या को हल करने के लिए, अंततः मैंने अंत में उन्हें हटाने के लिए सफल प्रविष्टि की आईडी संग्रहीत की है यदि मैं रोलबैक चाहता हूं और $ विफलता सरणी खाली नहीं है – Dargor

+0

मुझे लगता है कि यदि आपको ** ** अपने सभी आवेषणों को एक बार में करना चाहिए किसी भी असफलताओं के बाद, आप ऐसा कर सकते हैं, लेकिन यदि आपका इरादा यह है कि कुछ विफल होने पर कोई भी इन प्रविष्टियों को नहीं देख पाएगा, तो आप इसे इस तरह पूरा नहीं कर सकते हैं। आपके पास "स्वीकृत" नामक एक बूलियन कॉलम हो सकता है और सभी प्रविष्टियों को समाप्त होने के बाद ही इसे सत्य सेट कर दिया जा सकता है और कोई भी विफल नहीं हुआ - और अपने अन्य प्रश्नों के लिए 'WHERE स्वीकृत = TRUE' खंड जोड़ें। – user9645

+0

मैंने यह दिखाने के लिए अद्यतन जोड़ा कि यदि आप चाहते हैं तो लेनदेन के अंदर लूप कैसे करें। – user9645

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