2013-08-07 6 views
10

क्या कभी किसी ने इस त्रुटि के पार चलो गया है शामिल हैं: सामान्य त्रुटि: 1390 तैयार बयान भी कई प्लेसहोल्डरआयात देता सामान्य त्रुटि: 1390 तैयार बयान भी कई प्लेसहोल्डर

शामिल मैं सिर्फ का SequelPro के माध्यम से एक आयात किया 50,000 से अधिक रिकॉर्ड और अब जब मैं इन दृश्यों को अपने विचार में देखने के लिए जाता हूं (लैरावेल 4) मुझे सामान्य त्रुटि मिलती है: 13 9 0 तैयार कथन में बहुत से प्लेसहोल्डर हैं।

मेरी AdminNotesController.php फ़ाइल में नीचे दी गई अनुक्रमणिका() विधि क्वेरी उत्पन्न करने और दृश्य को प्रस्तुत करने वाला है।

public function index() 
{ 
    $created_at_value = Input::get('created_at_value'); 
    $note_types_value = Input::get('note_types_value'); 
    $contact_names_value = Input::get('contact_names_value'); 
    $user_names_value = Input::get('user_names_value'); 
    $account_managers_value = Input::get('account_managers_value'); 

    if (is_null($created_at_value)) $created_at_value = DB::table('notes')->lists('created_at'); 
    if (is_null($note_types_value)) $note_types_value = DB::table('note_types')->lists('type'); 
    if (is_null($contact_names_value)) $contact_names_value = DB::table('contacts')->select(DB::raw('CONCAT(first_name," ",last_name) as cname'))->lists('cname'); 
    if (is_null($user_names_value)) $user_names_value = DB::table('users')->select(DB::raw('CONCAT(first_name," ",last_name) as uname'))->lists('uname'); 

    // In the view, there is a dropdown box, that allows the user to select the amount of records to show per page. Retrieve that value or set a default. 
    $perPage = Input::get('perPage', 10); 

    // This code retrieves the order from the session that has been selected by the user by clicking on a table column title. The value is placed in the session via the getOrder() method and is used later in the Eloquent query and joins. 
    $order = Session::get('account.order', 'company_name.asc'); 
    $order = explode('.', $order); 

    $notes_query = Note::leftJoin('note_types', 'note_types.id', '=', 'notes.note_type_id') 
     ->leftJoin('users', 'users.id', '=', 'notes.user_id') 
     ->leftJoin('contacts', 'contacts.id', '=', 'notes.contact_id') 
     ->orderBy($order[0], $order[1]) 
     ->select(array('notes.*', DB::raw('notes.id as nid'))); 

    if (!empty($created_at_value)) $notes_query = $notes_query->whereIn('notes.created_at', $created_at_value); 

    $notes = $notes_query->whereIn('note_types.type', $note_types_value) 
     ->whereIn(DB::raw('CONCAT(contacts.first_name," ",contacts.last_name)'), $contact_names_value) 
     ->whereIn(DB::raw('CONCAT(users.first_name," ",users.last_name)'), $user_names_value) 
     ->paginate($perPage)->appends(array('created_at_value' => Input::get('created_at_value'), 'note_types_value' => Input::get('note_types_value'), 'contact_names_value' => Input::get('contact_names_value'), 'user_names_value' => Input::get('user_names_value'))); 

    $notes_trash = Note::onlyTrashed() 
     ->leftJoin('note_types', 'note_types.id', '=', 'notes.note_type_id') 
     ->leftJoin('users', 'users.id', '=', 'notes.user_id') 
     ->leftJoin('contacts', 'contacts.id', '=', 'notes.contact_id') 
     ->orderBy($order[0], $order[1]) 
     ->select(array('notes.*', DB::raw('notes.id as nid'))) 
     ->get(); 

    $this->layout->content = View::make('admin.notes.index', array(
     'notes'    => $notes, 
     'created_at'  => DB::table('notes')->lists('created_at', 'created_at'), 
     'note_types'  => DB::table('note_types')->lists('type', 'type'), 
     'contacts'   => DB::table('contacts')->select(DB::raw('CONCAT(first_name," ",last_name) as cname'))->lists('cname', 'cname'), 
     'accounts'   => Account::lists('company_name', 'company_name'), 
     'users'    => DB::table('users')->select(DB::raw('CONCAT(first_name," ",last_name) as uname'))->lists('uname', 'uname'), 
     'notes_trash'  => $notes_trash, 
     'perPage'   => $perPage 
    )); 
} 

किसी भी सलाह की सराहना की जाएगी। धन्यवाद।

+0

यदि आप आयात करते हैं तो हम 100 रिकॉर्ड कहें। यह ठीक काम करता है? त्रुटि के आधार पर –

+0

(मैं उस ह्यूज कोड टुकड़े को देखने की कोशिश भी नहीं करूंगा), ऐसा लगता है कि आप एक्स प्लेसहोल्डर्स और केवल वाई मानों के साथ एक प्रश्न तैयार कर रहे हैं, वाई <एक्स –

+0

@TheDisintegrator हां, यह ठीक काम करता है । –

उत्तर

-2

मुझे लगता है कि प्लेसहोल्डर की संख्या 65536 प्रति क्वेरी तक सीमित है (कम से कम पुराने mysql संस्करणों में)।

मैं वास्तव में यह नहीं समझ सकता कि कोड का यह टुकड़ा क्या उत्पन्न कर रहा है। लेकिन अगर यह एक विशाल सवाल है, तो आपकी समस्या है।

