wyklad pl sql7


WYKAAD
Z
PROJEKTOWANIA SYSTEMÓW
BAZODANOWYCH
PHP + Oracle
Rozwiązania umożliwiające współpracę Oracle i PHP

Rozwiązania dedykowane tylko dla bazy Oracle

Rozszerzenie PHP OCI8

warstwy abstrakcji bazy danych (ang. database abstraction
layer)  mają za zadanie oddzielić logikę aplikacji od logiki
komunikacji z bazą danych, pozwolić na łączenie się z różnymi
bazami danych (polecenia do bazy danych są kierowane przez
ogólny interfejs, warstwa abstrakcji posiada sterowniki do
różnych baz)

PHP Data Objects (PDO) (interfejs obiektowy o wysokiej
wydajności)

PEAR MDB2

ADOdb
Rozszerzenie OCI8
OCI8

Oferuje wiele możliwości (nie wszystkie są dostępne w innych
narzędziach).

Można

uzyskać dostęp do danych i operować zbiorami wynikowymi

kontrolować kolejne fazy wykonania instrukcji

wykorzystywać bufor połączenia podczas nawiązywania
połączenia z bazą danych

używać zmiennych wiązanych

obsługiwać transakcje

obsługiwać bardzo duże obiekty (LOB)
Połączenie Oracle XE i WampServera

Po uruchomieniu programu
WampServer, klikamy lewym
klawiszem myszy na ikonę
programu na dolnym pasku,
wybieramy z menu opcję PHP,
dalej PHP extensions i zaznaczamy
php_oci8_11g.

Restartujemy serwer.

Uruchamiamy bazę danych.
Zmiany ustawień można także
dokonać bezpośrednio w pliku
konfiguracyjnym php.ini (wystarczy
odkomentarzować odpowiednią linijkę,
czyli usunąć z początku średnik).
5
Aleksandra Stasiak 2014
Uruchomienie przykładów
Aby uruchomić przykłady należy:

utworzyć użytkownika bazy danych o nazwie uzytkownik i haśle
haslo

utworzyć na koncie użytkownika uzytkownik tabele z bazy
BIBLIOTEKA
(Niezbędnik -> Polecenia do generowania tabel (Biblioteka)
(sql))
6
Aleksandra Stasiak 2014
OCI8

Zawiera predefiniowane stałe, funkcje oraz metody
umożliwiające uzyskanie dostępu do baz Oracle Database 12c,
11g, 10g, 9i, 8i. Wspiera język SQL i PL/SQL.

Najczęściej używane funkcje:

oci_connect

oci_parse

oci_execute

oci_fetch

oci_fetch_all

oci_fetch_array

oci_fetch_assoc
7
Aleksandra Stasiak 2014
OCI8

oci_fetch_row

oci_result

oci_error

oci_close

oci_free_statement

oci_commit

oci_rollback

oci_num_rows

oci_define_by_name

oci_bind_by_name
8
Aleksandra Stasiak 2014
$host = 'localhost';
$port='1521';
$nazwa_uslugi = 'xe'; // dbServiceName
$uzytkownik = 'uzytkownik';
$haslo = 'haslo';
$deskryptor = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)
(HOST=".$host.")(PORT=".$port."))
(CONNECT_DATA=(SERVICE_NAME=".$nazwa_uslugi.")))";
$polaczenie = oci_connect($uzytkownik,$haslo,$deskryptor);
if(!$polaczenie)
{
$err = oci_error();
trigger_error('Nie można nawiązać połączenia z bazą danych:'.
htmlentities($err['message'], ENT_QUOTES), E_USER_ERROR);
9
}
Aleksandra Stasiak 2014
$zapytanie = 'SELECT COUNT(id_pracownika) ile FROM pracownicy';
$wyrazenie = oci_parse($polaczenie,$zapytanie);
if (!oci_execute($wyrazenie))
{
$err = oci_error($wyrazenie);
trigger_error('Zapytanie zakończyło się niepowodzeniem: '.
htmlentities($err['message'], ENT_QUOTES), E_USER_ERROR);
}
echo 'Liczba pracowników: ';
oci_fetch($wyrazenie);
$wynik = oci_result($wyrazenie, 'ILE');
echo $wynik;
oci_free_statement($wyrazenie);
if(!oci_close($polaczenie))
{
$err = oci_error();
trigger_error('Problem z zamknięciem połączenia z bazą danych: '.
htmlentities($err['message'], ENT_QUOTES), E_USER_ERROR);
10
Aleksandra Stasiak 2014
} ?>
Przetwarzanie zapytań

Nawiązujemy połączenie z bazą danych.

Przygotowujemy zapytanie do wykonania poprzez użycie funkcji
oci_parse().

Jeśli zapytanie zawiera znaczniki zmiennych wiązanych, dla
wartości, które będą przekazywane przez aplikację w czasie
wykonywania skryptu, to używamy funkcji oci_bind_by_name(),
aby utworzyć powiązanie pomiędzy zmiennymi PHP
a znacznikiem zmiennej wiązanej w Oracle.

Za pomocą funkcji oci_define_by_name() można zdefiniować
zmienne PHP, które będą służyły do pobierania wartości
z poszczególnych kolumn.
Przetwarzanie zapytań

Za pomocą funkcji oci_set_prefetch() można ustalić liczbę
wierszy, które zostaną wybrane wyprzedzeniem (domyślnie 1)
( poprzez ustawienie większej wartości, można zmniejszyć
obciążanie związane z przenoszeniem danych przez sieć,
kosztem większego zużycia pamięci [1])

Wykonujemy zapytanie w bazie danych dzięki funkcji
oci_execute() oraz sprawdzamy czy wykonanie się powiodło.
W przypadku niepowodzenia należy podjąć odpowiednie kroki.
Można pobrać kod i opis błędu dzięki funkcji oci_error().

Pobieramy wyniki zapytania. Można zastosować funkcje typu
oci_fetch_...() umieszczające wyniki w tablicach lub funkcji
oci_fetch() umieszczającej wyniki w buforze wynikowym (skąd
można je pobrać za pomocą funkcji oci_result()).

Zwalniamy zasoby, zamykamy połączenie z bazą.
Przetwarzanie instrukcji DML

Nawiązujemy połączenie z bazą danych.

Przygotowujemy instrukcję do wykonania poprzez użycie funkcji
oci_parse().

Jeśli zapytanie zawiera znaczniki zmiennych wiązanych,
używamy funkcji oci_bind_by_name() tworzącej powiązanie
pomiędzy zmiennymi PHP a znacznikiem zmiennej wiązanej
w Oracle.

Wykonujemy instrukcję w bazie danych dzięki funkcji
oci_execute(). Domyślnie następuje automatyczne
zatwierdzenie wykonanej instrukcji. Można jednak użyć
parametru OCI_DEFAULT, który sprawi, że zmiany nie będą
automatycznie zatwierdzane. Wówczas trzeba samemu
zatwierdzić lub wycofać zmiany w odpowiednim momencie (za
pomocą funkcji oci_commit() / oci_rollback()).
Przetwarzanie instrukcji DML

Sprawdzamy czy wykonanie instrukcji się powiodło.
W przypadku niepowodzenia należy podjąć odpowiednie kroki.

