Narzędzia użytkownika

Narzędzia witryny


ewdsql

Różnice

Różnice między wybraną wersją a wersją aktualną.

Odnośnik do tego porównania

Both sides previous revision Poprzednia wersja
Nowa wersja
Poprzednia wersja
Nowa wersja Both sides next revision
ewdsql [2014/04/28 14:10]
zozlak
ewdsql [2015/09/06 23:20]
t.zoltak [2. Dbamy o poprawne zakończenie połączenia]
Linia 1: Linia 1:
 ====== Zasady wykonywania zapytań SQL ====== ====== Zasady wykonywania zapytań SQL ======
 +
 +===== 1. Używamy zapytań parametrycznych =====
 +
 +Zapytania do bazy wykonujemy jako **zapytania parametryczne** z użyciem funkcji //​sqlPrepare()//​ i //​sqlExecute()//​ pakietu //​RODBCext//​.
 +  * Pakiet //​RODBCext//​ dostępny jest na githubie [[https://​github.com/​zozlak/​RODBCext]],​ tam też znajduje się instrukcja instalacji.
 +  * Sposób korzystania z funkcji //​sqlPrepare()//​ i //​sqlExecute()//​ opisano w dokumentacji pakietu.
 +  * Dlaczego tak - patrz omówienie niżej.
 +
 +==== Omówienie ====
  
 Zwykły użytkownik nie jest w stanie w bazie nic popsuć, bowiem nie ma praw do zapisu, aktualizacji ani usuwania czegokolwiek. Zwykły użytkownik nie jest w stanie w bazie nic popsuć, bowiem nie ma praw do zapisu, aktualizacji ani usuwania czegokolwiek.
Linia 5: Linia 14:
 Nie oznacza to jednak, że nie należy zwracać uwagi na zabezpieczanie pisanego kodu przed **[[http://​xkcd.com/​327/​|SQL injections]]**. Nie oznacza to jednak, że nie należy zwracać uwagi na zabezpieczanie pisanego kodu przed **[[http://​xkcd.com/​327/​|SQL injections]]**.
  
-Niestety ​pakiet //​RODBC// ​sprawy ​nie ułatwia, bowiem: +Ponieważ ​pakiet //RODBC// nie umożliwia wykonywania ​zapytań parametrycznych (gdzie ​parametry zapytania są oddzielone od jego treści, a więc nie da się zmienić treści zapytania za pomocą jego parametrów),​ stworzone zostałjego rozszerzenie //​**RODBCext**//,​ które udostępnia ​stosowne ​funkcje i należy z niego korzystać. 
-  * ani nie daje możliwości przygotowywania ​zapytań parametrycznych (gdzie o stosowne ​przygotowanie parametrów dba za nas funkcja ​wykonująca zapytanie); + 
-  ​* ani nie udostępnia żadnej ​funkcji do wyparsowywania znaków specjalnych.+===== 2. Dbamy o poprawne zakończenie połączenia ===== 
 + 
 +Jeśli ​funkcja ​operująca na bazie danych sama otwiera połączenie z bazą, powinna też zadbać o jego zamknięcie. **Także wtedy, jeśli w trakcie jej wywołania nastąpi błąd.** Aby to osiągnąć,​ wystarczy zastosować (funkcję on.exit()
 + 
 +<​code>​ 
 +moja_funkcja = function(...){ 
 +  ​P = odbcConnect('​mojeZrodloODBC'​) 
 +  on.exit(odbcClose(P)) 
 +  ... 
 +
 +</​code>​ 
 + 
 +===== 3. Przy zapisie do bazy korzystamy z transakcji ===== 
 + 
 +Jeśli funkcja modyfikuje bazę danych, powinna to robić w transakcji. W takim wypadku wystąpienie błędu podczas działania ​funkcji ​spowoduje, że baza wróci ​do stanu sprzed jej wywołania i nie trzeba będzie cofać tej części zapytań, które zdołały wykonać się przed wystąpieniem błęduAby to osiągnąć stosujemy funkcje //​odbcSetAutoCommit()//​ oraz //​odbcEndTran()//:​ 
 + 
 +<​code>​ 
 +TryCatch( 
 +  { 
 +    P = odbcConnect(zrodloDanychODBC) 
 + 
 +    odbcSetAutoCommit(P,​ FALSE) # rozpocznij transakcję 
 + 
 +    kod modyfikujący bazę 
 +     
 +    odbcEndTran(P,​ TRUE) # zatwierdzamy transakcję 
 +  }, 
 +  error = stop, 
 +  finally = odbcClose(P) 
 +
 +</​code>​ 
  
-W związku z tym zalecane jest: 
-  * konstruowanie zapytań za pomocą //​sprintf()//​ (a nie //paste()// / //​paste0()//​) i korzystanie w //​sprintf()//​ z typów //%d// i //%f// tam, gdzie to możliwe; 
-  * napisanie sobie funkcji wyparsowującej obejmującej minimalnie przypadek<​code>​gsub("'",​ "''",​ wartość)</​code>​i stosowanie jej wszędzie tam, gdzie do zapytania wkładamy argument będący stringiem. 
ewdsql.txt · ostatnio zmienione: 2015/09/06 23:20 przez t.zoltak