2009-11-05 10 views
13

Ho una procedura memorizzata con più set di risultati. Come posso passare al secondo set di risultati in mysqli per ottenere quei risultati?Recupero di serie di risultati multipli con stored procedure in php/mysqli

Diciamo che è un proc memorizzato come:

create procedure multiples(param1 INT, param2 INT) 
BEGIN 

SELECT * FROM table1 WHERE id = param1; 

SELECT * FROM table2 WHERE id = param2; 

END $$ 

Il PHP è qualcosa di simile:

$stmt = mysqli_prepare($db, 'CALL multiples(?, ?)'); 

mysqli_stmt_bind_param($stmt, 'ii', $param1, $param2); 

mysqli_stmt_execute($stmt); 

mysqli_stmt_bind_result($stmt, $id); 

Allora questa è la parte che non posso andare al lavoro. Ho provato a utilizzare mysqli_next_result per passare al set di risultati successivo, ma non riesco a farlo funzionare. L'abbiamo fatto funzionare con mysqli_store_result e mysqli_fetch_assoc/array/row, ma per qualche motivo tutti gli inti vengono restituiti come stringhe vuote.

Qualcun altro si imbatte in questo e ha una soluzione?

+0

La chiamata alla procedura restituisce correttamente utilizzando mysqli_multi_query() invece di un'istruzione preparata? – gapple

+0

Oh, mi dispiace. La mia prima risposta non è stata la lettura corretta del tuo commento. Abbiamo bisogno di utilizzare istruzioni preparate, ma la query è corretta e funziona per il primo set di risultati. Non riesco proprio a capire come avanzare al secondo set di risultati. – MacAnthony

risposta

13

penso che ti manca qualcosa qui (di seguito non è stato testato):

$stmt = mysqli_prepare($db, 'CALL multiples(?, ?)'); 
mysqli_stmt_bind_param($stmt, 'ii', $param1, $param2); 
mysqli_stmt_execute($stmt); 
// fetch the first result set 
$result1 = mysqli_use_result($db); 
// you have to read the result set here 
while ($row = $result1->fetch_assoc()) { 
    printf("%d\n", $row['id']); 
} 
// now we're at the end of our first result set. 
mysqli_free_result($result1); 

//move to next result set 
mysqli_next_result($db); 
$result2 = mysqli_use_result($db); 
// you have to read the result set here 
while ($row = $result2->fetch_assoc()) { 
    printf("%d\n", $row['id']); 
} 
// now we're at the end of our second result set. 
mysqli_free_result($result2); 

// close statement 
mysqli_stmt_close($stmt); 

Utilizzando PDO il codice sarebbe simile:

$stmt = $db->prepare('CALL multiples(:param1, :param2)'); 
$stmt->execute(array(':param1' => $param1, ':param2' => $param2)); 
// read first result set 
while ($row = $stmt->fetch()) { 
    printf("%d\n", $row['id']); 
} 
$stmt->nextRowset(); 
// read second result set 
while ($row = $stmt->fetch()) { 
    printf("%d\n", $row['id']); 
} 

Ma ho sentito dire che il PDOStatement::nextRowset() non è implementato con rendendo impossibile recuperare più set di risultati:

Quindi, a seconda della versione di PHP, che avrebbe dovuto attaccare con la vostra mysqli -solution. A proposito: usi deliberatamente lo stile procedurale? Utilizzare lo stile orientato agli oggetti con mysqli renderebbe il tuo aspetto un po 'più accattivante (la mia opinione personale).

+0

Siamo a conoscenza di PDO e ancora bisogno di valutare per vedere se è meglio del mysqli, ma questo è un progetto esistente e la sostituzione del livello DB non è realistico. La combinazione di 2 livelli di DB è solo una cattiva progettazione, IMO. – MacAnthony

+0

Sì, hai ragione, ho omesso la linea mysqli_stmt_fetch ($ stmt). Uno sviluppatore precedente ha utilizzato oggetti mysqli-stmt invece di oggetti set di risultati. Come detto, quando abbiamo provato il set di risultati con fetch_assoc, tutte le colonne int restituite come stringhe vuote. – MacAnthony

+0

