2013-02-19 9 views
5

मेरे सभी प्रश्नों पर bind_param का उपयोग करके, अब मैं IN(?) का उपयोग करना चाहता हूं जहां सूची में तत्वों की संख्या भिन्न हो सकती है।mySQL bind_param IN (?)

SQLout समारोह मैं यहाँ मूल रूप से उपयोग कर रहा हूँ एक $sql_db->prepare, ->bind_param, ->execute(), ->store_result(), ->bind_result

// the code below does not work as the query only matches on element 'a': 
$locations = ('a','b','c','d','e'); 

SQLout ("SELECT Name FROM Users WHERE Locations IN (?)", 
    array('s', $locations), array(&$usrName)); 


// the code below does work as a brute-force method, 
// but is not a viable solution as I can't anticipate the number of elements in $locations going forward: 

SQLout ("SELECT Name FROM Users WHERE Locations IN (?,?,?,?,?)", 
    array('sssss', $locations[0],$locations[1],$locations[2],$locations[3],$locations[4]), array(&$usrName)); 

किसी को इस के लिए एक अधिक सुरुचिपूर्ण समाधान के साथ आ गया है करता है?

+0

[पीएचपी पीडीओ के संभावित डुप्लिकेट से काम कर कोड के करीब : क्या मैं एक आईएन() स्थिति में एक सरणी बांध सकता हूं?] (Http://stackoverflow.com/questions/920353/php-pdo-can-i-bind-an-array-to-an-in-condition) –

+1

पीडीओ उत्तरों के पास mysqli समस्याओं से कोई लेना देना नहीं है। पीडीओ तैयार कथन की परिवर्तनीय संख्या को संभालने के मामले में mysqli की तुलना में एक स्वर्ग है –

उत्तर

4

यह एक जगह प्लेसहोल्डर्स उनके चेहरे पर पड़ता है। माइनस ऑटो एस्केपिंग, वे लगभग सचमुच सिर्फ एक स्ट्रिंग प्रतिस्थापन operationt आंतरिक रूप से कर रहे हैं, जिसका अर्थ है कि यदि आप WHERE x IN (?) है, और 1,2,3,4 में गुजरती हैं, आप तार्किक

के बराबर

WHERE x IN ('1,2,3,4') // note, it's a string, not individual comma-separated ints 

के बराबर मिलेगा

WHERE x = '1,2,3,4' // again, just a string 

अधिक की उम्मीद

WHERE (x = 1) or (x = 2) or (x = 3) or (x = 4) 

केवल व्यावहारिक समाधान की isntead +०१२३८३३४२५७४ की अपनी सूची का निर्माण करना है, उदाहरण:

$placeholders = implode(array_fill(0, count($values), '?')); 
$sql = "SELECT ... WHERE x IN ($placeholders)"; 

और फिर अपने पैरामीटर को बाध्य करें सामान्य हैं।

+0

'$ stmt-> निष्पादित करें ($ मान)'। के रूप में आसान हो सकता है। –

+2

दुर्भाग्यवश, माइस्क्ली में बाध्यकारी तैयार बयान पीडीओ में जितना आसान नहीं है। Mysqli में '$ stmt-> निष्पादित ($ मान)' सुविधा नहीं है। न ही इसमें बाध्य वैल्यू विधि है (इसलिए आप पुनरावृत्त चर का उपयोग कर लूप में बाध्य नहीं कर सकते हैं) जो एक बार में सर्कस और एक दुःस्वप्न का इतना आसान काम करता है। यही कारण है कि यह उत्तर अधूरा –

+0

मेरे मामले के लिए सबसे अच्छा काम करता है। मुझे लंबे समय तक तत्वों के उपयोग पर कुछ गति परीक्षण चलाने होंगे। – user2033684

-1

आईएन आमतौर पर धीमी और तैयार कथन अनुकूल नहीं है। बेहतर समाधान उन वस्तुओं की एक तालिका बनाना है जो आईएन में होंगे और एक ही प्रभाव प्राप्त करने के लिए जॉइन का उपयोग करें।

+0

@ फिर आप आईएन में मूल्यों की परिवर्तनीय संख्या कैसे प्राप्त करें इसका एक उदाहरण प्रदान करते हैं। –

+0

@your कृपया पढ़ें http://stackoverflow.com/questions/4771183/sql-fixed-value-in-vs-inner-join-performance आईएन के साथ समस्या यह है कि आप सूची में सूचीबद्ध नहीं कर सकते हैं जैसे आप कर सकते हैं तालिका और सूची के रूप में लंबे समय तक प्रदर्शन तेजी से गिरावट आती है। बेशक यह सूची तेज है जब सूची कम है। –

1

आप इसे तैयार करने/बांधने से पहले IN खंड में "निर्माण" कर सकते हैं।

$sql = 'SELECT Name FROM Users WHERE Locations IN (' . implode(array_fill(0, count($locations), '?')) . ')'; 

तो फिर तुम call_user_func_array का उपयोग मानकों बाध्य करने के लिए, कभी जानने देखते हैं कि कितने बिना कर सकते हैं।

// Parameters for SQLOut 
$params = array(
    # The SQL Query 
    $sql, 
    # The params for bind_param 
    array(str_repeat('s', count($locations))), 
    # The params for bind_result 
    array(&$usrName) 
); 

// Add the locations into the parameter list 
foreach($locations as &$loc){ 
    // not sure if this is needed, but bind_param 
    // expects its parameters to be references 
    $params[1][] = &$loc; 
} 

// Call your function 
call_user_func_array('SQLout', $params); 

नोट: यह अपरीक्षित है

-2

किसी को भी इस के लिए एक अधिक सुरुचिपूर्ण समाधान के साथ आ गया है?

निश्चित रूप से। मैं हूँ।

माईस्की व्यावहारिक रूप से तैयार बयान के साथ अनुपयोगी है, खासकर ऐसे जटिल मामलों के साथ।
तो, तैयार बयानों से छुटकारा पाने और सभी वास्तविक जीवन के मामलों के समर्थन के साथ अपने स्वयं के प्लेसहोल्डर को कार्यान्वित करना बेहतर है।

तो, safeMysql में एक समाधान है जिसे आप ढूंढ रहे हैं (और दर्जन अन्य सिरदर्द के लिए भी समाधान)।

अपने विशेष मामले में यह कोड के इस एक पंक्ति के रूप में के रूप में आसान होगा

// the code works all right: 
$locations=array('a','b','c','d','e'); 
$usrName=$db->getCol("SELECT Name FROM Users WHERE Locations IN (?a)",$locations); 
बदसूरत कोड आप कुछ PHP और एपीआई कार्यों के साथ खेल प्राप्त कर सकते हैं (और अब भी परेशान चेतावनी मिल के विपरीत

PHP संस्करण पर निर्भर करता है आप इस समय उपयोग कर रहे हैं) यह कोड साफ है और पठनीय है। यह महत्वपूर्ण बात है। आप बता सकते हैं कि एक वर्ष बीतने के बाद भी यह कोड क्या करता है।

+0

यदि सूची लंबी है तो यह धीमा होने जा रहा है http://stackoverflow.com/questions/4771183/sql-fixed-value-in-vs-inner-join-performance –

2

रूप Hazmat कहा, तुम मानकों का निर्माण और फिर उन्हें तैयार बयान पर call_user_func_array फोन करके उत्तीर्ण करने की आवश्यकता है, लेकिन थोड़ा उसके उदाहरण :)

//In the calling code 
$queryString = "SELECT Name FROM Users WHERE Locations IN ("; 
$queryString .= getWhereIn($locations); 
$queryString .= ")"; 

$parametersArray = array(); 

foreach($locations as $location){ 
    $parameter = array(); 
    $parameter[0] = 's'; //It's a string 
    $parameter[1] = $location; 

    $parametersArray[] = $parameter; 
} 



//This is a function in a class that wraps around the class mysqli_statement 
function bindParameterArray($parameterArray){ 

    $typesString = ''; 
    $parameterValuesArray = array(); 

    foreach($parameterArray as $parameterAndType){ 
     $typesString .= $parameterAndType[0]; 
     $parameterValuesArray[] = $parameterAndType[1]; 
    } 

    $finalParamArray = array($typesString); 
    $finalParamArray = array_merge($finalParamArray, $parametersArray); 
    call_user_func_array(array($this->statement, "bind_param"), $finalParamArray); 
} 

function getWhereIn($inArray){ 
    $string = ""; 
    $separator = ""; 
    for($x=0 ; $x<count($inArray) ; $x++){ 
     $string .= $separator."?"; 
     $separator = ", "; 
    } 
    return $string; 
} 
संबंधित मुद्दे