2011-12-21 9 views
10

Nauczyłem się, że nie zawsze odbc_execute() wywołać odpowiedni błąd ODBC kiedy wraca FALSE (przynajmniej nie ze sterownikiem Oracle) i nie mogę w pełni zaufać odbc_error() lub odbc_errormsg(). Ta sytuacja jest łatwa do wykrycia, gdy nie wystąpił poprzedni błąd, ponieważ odbc_error() zwraca pusty ciąg znaków. Jednakże, gdy zwraca coś nie wiem, czy należy do ostatniej nieudanej operacji lub jest pozostać z poprzedniego błędu.Sztuczka zresetować odbc_error()

Najprostszym rozwiązaniem byłoby zresetowaćodbc_error()odbc_errormsg() i funkcje, gdy wystąpi błąd więc kolejne rozmowy będzie zaczynać od zera, ale nie mogłem znaleźć obsługiwanego sposób, aby to zrobić. Czy potrafisz wymyślić sposób na zrobienie tego?

Tło: Rozszerzam starszą aplikację o klasę, która hermetyzuje wywołania bazy danych. Dlatego muszę zrobić wszystko tak ogólne, jak to tylko możliwe.

Odpowiedz

1

odbc_error czasami staje się zagmatwany. wykonany ciąg sql i komunikat o błędzie mogą być inne. Aby temu zapobiec, możemy zatrzymać wszystkie wykonane sqls w tablicy i po zakończeniu wszystkich działań możemy sprawdzić, jakie są komunikaty o błędach.

Najpierw zdefiniujmy klasę executedSQL który mocuje wykonywane zapytania SQL informacje:

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

Ta klasa będzie posiadać wszystkie sql informacji i ich wynik i wrócił wiadomości.

Jeśli użyjemy klasy połączyć 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; 
    } 
} 

Jeśli wykonujemy nasze zapytania SQL:

$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); 

To będzie drukować wszystkie zapytania SQL i ich rezultaty. W tym momencie możemy zobaczyć wykonany sql i związany z nim komunikat o błędzie. Więc dosłownie nie resetujemy odbc_error, ale robimy to wyraźniej. Jeśli komunikat o błędzie jest powtarzany dwa razy, jest bardziej prawdopodobne, że należy do wcześniej wykonanego sql. W ten sposób debugowanie staje się łatwiejsze.

+0

Dzięki za odpowiedź. Jednak twoja odpowiedź jest tylko dla przypadku, że potrzebujesz komunikatów o błędach tylko do celów debugowania. W aplikacji w świecie rzeczywistym można polegać na komunikatach o błędach, aby podejmować decyzje (inne zachowanie w zależności od błędu lub przetłumaczyć wiadomość w sposób, który ma sens dla użytkownika końcowego). Z tego powodu potrzebowałem dokładnej odpowiedzi i zaoferowałem nagrodę. –

+0

Błąd platformy głównej, o który chodzi w tym pytaniu, polega na tym, że 'odbc_errormsg()' może z powodzeniem zwrócić komunikat z poprzedniej instrukcji. Problemem nie jest wykrycie, czy zapytanie się powiedzie (to proste), problem polega na upewnieniu się, że komunikat o błędzie nie należy do poprzedniego zapytania.O ile czegoś nie brakuje, twój kod nie robi nic, aby to rozwiązać. –

+0

W tym podejściu możemy wykryć, czy wiadomość arror z poprzedniej instrukcji, czy nie. Na przykład powiedzmy, że wykonujemy trzy zapytania. Pierwszy z nich się powiódł, drugi się nie powiedzie i zwraca "komunikat o błędzie 1". I trzecia także nie zwraca "wiadomość o błędzie 1". Dzięki temu podejściu możemy się dowiedzieć, że "komunikat o błędzie 1" należy do zapytania 2. – isa

2

to nie necesary zresetować funkcję I rozwiązać w ten sposób:

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

Jeśli postanowisz przechwycić wyjątek i zignorować błąd (np. Ponieważ jest to zduplikowany klucz, który może obsłużyć logika kodu), jego komunikat o błędzie może zostać skojarzony z następnymi błędami. Właśnie tego chcę się ochronić. –

+0

Co robi '$ this-> catchException()'? –

+0

funkcja publiczna catchException ($ odbc_errormsg) { // echo "Funciona en catch
"; $ patron_error = "/ SQL \ d + /"; if (preg_match ($ patron_error, $ odbc_errormsg, $ coincidencias)) { throw new Exception ($ coincidencias [0]. ";". $ Odbc_errormsg); } } Na razie jest to przydatne tylko w przypadku komunikatów o błędach DB2. Mam nadzieję znaleźć sposób na zarządzanie błędami innych baz danych za pomocą sterownika php odbc – vteran93

0

błędy odbc_errormsg nie mogą zostać wyzerowane w skrypcie. Tak więc w rzeczywistości prostym sposobem na oddzielenie błędów odbc_errormsg jest przypisanie każdemu obdc_connect unikalnego identyfikatora. Przykłady pokazują $ db = @ odbc_connect ($ somefile, ......), ale używając losowych lub unikalnych nazw => $ db900 = @ odbc_connect ($ somefile, ......) lub $ myuniquename = @ odbc_connect ($ somefile, ......) oddzieli komunikaty o błędach. Następnie użycie odbc_errormsg ($ myuniquename) zwróci błąd tylko dla tego id.