Można odczytać liczbę przetworzonych przez instrukcję wierszy
za pomocą funkcji oci_num_rows().

Jeśli instrukcje nie były zatwierdzane automatycznie, należy je
zatwierdzić. Brak zakończenia transakcji spowoduje jej
wycofanie w momencie zakończenia skryptu lub zamknięcia
połączenia z bazą danych.

Zwalniamy zasoby, zamykamy połączenie z bazą danych.
Nawiązanie połączenia z bazą
$host = 'localhost';
$port='1521';
$nazwa_uslugi = 'xe'; // dbServiceName
$uzytkownik = 'uzytkownik';
$haslo = 'haslo';
$deskryptor = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)
(HOST=".$host.")(PORT=".$port."))
(CONNECT_DATA=(SERVICE_NAME=".$nazwa_uslugi.")))";
$polaczenie = oci_connect($uzytkownik,$haslo,$deskryptor);
if(!$polaczenie)
{
$err = oci_error();
trigger_error('Nie można nawiązać połączenia z bazą danych:'.
htmlentities($err['message'], ENT_QUOTES), E_USER_ERROR);
15
}
Aleksandra Stasiak 2014
Funkcja oci_connect()

Aączy z bazą danych, zwraca identyfikator połączenia.
http://www.php.net/manual/en/function.oci-connect.php

Dostępne są także funkcje oci_new_connect() i oci_pconnect().
http://www.php.net/manual/en/function.oci-pconnect.php
http://www.php.net/manual/en/function.oci-new-connect.php
...
$polaczenie = oci_connect($uzytkownik,$haslo,$deskryptor);
...
16
Aleksandra Stasiak 2014
Funkcja oci_connect()

Trzecim parametrem funkcji oci_connect jest łańcuch znakowy
zawierający nazwę instancji, z którą się łączymy.

Nazwa ta może występować w kilku postaciach

jako tzw.  Easy Connect string

jako Connect Name z pliku tnsnames.ora

oraz jako nazwa lokalnej instancji Oracle

 Easy Connect string jest postaci:
dla Oracle 10g
[//]host_name[:port][/service_name]
od wersji Oracle 11g
[//]host_name[:port][/service_name][:server_type][/instance_name]
17
Aleksandra Stasiak 2014
Nawiązanie połączenia z bazą (dla Oracle 10 XE i 11XE)
$polaczenie = oci_connect('uzytkownik', 'haslo','localhost/XE');
if(!$polaczenie)
{
$err = oci_error();
trigger_error('Nie można nawiązać połączenia z bazą danych:'.
htmlentities($err['message'], ENT_QUOTES), E_USER_ERROR);
}
18
Aleksandra Stasiak 2014
plik funkcje.inc
/* function polacz($host='localhost',$port='1521',$nazwa_uslugi = 'xe',
$uzytkownik='uzytkownik',$haslo='haslo')
{
$deskryptor = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)
(HOST=".$host.")(PORT=".$port."))
(CONNECT_DATA=(SERVICE_NAME=".$nazwa_uslugi.")))";
$polaczenie = oci_connect($uzytkownik,$haslo,$deskryptor);
if(!$polaczenie)
{
$err = oci_error();
trigger_error('Nie można nawiązać połączenia z bazą danych: '.
$err['message'], E_USER_ERROR);
}
return $polaczenie;
} */
function polacz($host ='localhost',$uzytkownik ='uzytkownik',$haslo='haslo')
{
$polaczenie = oci_connect($uzytkownik, $haslo,'localhost/XE', 'UTF8');
if(!$polaczenie)
{
$err = oci_error();
trigger_error('Nie można nawiązać połączenia z bazą danych: '.
$err['message'], E_USER_ERROR);
}
return $polaczenie;
19
}?>
Aleksandra Stasiak 2014
W kolejnych skryptach:
include('funkcje.inc');
$polaczenie=polacz();
...
?>
20
Aleksandra Stasiak 2014
Funkcje łączące

oci_connect() - używa bufora połączeń z bazą danych, dlatego
każde kolejne wywołanie tej funkcji z tymi samymi parametrami,
w czasie wykonania jednego skryptu, będzie zwracało wciąż ten
sam uchwyt połączenia, co za pierwszym jej wywołaniem.
Jest to najczęściej używana z funkcji łączących. Nie używa się
jej wtedy, gdy potrzeba trwałego połączenia z bazą danych lub
gdy istnieje potrzeba izolacji transakcji. Wykonanie
zatwierdzenia lub wycofania dotyczy wszystkich transakcji
otwartych przez dany skrypt.

oci_pconnect() - zwraca uchwyt do trwałego połączenia z bazą
danych.
Trwałe połączenie nie jest zamykane po zakończeniu skryptu.
Korzystając stale z jednego połączenia można wyeliminować
obciążenie związane z otwierania i zamykaniem połączeń.
21
Aleksandra Stasiak 2014
Funkcje łączące
Funkcja oci_pconnect() jest stosowana właściwie tylko wtedy,
gdy aplikacja działa bardzo niewydajnie i nie można sobie
inaczej poradzić. Używając tego typu połączeń trzeba być
ostrożnym (np. problemy z nieusunięciem blokad dostępu do
zasobów).

oci_new_connect() - nie używa bufora połączeń, za każdym
razem zwraca wskaznik do nowego połączenia.
Funkcja ta jest używana, gdy trzeba odseparować od siebie
transakcje. Dzięki temu zabiegowi można zatwierdzać lub
wycofywać lub wycofywać transakcje rozpoczęte tylko w danym
połączeniu.
22
Aleksandra Stasiak 2014
Funkcja oci_close()

Zamyka połączenie z bazą danych.
http://www.php.net/manual/en/function.oci-close.php

Przy zmykaniu połączenia (oraz przy zakończeniu skryptu)
automatycznie wycofywane są otwarte transakcje. Trzeba dbać
o to, aby w odpowiednim momencie pojawiało się zatwierdzenie
transakcji (samodzielne lub automatyczne).
...
if(!oci_close($polaczenie))
{
$err = oci_error();
trigger_error('Problem z zamknięciem połączenia z bazą danych: '.
htmlentities($err['message'], ENT_QUOTES), E_USER_ERROR);
}
23
?>
Aleksandra Stasiak 2014
Funkcja oci_error()

Zwraca informację związaną z ostatnim błędem (jako tablicę
asocjacyjną) lub wartość false, jeśli nie było błędu.
http://www.php.net/manual/en/function.oci-error.php
if(!$polaczenie)
{
$err = oci_error();
trigger_error('Nie można nawiązać połączenia z bazą danych:'.
htmlentities($err['message'], ENT_QUOTES), E_USER_ERROR);
}
24
Aleksandra Stasiak 2014
Funkcja trigger_error() (spoza pakietu oci8)

Pobiera komunikat oraz stałą wskazująca na rodzaj błędu.

W przypadku stałej

E_USER_ERROR - funkcja generuje błąd krytyczny (przerywa
działanie skryptu)

E_USER_WARNING - funkcja generuje ostrzeżenie

E_USER_NOTICE - funkcja generuje uwagę

Funkcję tę można uważać za mechanizm służący do
informowania o nieoczekiwanych zdarzeniach mających
miejsce w czasie wykonywania skryptu
http://pl1.php.net/manual/en/function.trigger-error.php
trigger_error('Nie można nawiązać połączenia z bazą danych:'.
htmlentities($err['message'], ENT_QUOTES), E_USER_ERROR);
25
Aleksandra Stasiak 2014
Funkcja oci_parse()

Pobiera identyfikator połączenia oraz instrukcję SQL lub
PL/SQL. Przygotowuje polecenie do wykonania (ale nie
weryfikuje go). Zwraca uchwyt do instrukcji lub, w przypadku
błędu, wartość FALSE. Nie ma innego sposobu sprawdzenia
czy polecenie jest poprawne, poza próbą jego wykonania.

Polecenia języka SQL występujące jako argument funkcji
oci_parse nie powinny być zakończone średnikiem,
w odróżnieniu od instrukcji języka PL/SQL, które powinny być
nim zakończone.
http://www.php.net/manual/en/function.oci-parse.php
$polaczenie = oci_connect($uzytkownik,$haslo,$deskryptor);
$zapytanie = 'SELECT COUNT(id_pracownika) ile FROM pracownicy';
$wyrazenie = oci_parse($polaczenie,$zapytanie);
26
Aleksandra Stasiak 2014
Funkcja oci_execute()

Pobiera identyfikator zwrócony przez funkcję oci_parse()
i wykonuje w bazie wskazaną instrukcję.

Można, jako drugi parametr, podać tryb wykonania (domyślnie
OCI_COMMIT_ON SUCCESS). W tym trybie zmiany będą
automatycznie zatwierdzane.
http://www.php.net/manual/en/function.oci-execute.php
$wyrazenie = oci_parse($polaczenie,$zapytanie);
if (!oci_execute($wyrazenie))
{
// informacja o błędzie, odpowiednie działania
}
27
Aleksandra Stasiak 2014
Tryby wykonania

Dopuszczalne tryby wykonania:

OCI_COMMIT_ON_SUCCESS (domyślny)  zmiany wykonane
podczas danego połączenia są automatycznie zatwierdzane (jeśli
polecenia zostaną wykonane poprawnie)

OCI_DESCRIBE_ONLY  pozwala na przeglądanie metadanych
przez funkcje takie jak oci_field_name() (zbiór wynikowy nie jest
tworzony, nie powiedzie się zatem pobieranie przez
oci_fetch_array()).

OCI_NO_AUTO_COMMIT  nie zatwierdza zmian automatycznie.
Od wersji PHP 5.3.2 lepiej używać równoważnego
OCI_DEFAULT. Transakcje są automatycznie wycofywane przy
zamykaniu połączenia lub na końcu skryptu (nawet, jeśli żadne
dane nie zostały zmienione). Trzeba samodzielnie dbać
o zatwierdzanie lub odrzucanie poleceń przez oci_commit() lub
oci_rollback().
28
Aleksandra Stasiak 2014
Pobieranie wyników

Funkcje:

oci_fetch_assoc() - zwraca kolejny rekord wyniku jako tablicę
asocjacyjną lub wartość false, gdy nie ma więcej rekordów do
pobrania
http://www.php.net/manual/en/function.oci-fetch-assoc.php

oci_fetch_row() - zwraca kolejny rekord wyniku jako tablicę
numeryczną lub wartość false, gdy nie ma więcej rekordów do
pobrania
http://www.php.net/manual/en/function.oci-fetch-row.php

oci_fetch_arrray() - zwraca kolejny rekord wyniku jako tablicę
(drugi parametr określa rodzaj tablicy) lub wartość false, gdy nie
ma więcej rekordów do pobrania
http://www.php.net/manual/en/function.oci-fetch-array.php
29
Aleksandra Stasiak 2014
Pobieranie wyników

oci_fetch() - pobiera kolejny rekord wyniku i umieszcza go
w wewnętrznym buforze (do pobrania z bufora służy funkcja
oci_result())
http://www.php.net/manual/en/function.oci-fetch.php

oci_fetch_all() - pobiera jednocześnie wszystkie rekordy zwrócone
przez zapytanie i umieszcza je w tablicy zdefiniowanej przez
użytkownika; zwraca liczbę pobranych rekordów lub false, gdy nie
uda się wykonać operacji
http://www.php.net/manual/en/function.oci-fetch-all.php

oci_fetch_object() - zwraca kolejny rekord wyniku jako obiekt lub
wartość false, gdy nie ma więcej rekordów do pobrania
http://www.php.net/manual/en/function.oci-fetch-object.php
30
Aleksandra Stasiak 2014
Wybrane parametry w oci_fetch_array()

W funkcji oci_fetch_array() możemy użyć m. in. następujących
wartości parametrów:

OCI_BOTH (ustawienie domyślne)  funkcja zwraca tablicę, do
której pól możemy się odwoływać zarówno poprzez indeksy
(numerowanie od 0, jak i nazwy / aliasy kolumn / wyrażeń z listy
SELECT) (równoważne OCI_ASSOC + OCI_NUM)

OCI_ASSOC - funkcja zwraca tablicę asocjacyjną

OCI_NUM  funkcja zwraca tablicę zwykłą (numeryczną)

OCI_RETURN_NULLS  funkcja tworzy elementy tablicy dla pól
zawierających wartości NULL (będzie tam przechowywać wartość
NULL (z PHP))
Można łączyć parametry: np. OCI_RETURN_NULLS+OCI_NUM
31
Aleksandra Stasiak 2014
Pobieranie danych - przykład
...
$zapytanie = 'SELECT id_pracownika, imie, nazwisko
FROM pracownicy';
$wyrazenie = oci_parse($polaczenie,$zapytanie);
if (!oci_execute($wyrazenie))
{
\\ informacja o błędzie, odpowiednie działania
}
echo 'Lista pracowników
';
while($rekord=oci_fetch_array($wyrazenie, OCI_ASSOC))
{
echo $rekord['ID_PRACOWNIKA'].' '.$rekord['IMIE'].' '.
$rekord['NAZWISKO'].'
';
}
32
Aleksandra Stasiak 2014
...
Funkcja oci_free_statement()

Zwalnia zasoby związane z kursorem lub instrukcją otrzymaną
z oci_parse().
http://www.php.net/manual/en/function.oci-free-statement.php
$wyrazenie = oci_parse($polaczenie,$zapytanie);
...
oci_free_statement($wyrazenie);
if(!oci_close($polaczenie))
{
...
}
?>
33
Aleksandra Stasiak 2014
Kodowanie znaków

Aby strony prawidłowo się wyświetlały:

musi być ustawione odpowiednie kodowanie strony (nagłówek
HTML)

musi być odpowiednie kodowanie w aplikacji, w której są
tworzone strony (np. Notepad ++)

musi być odpowiednie kodowanie w bazie i odpowiednie
kodowanie w plikach, które zawierają instrukcje wprowadzania
danych

musi być odpowiednie kodowanie w PHP (plik php.ini, parametr
default_charset, np. default_charset = "UTF-8"  trzeba
odkomentować odpowiedni wpis, czyli usunąć z początku średnik)

ustawić odpowiednie kodowanie przy połączeniu, np.
$polaczenie = oci_connect($uzytkownik, $haslo,'localhost/XE', 'UTF8');
34
Aleksandra Stasiak 2014
Funkcja oci_num_rows()

Zwraca liczbę rekordów, na które miało wpływ wykonane
polecenie. Nie zwraca liczby wierszy wybranych przez
zapytanie!!! Dla zapytań zwróci liczbę wierszy przesłanych do
bufora przez funkcje typu oci_fetch_...().
www.php.net/manual/en/function.oci-num-rows.php
35
Aleksandra Stasiak 2014

include('funkcje.inc');
$polaczenie=polacz();
$wyrazenie = oci_parse($polaczenie, 'CREATE TABLE pracownicy_kopia AS
SELECT * FROM pracownicy');
if(!oci_execute($wyrazenie)) { \\ informacja o błędzie, odpowiednie działania }
else {
echo 'Wstawiono '.oci_num_rows($wyrazenie) . ' wierszy.
';
echo 'Typ instrukcji: '.oci_statement_type($wyrazenie).'

'; }
oci_free_statement($wyrazenie);
$wyrazenie = oci_parse($polaczenie, "UPDATE pracownicy_kopia SET pensja=2*pensja
WHERE plec='K'");
if(!oci_execute($wyrazenie)) { \\ informacja o błędzie, odpowiednie działania }
else {
echo 'Zaktualizowano '.oci_num_rows($wyrazenie) . ' wierszy.
';
echo 'Typ instrukcji: '.oci_statement_type($wyrazenie).'

'; }
oci_free_statement($wyrazenie);
$zatwierdzenie = oci_commit($polaczenie);
if (!$zatwierdzenie) { \\ informacja o błędzie, odpowiednie działania }
$wyrazenie = oci_parse($polaczenie, "DELETE FROM pracownicy_kopia WHERE plec='M'");
if(!oci_execute($wyrazenie)) { \\ informacja o błędzie, odpowiednie działania }
else {
echo 'Usunięto '.oci_num_rows($wyrazenie) . ' wierszy.
';
echo 'Typ instrukcji: '.oci_statement_type($wyrazenie).'
'; }
oci_free_statement($wyrazenie);
$zatwierdzenie = oci_commit($polaczenie);
if (!$zatwierdzenie)
{ \\ informacja o błędzie }
$wyrazenie = oci_parse($polaczenie, 'DROP TABLE pracownicy_kopia');
if(!oci_execute($wyrazenie)) { \\ informacja o błędzie, odpowiednie działania }
else { echo 'Usunięto tabelę!';}
oci_free_statement($wyrazenie);
if(!oci_close($polaczenie))
{ \\ informacja o błędzie }
?>
Funkcja oci_statement_type() - zwraca typ instrukcji (ALTER, BEGIN, CALL, CREATE,
DECLARE, DELETE, DROP, INSERT, SELECT, UPDATE, UNKNOWN)
Zatwierdzanie transakcji

oci_commit () zatwierdza transakcję
http://www.php.net/manual/en/function.oci-commit.php

oci_rollback()  wycofuje transakcję
http://www.php.net/manual/en/function.oci-rollback.php
38
Aleksandra Stasiak 2014

include('funkcje.inc');
$polaczenie=polacz();
$zapytanie = 'SELECT * FROM pracownicy';
$wyrazenie = oci_parse($polaczenie,$zapytanie);
if (!oci_execute($wyrazenie, OCI_DESCRIBE_ONLY)) // nie pobieramy danych,
// potrzebujemy tylko informacji o metadanych
{ \\ informacja o błędzie, odpowiednie działania }
echo '';
echo '';
echo '';
echo '';
echo '';
echo '';
echo '';
echo '';
39
// cd. na kolejnym slajdzie
Aleksandra Stasiak 2014
$liczba_kolumn = oci_num_fields($wyrazenie);
for ($i = 1; $i <= $liczba_kolumn; $i++)
{
echo '';
echo '';
echo '';
echo '';
echo '';
echo '';
echo '';
}
echo '
Nazwa kolumnyTypDługośćRozmiarPrecyzja
'.oci_field_name($wyrazenie, $i).''.oci_field_type($wyrazenie, $i).''.oci_field_size($wyrazenie, $i).''.oci_field_precision($wyrazenie, $i).''.oci_field_scale($wyrazenie, $i).'
';
oci_free_statement($wyrazenie);
if(!oci_close($polaczenie))
{ \\ informacja o błędzie,
\\ odpowiednie działania}
?>
Pakiet oci8  informacje o kolumnach

oci_num_fields()  zwraca liczbę kolumn (pól) zwracanych
przez instrukcję

oci_field_name()  zwraca nazwę pola

oci_field_precision()  zwraca precyzję pola

oci_field_scale()  zwraca skalę pola

oci_field_size()  zwraca długość pola

oci_field_type()  zwraca typ danych przypisany do pola

oci_field_is_null()  sprawdza, czy zawartością kolumny
w pobranym wierszu jest wartość NULL
41
Aleksandra Stasiak 2014
Funkcja oci_define_by_name

Funkcja oci_define_by_name() przypisuje kolumnom
wybieranym w zapytaniu zmienne PHP.

Uwaga: w tego typu przypisania, w odwołaniach do kolumn
z listy SELECT często ważna jest wielkość znaków (wielkie
litery).
42
Aleksandra Stasiak 2014
include('funkcje.inc');
$polaczenie=polacz();
$zapytanie = 'SELECT id_pracownika, imie, nazwisko FROM pracownicy';
$wyrazenie = oci_parse($polaczenie,$zapytanie);
oci_define_by_name($wyrazenie, 'ID_PRACOWNIKA', $id);
oci_define_by_name($wyrazenie, 'IMIE', $imie);
oci_define_by_name($wyrazenie, 'NAZWISKO', $nazwisko);
if (!oci_execute($wyrazenie)) {\\ informacja o błędzie, odpowiednie działania }
echo 'Lista pracowników
';
while(oci_fetch($wyrazenie))
{
echo $id.' '.$imie.' '.$nazwisko.'
';
}
if(!oci_close($polaczenie)) { \\ informacja o błędzie, odpowiednie działania }
?>
Funkcja oci_fetch() umieszcza w wewnętrznym buforze tylko następny wiersz ze zbioru
wynikowego i zazwyczaj trzeba ten wiersz pobrać za pomocą funkcji oci_result().
Tutaj zastosowanie funkcji oci_result() jest niepotrzebne, gdyż przed wykonaniem zapytania
zdefiniowaliśmy zmienne PHP do pobierania danych.
43
Aleksandra Stasiak 2014
Pakiet oci8  zmiana hasła użytkownika

oci_password_change()  zmienia hasło użytkownika bazy
danych
oci_password_change($polaczenie, $uzytkownik, $obecne_haslo, $nowe_haslo)
44
Aleksandra Stasiak 2014

$baza= 'localhost/XE';
$uzytkownik= 'uzytkownik';
$obecne_haslo = 'haslo';
$nowe_haslo= 'nowe_haslo';
$polaczenie = oci_connect($uzytkownik, $obecne_haslo, $baza);
if(!$polaczenie) { // informacja o błędzie }
if(oci_password_change($polaczenie, $uzytkownik, $obecne_haslo, $nowe_haslo))
{
echo 'Hasło zmienione.';
}
else
{
echo 'Problem ze zmianą hasła.';
}
if(!oci_close($polaczenie)){ \\ informacja o błędzie}
?>
45
Aleksandra Stasiak 2014

$polaczenie = oci_connect('uzytkownik', 'haslo','localhost/XE');
if(!$polaczenie) { \\informacja o błędach }
echo 'Wersja serwera: '.oci_server_version($polaczenie);
if(!oci_close($polaczenie)){ \\informacja o błędach }
?>
Funkcja oci_server_version()
- zwraca wersję bazy danych, z którą jesteśmy połączeni.
46
Aleksandra Stasiak 2014
Funkcja oci_set_prefetch()

Funkcja oci_set_prefetch() pozwala na ustawienie liczby
wierszy, które będą buforowane w przypadku pomyślnie
wykonanego zapytania (pobierane w czasie jednego żądania
sieciowego  network request). Domyślnie jest to jeden wiersz.

Jeśli zapytania pobierają bardzo duże liczby wierszy
zwiększenie tego parametru może znacząco poprawić
wydajność.

Funkcję oci_set_prefetch() należy wykonać przed wywołaniem
funkcji oci_execute().

Najważniejsze jest dobranie takiej wartości parametru, aby była
ona odpowiednia zarówno dla sieci jak i dla bazy.
47
Aleksandra Stasiak 2014
Funkcja oci_set_prefetch()

W przypadku zapytań zwracających bardzo wiele wierszy dla
wydajności całego systemu może być lepiej, aby wiersze trafiały
do bazy w kilku  kawałkach (czyli, żeby wartość parametru była
mniejsza niż liczba wierszy). Wówczas, w czasie, gdy PHP
będzie przetwarzało bieżącą partię wierszy, baza będzie mogła
obsługiwać żądania innych użytkowników.
$wyrazenie = oci_parse($polaczenie,$zapytanie);
oci_set_prefetch($wyrazenie, 3);
if (!oci_execute($wyrazenie)) { ...
}
...
48
Aleksandra Stasiak 2014
Używanie zmiennych wiązanych

Pozwala na budowanie wydajnych aplikacji: instrukcja zostaje
przeanalizowana raz, a wykorzystywana wielokrotnie

Gdy polecenie zostanie przeanalizowane, jest współdzielone
w buforze. Drzewo przetwarzania i plan wykonania mogą być
wielokrotnie użyte przez wiele aplikacji.

Jeśli używamy zmiennych wiązanych, to mimo zmiany ich
wartości, wykorzystywane będą te same współdzielone
informacje (te same metadane) Unikamy zatem wielokrotnego
parsowania tej samej instrukcji i wielokrotnego wiązania.

Wiązanie zmniejsza możliwość powstania SQL Injection, gdyż
dane związane z wiązanymi zmiennymi nigdy nie są traktowane
jako część instrukcji języka SQL. Nie trzeba zatem stosować
zabiegów związanych w dopisywaniem / usuwaniem apostrofów
i cudzysłowów.
49
Aleksandra Stasiak 2014
Zamiast
...
$tabela_zawodow=array('BIBLIOTEKARZ', 'INFORMATYK', 'SEKRETARKA');
foreach($tabela_zawodow as $zawod)
{
$zapytanie = 'SELECT id_pracownika, imie, nazwisko
FROM pracownicy
WHERE zawod=\''.$zawod.'\'';
$wyrazenie = oci_parse($polaczenie,$zapytanie);
if (!oci_execute($wyrazenie)) { \\ informacja o błędzie, odpowiednie działania
echo 'Lista pracowników o zawodzie: '.$zawod.'
';
while($rekord=oci_fetch_array($wyrazenie, OCI_ASSOC))
{
echo $rekord['ID_PRACOWNIKA'].' '
.$rekord['IMIE'].' '.$rekord['NAZWISKO'].'
';
}
echo '
';
}
oci_free_statement($wyrazenie);
if(!oci_close($polaczenie))
50
{ \\informacja o błędzie, ... }
Aleksandra Stasiak 2014
?>
Możemy zastosować
...
$tabela_zawodow=array('BIBLIOTEKARZ', 'INFORMATYK', 'SEKRETARKA');
$zapytanie = 'SELECT id_pracownika, imie, nazwisko
FROM pracownicy WHERE zawod=:zawod';
$wyrazenie = oci_parse($polaczenie,$zapytanie);
oci_bind_by_name($wyrazenie, ':zawod', $zawod,25); //zawod  VARCHAR2(25)
foreach($tabela_zawodow as $zawod)
{
if (!oci_execute($wyrazenie)) { \\informacja o błędzie, odpowiednie działania
echo 'Lista pracowników o zawodzie: '.$zawod.'
';
while($rekord=oci_fetch_array($wyrazenie, OCI_ASSOC))
{
echo $rekord['ID_PRACOWNIKA'].' '.$rekord['IMIE'].' '.
$rekord['NAZWISKO'].'
';
}
echo '
';
}
oci_free_statement($wyrazenie);
51
if(!oci_close($polaczenie)) { \\informacja o błędzie, odpowiednie działania }?>
Aleksandra Stasiak 2014
Funkcja oci_bind_by_name()

Pozwala na utworzenie połączenia między zmienną skryptu
PHP, a znacznikiem zmiennej wiązanej Oracle.
http://www.php.net/manual/en/function.oci-bind-by-name.php

Zmienne wiązane dzielą się na zmienne typu IN (dla wartości
przekazywanych do bazy danych), typu OUT (które są
zwracane do PHP) oraz IN OUT. O tym jaki typ ma zmienna
wiązana decyduje się w czasie wykonania programu.

Dla zmiennych typu OUT należy podać maksymalną długość,
tak, by PHP mogło przydzielić odpowiednio dużo pamięci, aby
przechować zwróconą wartość.
52
Aleksandra Stasiak 2014
Funkcja oci_bind_by_name()
*

Jeśli w parametrze oznaczającym maksymalną długość
wpiszemy wartość -1, wtedy funkcja ustawi maksymalną
długość na długość bieżącej wartości zmiennej (zmienna ta
musi istnieć i mieć przypisaną wartość zanim wykonamy
oci_bind_by_name).

W przypadku zmiennych typu IN także zaleca się ustawiać
maksymalną długość, jeśli dana instrukcja będzie wykonywana
wielokrotnie z różnymi wartościami zmiennych PHP (Oracle
może obciąć dane do długości pierwotnej wartości zmiennej
PHP). Jeśli nie znamy maksymalnej długości, wtedy trzeba
wywołać ponownie oci_bind_by_name z bieżącą długością,
przed każdym wykonaniem oci_execute.

Podanie przy wiązaniu zbyt dużej długości (na wszelki
wypadek) również nie jest zalecane.
53
Aleksandra Stasiak 2014
Funkcja oci_bind_by_name()

W przypadku instrukcji, która jest przetwarzana wielokrotnie,
wartości wiązane, które nigdy się nie zmieniają mogą
uniemożliwić optymalizatorowi Oracle wybranie najlepszego
planu wykonania.

W przypadku długich instrukcji, które są rzadko wykonywane
ponownie wprowadzenie zmiennych wiązanych może nie
przynieść żadnego pożytku.

Mimo wszystko wiązanie może być bezpieczniejsze niż
sklejanie nieprzefiltrowanych (względem niebezpiecznych dla
bazy znaków) łańcuchów pochodzących od użytkownika
w jedną instrukcję SQL.
54
Aleksandra Stasiak 2014
Podsumowując
Wiązanie zmiennych

jest zalecane wszędzie tam, gdzie ma to sens

może poprawić wydajność aplikacji

sprawia, że program jest bardziej elastyczny

pozwala na bezpieczniejsze operowanie instrukcjami języka
SQL oraz blokami języka PL/SQL, które wykorzystują dane
dostarczane przez użytkowników w czasie działania aplikacji
(skryptu)
55
Aleksandra Stasiak 2014
$polaczenie = oci_connect('uzytkownik', 'haslo','localhost/XE', 'UTF8');
if(!$polaczenie) { \\informacja o błędzie }
$wyrazenie = oci_parse($polaczenie,
'INSERT INTO autorzy VALUES(:id, :imie, :nazwisko)');
$id = 85;
$imie='Larry';
$nazwisko='Ullman';
oci_bind_by_name($wyrazenie, ':id', $id);
oci_bind_by_name($wyrazenie, ':imie', $imie);
oci_bind_by_name($wyrazenie, ':nazwisko', $nazwisko);
if(oci_execute($wyrazenie))
{ echo 'Wstawiono wiersz!';}
else
{echo 'Problem ze wstawianiem!';}
oci_free_statement($wyrazenie);
if(!oci_close($polaczenie)) { \\informacja o błędzie }
56
Aleksandra Stasiak 2014
?>

include('funkcje.inc');
$polaczenie=polacz();
if(!$polaczenie) { //informacja o błędzie, podjęcie dalszych działań }
$autorzy = array(
array("id_autora" => 67, "imie" => 'Henryk', "nazwisko"=>'Sienkiewicz'),
array("id_autora" => 68, "imie" => 'Maria', "nazwisko"=>'Konopnicka'),
array("id_autora" => 69, "imie" => 'Bolesław', "nazwisko"=>'Prus')
);
$wyrazenie = oci_parse($polaczenie,'INSERT INTO autorzy VALUES
(:id, :imie, :nazwisko)');
foreach($autorzy as $wartosc)
{
oci_bind_by_name($wyrazenie, ':id', $wartosc['id_autora'], 3);
oci_bind_by_name($wyrazenie, ':imie', $wartosc['imie'], 30);
oci_bind_by_name($wyrazenie, ':nazwisko', $wartosc['nazwisko'], 30);
// cd na kolejnym slajdzie 57
Aleksandra Stasiak 2014
if (!oci_execute($wyrazenie,OCI_DEFAULT)) // bez automatycznego zatwierdzania
{//informacja o błędzie, podjęcie dalszych działań }
else
{
echo 'Wiersz został wstawiony!
';
}
}
oci_commit($polaczenie);
oci_free_statement($wyrazenie);
if(!oci_close($polaczenie))
{ //informacja o błędzie, podjęcie dalszych działań }
?>
58
Aleksandra Stasiak 2014

CREATE TABLE test(
liczba NUMBER(3) NOT NULL);
include('funkcje.inc');
$polaczenie=polacz();
if(!$polaczenie) { // informacja o błędzie, podjęcie dalszych działań}
$liczby = array(1,6,7,199,200);
$wyrazenie = oci_parse($polaczenie,'INSERT INTO test VALUES(:liczba)');
oci_bind_by_name($wyrazenie, ':liczba', $wartosc);
foreach($liczby as $wartosc)
{
if (!oci_execute($wyrazenie,OCI_DEFAULT))
{ // informacja o błędzie, podjęcie dalszych działań}
else
{
echo 'Wiersz został wstawiony!
';
}
}
oci_commit($polaczenie);
oci_free_statement($wyrazenie);
if(!oci_close($polaczenie)){ // informacja o błędzie, podjęcie dalszych działań}
59
?>
Aleksandra Stasiak 2014
Plik pobieranie_funkcje.php
function pracownicy_zawod($zawod)
{
$polaczenie=polacz();
$zapytanie = 'SELECT id_pracownika, imie, nazwisko FROM pracownicy
WHERE zawod=:zawod';
$wyrazenie = oci_parse($polaczenie,$zapytanie);
oci_bind_by_name($wyrazenie, ':zawod', $zawod,25);
if (!oci_execute($wyrazenie)) {
$err = oci_error($wyrazenie);
trigger_error('Zapytanie zakończyło się niepowodzeniem: '. $err['message'],
E_USER_WARNING);
return false; }
if($liczba_zwroconych_wierszy=oci_fetch_all($wyrazenie, $tablica_pracownikow))
{ return array($liczba_zwroconych_wierszy, $tablica_pracownikow); }
else
{ return false; }
60
}
Aleksandra Stasiak 2014

include("pobieranie_funkcje.php");
$zawod='BIBLIOTEKARZ';
if(list($liczba_znalezionych_wierszy, $tablica_pracownikow)=
pracownicy_zawod($zawod))
{
if($liczba_znalezionych_wierszy>0)
{
echo 'Liczba pracowników: '.$liczba_znalezionych_wierszy.'

';
echo '';
echo '';
foreach($tablica_pracownikow as $klucz => $pracownik)
{
echo '';
}
echo '';
// cd na kolejnym slajdzie
61
Aleksandra Stasiak 2014
for($i=0;$i<$liczba_znalezionych_wierszy;$i++)
{
echo '';
foreach($tablica_pracownikow as $pracownik)
{
echo '';
}
echo '';
}
}
else
{
echo 'Brak pracowników o takim zawodzie';
}
}
else
{
echo 'Problem z wykonaniem zapytania';
}
62
?>
Aleksandra Stasiak 2014
Po stronie aplikacji czy po stronie bazy?

Po której stronie lepiej umieścić logikę biznesową aplikacji
pisanej w PHP / Oracle: po stronie PHP czy po stronie bazy?
Według [1]:

 lepszym rozwiązaniem jest przeniesienie procesu przetwarzania
danych do samych danych od przenoszenia danych do procesu ich
przetwarzania

 w większości przypadków lepszym rozwiązaniem będzie
implementacja kluczowej logiki biznesowej aplikacji wewnątrz bazy
danych, aby przetwarzanie danych zachodziło na serwerze bazy
danych, a nie serwerze WWW/PHP. W ten sposób można znacznie
usprawnić wydajność aplikacji oraz możliwość jej skalowalności.

w praktyce nie zawsze jest możliwa implementacja logiki biznesowej
aplikacji całkowicie wewnątrz bazy danych lub całkowicie w PHP.
Dlatego też zazwyczaj stosowane będzie połączenie obu
63
wymienionych technik
Aleksandra Stasiak 2014
Po stronie aplikacji czy po stronie bazy?

Zaleca się implementować logikę biznesową po stronie bazy,
poza sytuacjami,

gdy tworzymy oprogramowanie, które ma być przenośne
(rozwiązanie ma być pózniej używane z inną bazą niż Oracle)

gdy przy implementacji potrzeba skorzystać ze sprawdzonych już
w działaniu fragmentów kodu, stosowanych już w innych
aplikacjach

kiedy serwer bazy danych jest bardzo obciążony
64
Aleksandra Stasiak 2014
Zalety
Zalety wykonywania większości operacji przetwarzania danych
po stronie bazy (na podstawie [1]):

poprawienie wydajności

zwiększenie możliwości skalowalności (*)

zwiększenie poziomu bezpieczeństwa

możliwość utworzenia ogólnego zestawu podprogramów, które
mogą być współdzielone przez wiele aplikacji

zmniejszenie obciążenia sieci (przesyłamy tylko produkt końcowy,
a nie duże ilości danych)

scentralizowana kontrola nad logiką biznesową (=> łatwiejsza
obsługa i konserwacja)
 Jako skalowalny można określić system, który stosunkowo łatwo można
uprościć lub rozbudować, w zależności od potrzeb. Wikipedia
65
Aleksandra Stasiak 2014
Zalety

Oracle ma wyjątkowo użyteczne narzędzia pozwalające na
implementację prowadzącą do efektywnych operacji
przetwarzania danych

wbudowane narzędzia Oracle (SQL, PL/SQL) oraz bazy danych
ściśle ze sobą współpracują, co daje lepszą wydajność podczas
przetwarzania danych z bazy

można efektywnie chronić dane aplikacji przed nieupoważnionym
dostępem, jednocześnie udostępniając uprawnionym
użytkownikom łatwy dostęp do danych
66
Aleksandra Stasiak 2014
Jak wykorzystać bazę?
Do implementowania logiki biznesowej aplikacji wewnątrz bazy
danych możemy użyć

poleceń języka SQL

widoków
zalety:

ukrywanie złożoności danych,

możliwość wykorzystania istniejących zapytań,

dodatkowa warstwa bezpieczeństwa,

możliwość modyfikowania jedynie widoków, a nie aplikacji przy
zmianie struktur bazy
67
Aleksandra Stasiak 2014
Jak wykorzystać bazę?

podprogramów składowanych
zalety:

efektywność

poprawienie wydajności (bo są przechowywane w bazie w postaci
skompilowanej, po wywołaniu są wczytywane do pamięci
współdzielonej)

zmniejszenie obciążenie sieciowego (jedno pojedyncze wywołanie
sieciowe może uruchomić wiele instrukcji języka SQL)

możliwość współdzielenia podprogramów przez wiele aplikacji

łatwa obsługa i konserwacja

warstwa bezpieczeństwa (użytkownik może mieć prawo do
uruchamiania podprogramu zamiast do tabel)

68
wyzwalaczy
Aleksandra Stasiak 2014
CREATE OR REPLACE FUNCTION rok_urodzenia
(p_id pracownicy.id_pracownika%TYPE) RETURN NUMBER IS
z_rok NUMBER(4);
BEGIN
SELECT TO_NUMBER(TO_CHAR(data_urodzenia, 'YYYY'))
INTO z_rok
FROM pracownicy
WHERE id_pracownika=p_id;
RETURN z_rok;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN 0;
END;
/
include('funkcje.inc');
$polaczenie=polacz();
if(!$polaczenie) { // informacja o błędzie, podjęcie dalszych działań}
$id=4;
$zapytanie = 'BEGIN :rok:=rok_urodzenia(:id); END;';
$wyrazenie = oci_parse($polaczenie,$zapytanie);
// cd na kolejnym slajdzie
69
Aleksandra Stasiak 2014
oci_bind_by_name($wyrazenie, ':id', $id);
oci_bind_by_name($wyrazenie, ':rok', $rok,4);
if (!oci_execute($wyrazenie))
{ //informacja o błędzie, podjęcie dalszych działań }
if($rok==0)
{
echo 'Nie ma osoby o takim identyfikatorze!';
}
else
{
echo "Rok urodzenia pracownika o identyfikatorze $id: $rok";
}
oci_free_statement($wyrazenie);
if(!oci_close($polaczenie))
{ // informacja o błędzie, podjęcie dalszych działań}
?>
70
Aleksandra Stasiak 2014
CREATE OR REPLACE PROCEDURE czytelnicy_plec_data
(p_plec IN czytelnicy.plec%TYPE, p_rok_zapisania IN NUMBER,
p_suma_kar OUT NUMBER, p_liczba_osob OUT NUMBER) IS
CURSOR k_czytelnicy IS SELECT id_czytelnika, imie1, nazwisko
FROM czytelnicy
WHERE plec=p_plec AND TO_NUMBER(TO_CHAR(data_zapisania, 'YYYY'))=p_rok_zapisania
ORDER BY nazwisko, imie1;
z_liczba_osob NUMBER:=0;
z_suma_kar NUMBER:=0;
z_kara NUMBER:=0;
BEGIN
FOR z_rekord IN k_czytelnicy LOOP
z_kara:=0;
z_liczba_osob:=z_liczba_osob+1;
SELECT SUM(kara)
INTO z_kara
FROM wypozyczenia
WHERE id_czytelnika=z_rekord.id_czytelnika;
IF z_kara IS NULL THEN
z_kara:=0;
END IF;
z_suma_kar:=z_suma_kar+z_kara;
END LOOP;
p_suma_kar:=z_suma_kar;
p_liczba_osob:=z_liczba_osob;
END;
/
71
Aleksandra Stasiak 2014
include('funkcje.inc');
$polaczenie=polacz();
if(!$polaczenie) { //informacja o błędzie, podjęcie dalszych działań }
$plec='K';
$rok=2000;
$zapytanie = 'BEGIN czytelnicy_plec_data(:plec, :rok, :suma_kar, :liczba_osob);
END;';
$wyrazenie = oci_parse($polaczenie,$zapytanie);
oci_bind_by_name($wyrazenie, ':plec', $plec);
oci_bind_by_name($wyrazenie, ':rok', $rok);
oci_bind_by_name($wyrazenie, ':suma_kar', $suma_kar, 4);
oci_bind_by_name($wyrazenie, ':liczba_osob', $liczba_osob, 4);
for($rok=1990;$rok<2015;$rok++)
{
if (!oci_execute($wyrazenie))
{ //informacja o błędzie, podjęcie dalszych działań }
// cd na kolejnym slajdzie
72
Aleksandra Stasiak 2014
echo 'Rok: '.$rok.' Liczba osób: '.$liczba_osob;
echo ' Suma kar: '.$suma_kar.'

';
}
oci_free_statement($wyrazenie);
if(!oci_close($polaczenie)) //informacja o błędzie, podjęcie dalszych działań
?>
73
Aleksandra Stasiak 2014
Aby uruchomić dalsze przykłady należy

Na koncie użytkownika uzytkownik utworzyć tabelę USERS.

Utworzyć sekwencję USER_SEQ.

Wstawić dane do tabeli wykonując skrypty 1.PHP i 2.PHP

Utworzyć na koncie użytkownika USER funkcję LOGOWANIE
(w języku PL/SQL).
Polecenia tworzące tabelę, sekwencję i funkcję znajdują się
w pliku tekstowym
74
Aleksandra Stasiak 2014
CREATE OR REPLACE FUNCTION logowanie
(z_login IN VARCHAR2, z_haslo IN VARCHAR2, z_czy_admin OUT NUMBER, z_komunikat OUT
VARCHAR2)
RETURN NUMBER IS
BEGIN
BEGIN
SELECT czy_admin
INTO z_czy_admin
FROM users
WHERE login=z_login AND haslo=z_haslo;
EXCEPTION
WHEN NO_DATA_FOUND THEN
z_komunikat:='Niepoprawne dane';
RETURN 0;
END;
RETURN 1;
END;
/
75
Aleksandra Stasiak 2014
...
$llogin=$_POST['login'];
$hhaslo=md5($_POST['haslo']); // kodujemy hasło
$polaczenie=polacz() or die ("Nie mogę się połączyć");
$zapytanie="BEGIN :wynik:=logowanie(:login, :haslo,:czy_admin, :komunikat);END;";
$wyrazenie=oci_parse($polaczenie,$zapytanie);
oci_bind_by_name($wyrazenie, ':wynik', $wynik, 1);
oci_bind_by_name($wyrazenie, ':login', $llogin, 30);
oci_bind_by_name($wyrazenie, ':haslo', $hhaslo, 35);
oci_bind_by_name($wyrazenie, ':czy_admin', $czy_admin, 1);
oci_bind_by_name($wyrazenie, ':komunikat', $komunikat, 100);
if (!oci_execute($wyrazenie)) {//informacja o błędzie, podjęcie dalszych działań}
if($wynik) {
$_SESSION['valid_user']=$llogin;
if($czy_admin==1)
$_SESSION['is_admin']=1;
}
76
... ?>
Aleksandra Stasiak 2014
PDO

Aby uruchomić przykład z użyciem interfejsu PDO należy
odkomentarzować w pliku php.ini linię
extension=php_pdo_oci.dll
77
Aleksandra Stasiak 2014
$uzytkownik = 'uzytkownik';
$haslo = 'haslo';
try {
$polaczenie= new PDO('oci:host=localhost; dbname=XE;charset=UTF8',
$uzytkownik, $haslo);
$wynik=$polaczenie-> query ('SELECT imie, nazwisko FROM pracownicy');
if($wynik)
{
foreach ($wynik as $wiersz)
{
echo 'Imię: '. $wiersz['IMIE'].', nazwisko: '.$wiersz['NAZWISKO'].'
';
}
}
$wynik->closeCursor();
$polaczenie=null;
} catch (PDOException $w) { die('Błąd!'.$w->getMessage()); }
?>
78
Aleksandra Stasiak 2014
Współdzielone konta bazy danych

W aplikacjach internetowych opartych na bazie danych bardzo
często stosowanym rozwiązaniem jest udostępnianie wszystkim
użytkownikom tego samego konta (schematu) bazy danych.

Oczywiście kontem tym nigdy nie jest konto użytkownika
systemowego bazy danych!!!

Jest to rozwiązanie wystarczające, ale nie najlepsze z punktu
widzenia bezpieczeństwa, gdyż osoba łączącą się z danym
schematem uzyskuje dostęp do wszystkich obiektów bazy
danych, które do tego schematu należą.
79
Aleksandra Stasiak 2014
Dwa schematy: jeden z zasobami, drugi do połączeń
(na podstawie [1])

Rozważmy sytuację, w której użytkownik nie powinien mieć
prawa wykonywania instrukcji DML.

Można wówczas np. utworzyć dodatkowy schemat bazy
danych, który będzie używany jedynie podczas nawiązywania
połączeń i będzie miał tylko prawo SELECT w stosunku do
obiektów podstawowego schematu do których aplikacja będzie
wykonywała zapytania.

Zawsze trzeba pamiętać o zasadzie najmniejszych uprawnień:
użytkownik powinien mieć najmniejsze uprawnienia, które
pozwolą mu na wykonywanie jego zadań.

W najprostszej sytuacji wystarczy dla schematu podstawowego
rola CONNECT (zawierająca jedynie przywilej CREATE
SESSION) oraz prawa SELECT do wybranych tabel.
Schematowi podstawowemu można wtedy odebrać rolę
80
Aleksandra Stasiak 2014
CONNECT.
Trzy schematy (na podstawie [1])

Poprzednie rozwiązanie ma ten minus, że każdy, kto będzie
mógł się połączyć z bazą, będzie miał prawo SELECT do tabeli
zawierającej użytkowników i ich hasła.

Pomysł: utworzenie trzeciego schematu (pośrednika pomiędzy
schematem do połączeń, a schematem podstawowym)
zawierającego procedury składowane, pozwalające na
bezpieczny dostęp do danych.

Schemat służący do połączeń ma tylko prawa wykonywania
procedur składowanych, użytkownicy mają dostęp do danych
tylko poprzez podprogramy, schemat z podprogramami nie ma
prawa CONNECT. Dostarczamy użytkownikowi funkcję, która
czyta jedynie wiersz z jego danymi uwierzytelniającymi.
81
Aleksandra Stasiak 2014
Przechowywanie informacji o zalogowanym użytkowniku

Informacje takie można przechowywać w

zmiennych sesyjnych PHP

zmiennych pakietowych PL/SQL
82
Aleksandra Stasiak 2014
Wykorzystanie pakietów  pomysł z [1]

Jeden pakiet przechowuje informacje o użytkowniku, drugi
operuje zmiennymi pakietu pierwszego (ustawia je lub
odczytuje), schemat łączący ma prawo EXECUTE jedynie do
pakietu drugiego.

Uprawnienie EXECUTE w stosunku do pakietu w jakimś
schemacie pozwala użytkownikowi połączyć się z bazą danych
za pomocą tego schematu, umożliwia wykonywanie wszystkich
publicznych podprogramów zawartych w pakiecie oraz dostęp
do wszystkich zmiennych publicznych pakietu.

Funkcje z pakietów ustawiające i odczytujące informacje
o zalogowanym użytkowniku mogą być także użyte przy
tworzeniu perspektyw pokazujących wiersze związane tylko
z danym użytkownikiem.
83
Aleksandra Stasiak 2014
Bibliografia
1) Yuli Vasiliev,  PHP i Oracle. Tworzenie aplikacji webowych: od
przetwarzania danych po Ajaksa , Helion 2009
2) http://www.php.net/
3) http://pl.wikibooks.org/wiki/PHP/Biblioteka_PDO
84
Aleksandra Stasiak 2014


Wyszukiwarka

Podobne podstrony:
WYKŁAD PL
WYKŁAD PL
WYKŁAD PL
wyklad pl sql8
Wyklad 7 Nieparametryczne metody statystyczne PL [tryb zgodności]
notatek pl wyklad 3 model krazenia odpadow wyklad
04 PL wyklad
notatek pl zarzadzanie jakoscia dr janusz niezgoda wyklady
notatek pl chemia budowlana wyklady
Przestrzenie zakrzywione(Feynmana wyklad 44 z tomu drugiego)(osiolek pl)
notatek pl wyklad 5 planowanie przestrzenne wyklad
02 PL wyklad
562 pl wyklady z dnia lutego 11
Wyklad 8 iloczyn rozpuszczalnosci,koloidy antastic pl
notatek pl wyklad 7 odpady torfowe weglowe wyklad
wyklad 9 Wnioskowanie o proporcjach PL [tryb zgodności]
notatek pl teoria polityki wyklady

więcej podobnych podstron

'.$klucz.'
'.$pracownik[$i].'