आपको प्रति रिकॉर्ड एक प्रश्न उत्पन्न करना चाहिए ताकि उन्हें आयात करने और लेनदेन में डाल दिया जा सके।

+1

डाउनवोट के लिए एक स्पष्टीकरण अच्छा होगा। मुझे पूरा यकीन है कि समस्या यह है कि ओपी प्लेसहोल्डर्स को –

+5

तक सीमित कर रहा था, मुझे लगता है कि यह कारण है कि आपको डाउनवॉटेड किया गया है: "आपको प्रति रिकॉर्ड एक क्वेरी उत्पन्न करनी चाहिए" –

+1

"आपको प्रति रिकॉर्ड एक क्वेरी उत्पन्न करनी चाहिए" मेरे मामले में धीमा। प्रति रिकॉर्ड एक प्रश्न 65536 प्लेसहोल्डर्स का उपयोग करने से धीमा है। एसक्यूएल पार्स और लेनदेन सामान आपके सीपीयू को आपके मामले में खर्च करेंगे। और नेटवर्क आरआरटी ​​भी बहुत समय लगेगा। –

5

जबकि मुझे लगता है कि @The Disintegrator प्लेसहोल्डर सीमित होने के बारे में सही है। मैं प्रति रिकॉर्ड 1 क्वेरी नहीं चलाऊंगा।

मेरे पास एक प्रश्न है जो ठीक काम करता है जब तक कि मैंने एक और कॉलम नहीं जोड़ा और अब मेरे पास 72k प्लेसहोल्डर्स हैं और मुझे यह त्रुटि मिलती है। हालांकि, यह 72k 8 कॉलम के साथ 9000 पंक्तियों से बना है। इस क्वेरी को एक समय में 1 रिकॉर्ड चलाने में दिन लगेंगे। (मैं एक डीबी में AdWords डेटा आयात करने की कोशिश कर रहा हूं और यदि मैं इसे एक बार रिकॉर्ड करता हूं तो दिन के डेटा के आयात के लिए 24 घंटे से अधिक समय लगेगा। मैंने पहले कोशिश की थी।)

मैं क्या एक हैक की सिफारिश करेंगे। सबसे पहले गतिशील रूप से उन प्लेसहोल्डर्स की अधिकतम संख्या निर्धारित करें जिन्हें आप अनुमति देना चाहते हैं - यानी 60k सुरक्षित होना चाहिए। कॉलम की संख्या के आधार पर निर्धारित करने के लिए इस नंबर का उपयोग करें, आप कितने पूर्ण रिकॉर्ड आयात कर सकते हैं/एक बार में लौट सकते हैं। आपके प्रश्न के लिए डेटा की पूरी सरणी बनाएं। कम से कम प्रश्नों में जो कुछ भी आप चाहते हैं उसे पकड़ने के लिए array_chunk और फ़ोरैच लूप का उपयोग करें। इस तरह:

$maxRecords = 1000; 
$sql = 'SELECT * FROM ...'; 
$qMarks = array_fill(0, $maxInsert, '(?, ...)'); 
$tmp = $sql . $implode(', ', $qMarks); 
foreach (array_chunk($data, $maxRecords) AS $junk=>$dataArray) { 
    if (count($dataArray) < $maxRecords)) { break; } 

    // Do your PDO stuff here using $tmp as you SQL statement with all those placeholders - the ?s 
} 

// Now insert all the leftovers with basically the same code as above except accounting for 
// the fact that you have fewer than $maxRecords now. 
5

यह त्रुटि केवल होता है जब निम्न स्थितियों के दोनों मिले हैं:

  1. आप MySQL Native Driver (mysqlnd) और नहीं MySQL क्लाइंट लाइब्रेरी (libmysqlclient)
  2. उपयोग कर रहे हैं आप अनुकरण तैयार नहीं कर रहे हैं।

यदि आप इन कारकों में से किसी एक को बदलते हैं, तो यह त्रुटि नहीं होगी। हालांकि ध्यान रखें कि इन दोनों को प्रदर्शन या सुरक्षा मुद्दों के लिए अनुशंसा की जाती है, इसलिए मैं किसी भी समय के लिए इस समाधान की अनुशंसा नहीं करता हूं, लेकिन आपके पास एक बार या अस्थायी समस्या है।

$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, true); 
+0

धन्यवाद @ माइक, यह वह जवाब है जिसे मैं – alex

+0

@Sadee देख रहा था, जहां डेटाबेस कॉन्फ़िगरेशन विकल्प संग्रहीत किए जाते हैं और कनेक्शन कैसे खोला जाता है, प्रत्येक एप्लिकेशन के लिए अलग होता है। – Mike

+0

@ माइक हां आप सही हैं। और इस तरह से (config/database.php फ़ाइल में सेट विकल्प) मेरे ऐप में अन्य समस्याएं उत्पन्न करता है (उदा: प्रश्नों के लिए सेट पैरामीटर में)। इसलिए, मैंने इसे हटा दिया और इस बड़ी क्वेरी से ठीक पहले इस विशेषता को सेट किया। इसके बारे में कोई सुझाव? मैंने अपनी पिछली टिप्पणी हटा दी। – Sadee

7

वहाँ MariaDB 5 में सीमा 65.535 (2^16-1) जगह धारकों है: होने से इस त्रुटि से बचने के लिए, ठीक के रूप में सरल है।5 जिसे MySQL 5.5 के समान व्यवहार माना जाता है।

यह सुनिश्चित नहीं है कि प्रासंगिक है, तो मैंने इसे MySQLi/MySQLND का उपयोग करके PHP 5.5.12 पर परीक्षण किया।

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