2011-12-21 19 views
10

Ho imparato che non sempre odbc_execute() innescare un errore ODBC corretta quando ritorna FALSE (almeno non con il driver Oracle) e non posso pienamente fiducia odbc_error() o odbc_errormsg(). Questa situazione è facile da rilevare quando non si è verificato un errore precedente poiché odbc_error() restituisce una stringa vuota. Tuttavia, quando restituisce qualcosa, non so se appartiene all'ultima operazione fallita o è un errore precedente.trucco per ripristinare odbc_error()

La soluzione più semplice sarebbe quella di ripristinare il odbc_error() e odbc_errormsg() funzioni quando c'è un errore in modo prossimi inviti sarebbero ripartire da zero, ma non sono riuscito a trovare un modo supportato per farlo. Riesci a capire un modo per farlo?

Background: sto migliorando un'applicazione legacy con una classe che incapsula le chiamate al database. Ecco perché ho bisogno di rendere tutto il più generico possibile.

risposta

1

odbc_error a volte diventa confuso. la stringa sql eseguita e il messaggio di errore possono essere diversi. Per evitare ciò, possiamo tenere tutti i sql eseguiti in un array e, al termine di ogni esecuzione, possiamo controllare quali sono i messaggi di errore.

Prima definiamo una classe executedSQL che terrà l'esecuzione informazioni sqls:

class executedSQL 
{ 
    public sql; 
    public result; 
    public error; 
    public message; 
} 

Questa classe conterrà tutte le informazioni di SQL e il loro risultato e restituito i messaggi.

Se usiamo una classe per collegare il db ODBC:

class myODBC 
{ 
    //holds the connection 
    public $connection; 

    //all executed sql string are added to this array as executedSQL object. 
    public $executedSQLs = array(); 


    public function connect() 
    { 
     $this->connection = dbc_connect(" ", " ","") or die(odbc_errormsg()); 
    } 

    public function execute($sql) 
    { 
     $execution = odbc_exec($this->connection, $sql); //execute it 

     //put all the results to executedSQL object 
     $executed = new executedSQL(); 
     $executed->sql = $sql; 
     $executed->result = $execution; 
     $executed->error = odbc_error(); 
     $executed->message = odbc_errormsg(); 

     //push to executedSQLs var. 
     array_push($this->executedSQLs, $executed); 

     return $execution; 
    } 
} 

Se eseguiamo i nostri sqls:

$db = new myODBC(); 

$db->connect(); 

$db->execute("select * from table1"); 
$db->execute("this is gonna be failed sql"); 
$db->execute("select * from table2"); 

print_r($db->executedSQLs); 

Questo sta per stampare tutti sqls e dei loro risultati. A questo punto possiamo vedere lo sql eseguito e il suo messaggio di errore correlato. Quindi letteralmente non stiamo ripristinando odbc_error ma lo rendiamo più chiaro. Se un messaggio di errore viene ripetuto due volte, è più probabile che appartenga al precedente sql eseguito. In questo modo il debug diventa più facile.

+0

Grazie per la risposta. Eppure la tua risposta va bene solo nel caso in cui uno abbia bisogno dei messaggi di errore solo a scopo di debug. In un'applicazione del mondo reale, si dovrebbe essere in grado di fare affidamento sui messaggi di errore per prendere decisioni (comportamento diverso in base all'errore o tradurre il messaggio in un modo che ha senso per l'utente finale). Questo è il motivo per cui avevo bisogno di una risposta approfondita e ho offerto una taglia. –

+0

Il bug della piattaforma radice di cui tratta questa domanda è che 'odbc_errormsg()' può restituire felicemente il messaggio da un'istruzione precedente. Il problema non è quello di rilevare se la query ha esito positivo (è facile), il problema è di essere sicuri che il messaggio di errore non appartiene a una query precedente.A meno che non manchi qualcosa, il tuo codice non fa nulla per risolverlo. –

+0

In questo approccio, siamo in grado di rilevare se un messaggio di arresto da dichiarazione precedente o meno. Ad esempio, diciamo, stiamo eseguendo tre query. Il primo ha successo, il secondo fallisce e restituisce "messaggio di errore 1". E il terzo fallisce anche il ritorno "fail message 1". Con questo approccio, possiamo apprendere che "il messaggio di errore 1" appartiene alla query 2. – isa

2

non è necesary per ripristinare la funzione ho risolto in questo modo:

function foo($sql){ 
    $res = odbc_exec($this->dbconn, $sql); 
    if (odbc_error() and $res===false) { 
     return $this->catchException(odbc_errormsg($this->dbconn)); 

    } 
    return $res; 
} 
+0

Se si decide di rilevare l'eccezione e ignorare l'errore (ad es., Poiché si tratta di una chiave duplicata gestibile dalla logica del codice), il suo messaggio di errore potrebbe essere associato agli errori successivi. Questo è ciò di cui voglio guardarmi. –

+0

Cosa fa '$ this-> catchException()' fare? –

+0

public function catchException ($ odbc_errormsg) { // echo "Funciona en catch
"; $ patron_error = "/ SQL \ d + /"; if (preg_match ($ patron_error, $ odbc_errormsg, $ coincidencias)) { lanciare una nuova eccezione ($ coincidencias [0]. ";". $ Odbc_errormsg); } } Per ora, è utile solo con i messaggi di errore di DB2. Spero di trovare un modo per gestire gli errori di un altro database con il driver php odbc – vteran93

0

errori odbc_errormsg non possono essere azzerati durante gli script. Quindi, in realtà, un modo semplice per separare gli errori odbc_errormsg è assegnare a ogni oggetto obdc_connect un identificatore univoco. Gli esempi mostrano $ db = @ odbc_connect ($ somefile, ......) ma usando nomi casuali o univoci => $ db900 = @ odbc_connect ($ somefile, ......) o $ myuniquename = @ odbc_connect ($ somefile, ......) separerà i messaggi di errore. Quindi usando odbc_errormsg ($ myuniquename) restituirà solo l'errore per quell'id.