Questa è una vecchia domanda e risposta, ma la soluzione mysqli non funziona più ... 'mysqli_use_result' restituirà' false' dopo 'mysqli_stmt_execute' ...' mysqli_use_result' può essere utilizzato solo dopo una "query" –

1

Sembra che MySQLi supporti solo più set di risultati tramite mysqli_multi_query(), poiché gli oggetti MySQLi_STMT funzionano diversamente dagli oggetti MySQLi_Result.

PDO sembra essere un po 'più astratto, con gli oggetti PDOStatement poter gestire più set di risultati per entrambe le query regolari (PDO::query) e istruzioni preparate (PDO:prepare).

+0

può anche scorrere su più set di risultati usando '$ stmt-> get_results()' ... '$ stmt-> next_result()' .. entrambe le funzioni/metodi sono disponibili solo con "MySQL Native Driver" –

0

Questo ha funzionato molto bene per me, si occuperà (come un esempio) di molti elenchi di selezione quanti sono nel tuo SP. Da notare come si deve chiudere la chiamata prima di $ si può quindi raggiungere i parametri fuori dal vostro SP ...

?><pre><? 
$call = mysqli_prepare($db, 'CALL test_lists(?, ?, @result)'); 
if($call == false) { 
    echo "mysqli_prepare (\$db, 'CALL test_lists(?, ?, @result) FAILED!!!\n"; 
} else { 
    // A couple of example IN parameters for your SP... 
    $s_1 = 4; 
    $s_2 = "Hello world!"; 

    // Here we go (safer way of avoiding SQL Injections)... 
    mysqli_stmt_bind_param($call, 'is', $s_1, $s_2); 

    // Make the call... 
    if(mysqli_stmt_execute($call) == false) { 
     echo "mysqli_stmt_execute(\$call) FAILED!!!\n"; 
    } else { 
     //print_r($call); 

     // Loop until we run out of Recordsets... 
     $set = 0; 
     while ($recordset = mysqli_stmt_get_result($call)) { 
      ++$set; 
      //print_r($recordset); 
      echo "\nRecordset #" . $set . "...\n"; 
      if ($recordset->num_rows > 0) { 
       $ctr = 0; 
       while ($row = $recordset->fetch_assoc()) { 
        ++$ctr; 
        //print_r($row); 
        echo "\t" . $ctr . ": "; 
        forEach($row as $key => $val) { 
         echo "[" . $key . "] " . $val . "\t"; 
        } 
        echo "\n"; 
       } 
      } 
      echo $recordset->num_rows . " record" . ($recordset->num_rows == 1 ? "" : "s") . ".\n"; 
      // Clean up, ready for next iteration... 
      mysqli_free_result($recordset); 

      // See if we can get another Recordset... 
      mysqli_stmt_next_result($call); 
     } 

     // Then you have to close the $call... 
     mysqli_stmt_close($call); 
     // ...in order to get to the SP's OUT parameters... 
     $select = mysqli_query($db, "SELECT @result"); 
     $row = mysqli_fetch_row($select); 
     $result = $row[0]; 
     echo "\nOUT @result = " . $result . "\n"; 
    } 
} 
?></pre><? 

E questo è ciò che l'output del codice di cui sopra appare come usare il mio test_lists SP ...

Recordset #1... 
    1: [s_1] 4 [user_name] Andrew Foster 
    2: [s_1] 4 [user_name] Cecil 
    3: [s_1] 4 [user_name] Sheff 
3 records. 

Recordset #2... 
    1: [s_2] Hello world! [section_description] The Law 
    2: [s_2] Hello world! [section_description] History 
    3: [s_2] Hello world! [section_description] Wisdom Literature 
    4: [s_2] Hello world! [section_description] The Prophets 
    5: [s_2] Hello world! [section_description] The Life of Jesus and the Early Church  
    6: [s_2] Hello world! [section_description] Letters from the Apostle Paul 
    7: [s_2] Hello world! [section_description] Other Letters from Apostles and Prophets 
    8: [s_2] Hello world! [section_description] Prophecy - warnings for the present and revelation of the future 
8 records. 

OUT @result = 16 
Problemi correlati