Bases de Dados PostgreSQL e Php Transacções Joins, agregações, vistas P. Serendero, 2011 1
PostgreSQLe Php: transacções Os comandos SQL utilizados nas aulas práticas e mostrados aqui foram feitos num interpretador de comandos: psql Para desenvolver aplicações os comandos de SQL aparecem misturados numa linguagem de programação Neste módulo mostramos como fazer chamados sqldesde a linguagem Php 2
PostgreSQLe Php: transacções O Php é uma linguagem interpretada. scripting language PHP, é a sigla de Hypertext Preprocessor, Lerdorf 1995 Uma linguagem open-sourcepara utilização geral, especialmente adaptada para desenvolvimento Web Pode ser embebida em HTML. Uma linguagem que funciona no lado do servidor Interpretada no web server com um processador A sintaxe vem de C, C, Java, e Perl O principal objectivo desta linguagem é permitir escrever páginas web dinamicamente geradas Manual. http://www.php.net/manual/en/index.php 3
PostgreSQLe Php: transacções scriptinglanguage: uma linguagem de programação que permite o controlo de uma ou mais aplicações Os chamados a SQL são interpretados previamente por um pre-processador Consultar o Manual do PostreSQL: Programer s Guide Client Interfaces Em php existem extensões do PostgreSQL. Incluem sql embebido Ver http://php.net/manual/en/book.pgsql.php / 4
PostgreSQLe Php: transacções ANTES de utilizar a BD é preciso abrir. No fim devemos fechar Abrir a base de dados desde php <?php include'/dir1/dir11/bibliotecas/biblio-1.php'; $db= dbconnect(); //ligar a bdde dcbm if(!$db) { printf("<p>erro ao abrir a Base de Dados. Contactar o Administrador da BD :).</p> \n"); exit(); } pg_close($db); // fechar a bdno fim?> 5
PostgreSQLe Php: transacções <?php function dbconnect() //-------------------------- { $hostname="localhost"; $db_name= nome-bd"; $db_user = postgres"; $user_psw= lasdflakjasdfj"; $connection_string ="host=$hostname dbname = $db_name user =$db_user password = $user_psw"; $db = pg_connect($connection_string); // abrir a BD desde php if(!$db) { printf("<p> Nãohá ligaçãocom a base de dados. Ensaiar mais tarde. </p>\n"); exit(); } return $db; }?> 6
PostgreSQLe Php: interrogar $OK = pg_query($db, $instrução-sql); Executa o query indicado na string $instrução-sql na base de dados indicada na ligação prévia a base de dados representada aqui pela variável $db Em caso de erro, devolve NULL (pode-se verificar sempre o $OK Pormenores do erro se podem encontrar na função pg_last_error() se a ligação a bd era válida O primeiro parâmetro é opcional, mas não recomendável não incluir 7
PostgreSQLe Php: SELECT if($tripulante) { $query_tripulante = "SELECT* FROM tripulante WHERE nif = $tripulante "; $res = pg_query($conexao, $query_tripulante); if($res) { $c=pg_fetch_array($res); echo$c[0]."<-nome\n"; echo$c[1]."<-morada\n"; } elseerror pg_fetch_array Carrega um tuplo como um array. parareferenciaroselementosdo array, podem-se utilizar indices ou os nomes dos atributos da tabela 8
PostgreSQLe Php: SELECT function valida_chave($db, $tabela, $campo, $chave) {//------------------------------------------------------------------ $instr= "SELECT* FROM $tabelawhere $campo= '$chave'"; $id = pg_query($db, $instr); $row = pg_fetch_row($id); if($row[0]!= $chave) return 0; elsereturn1; }//---------------------------------------------------------------------- pg_fetch_row:semelhante a pg_fetch_arraysó que apenas refere os elementos utilizando índices Isto é, devolve um arranjo numerado com índices 9
PostgreSQLe Php: SELECT //---------------------------------------------------------------- function get_nome_disciplina($db, $id_disciplina) { $query = "SELECT* FROM grupo_curricular WHERE id= '$id_disciplina' "; $resultado = pg_query($db, $query); if($resultado) { $r = pg_fetch_array($resultado); return$r['nome']; } else return NULL: } //------------------------------------------------------------------------- 10
INSERIRtuplos tuplosdinamicamente: HTML <html> Iniciar um bloco de html <head> <title>deei-ualg</title> <link rel="shortcut icon" href= /deei/icon.ico" /> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> </head> <formname= utilizador" action= validar-user.php" method="post" enctype="application/x-www-form-urlencoded"> Nome Utilizador: <INPUT TYPE = "text" value="" name="usuario /> Password: <INPUT TYPE = PASSWORD value ="" name="passwd /> <p> <input type="submit" value ="Validar" name = "go"></p> </form> </html> Após submit, HTML carrega todos os dados de <input> no array $_POST 11
INSERIRtuplos tuplosdinamicamente ***** este é o programa validar-user.php <?php $usuario = $_POST['usuario']; $passw = $_POST['passw']; $nivel= $_POST['nivel']; $data= $_POST['data']; date_default_timezone_set("europe/lisbon"); $data = date(); if (verifica_utilizador($db, $usuario)) //verifica se utilizador existe show_error("já existe um usuariocom este nome. Favor trocar por um outro.",1); $sqlcmd= "INSERT INTO utilizador ( usuario, passw, data) VALUES ('$usuario', '$passw', '$data')"; $OK = pg_query($db, $sqlcmd); //inserir registo na bd. pg_close($db); //após inserção, fechar a BD if(!$ok) show_error(1); else mandar_aviso("novo Utilizador(a): $usuario- criado(a)", 4);?> 12
PostgreSQLe Php: UPDATE SQL: UPDATE utilizador SET passw = D67N9#%BB, data = 11/1172011, WHERE usuario = patricio ; ---------------------------Php----------------------------------------- $usuario = $_POST['usuario']; $passw1 = $_POST['passw1']; $passw2 = $_POST['passw2']; if($passw1!= passw2) show_error( password incorrecto. Repetir sff",1); $cmd= "UPDATE utilizador SET passw='$passw1', WHERE usuario= '$usuario' "; If( pg_query($db, $cmd)) echo user alterado com sucesso ; 13
PostgreSQLe Php: APAGAR SQL DELETEFROM climatologiawhere city = London ; --------------------------------------Php----------------------------------------------- function apagar_registo($db, $bi) { $apagar= "DELETE FROM sociowhere bi= '$bi'"; $OK = pg_query($db, $apagar); if($ok) return("registo sócio nº BI: $bi apagado. \n"); else return( erro: Registo socio nº BI: $bi NÃO apagado\n"); 14
SQL : Transacções Uma Base de Dados tem sempre acessos concorrentes: muitos utilizadores que estão fazer insert, update, delete simultaneamente Para cada utilizador, o SGBD abre um novo processo. Uma nova sessão até este sair da BD. (fechar) Como assegurar a integridade e coerência da BD? Exemplos críticos: reservas bilhetes online, bancos, bolsa, 15
SQL : Transacções O que se passa quando o acesso é concorrente e a um mesmo registo da BD? Por exemplo, a sua conta bancária: Você anda a tirar 30 da sua conta, mas o seu pai ainda não fez depósito também na sua conta Como deveríam acontecer as coisas? Qual transacção primeiro? A conta do seu pai é actualizada depois de lhe depositar os 30 Que se passa se a sua irmã sabe a sua conta e está intentar retirar 20 no mesmo momento que você pretende levantar os 30 que precisa? Que se passa se a BD do banco crasha no meio disto tudo? 16
SQL : Transacções Uma transacção é uma sequência de operações SQL Esta sequência é tratada como um todo Por defeito, uma instrucção de SQL é uma transacção As transacções obedecem as propriedades ACID": Atomicity Consistency Isolation Durability (Ver na introdução) 17
SQL : Transacções Atomicidade: A transacção é um todo. Toda a transacção completada ou nada feito Consistência Os dados devem sempre cumprir as restrições impostas sobre eles no fim, mesmo que transitoriamente estas possam serem violadas Isolamento Duas transacções a correr simultaneamente: os seus efeitos devem ficar isolados. Deve acontecer tal como se só uma transacção tivesse ocorrido. Transparente ao utilizador Durable Terminada uma transacção, os seus efeitos devem perdurar, mesmo se o sistema crachar (system crash) 18
SQL : Transacções em SQL BEGIN WORK inicia uma transacção COMMIT WORK termina uma transacção. BD actualizada ROLLBACK WORK igualmente termina uma transacção. Semelhante a fazer um undo Por defeito, uma instrução SQL é uma transacção 19
SQL : Transacções em SQL Numa operação de inserção fazer LOCK na tabela: BEGIN WORK; LOCK TABLE tripulante IN SHARE MODE; SELECT id_tripulante FROM tripulante WHERE nome = Alberto Martins Lopes ; INSERT INTO folha_tripulante VALUES ( _id_, 914563312 ); COMMIT WORK; Isolara tabela com a chaveprimáriano modoshare, quando se pretendeactualizarumatabelaondeala é foreign key Atenção: no standard SQlnãohálock table set transaction 20
SQL : Transacções em SQL Numa operação de apagar fazer LOCK na tabela com a chave primária: BEGIN WORK; LOCK TABLE filmes IN SHARE ROW EXCLUSIVE MODE; DELETE FROM commentarios_filmes WHERE id IN (SELECT id FROM filmeswhere nivel< 5); DELETE FROM filmeswhere nivel< 5; COMMIT WORK; 21
SQL : Transacções em SQL No standard SQL Por exemplo para a conta do seu pai no depósito dos 30 para sim, o banco terá as instruções: BEGIN WORK; UPDATE conta SET saldo = saldo -30 WHERE numero = 333; //a conta do seu pai UPDATE conta SET saldo = saldo + 30 WHERE numero = 888; // a sua conta COMMIT WORK; Se algo correr mal, o dinheiro não será posto na sua conta, mas também não será levantado da conta do seu pai 22
SQL : Transacções em SQL Os utilizadores (programas) só vem resultados de transacções que fizeram COMMIT E que acontece se no meio da transacção do seu pai, a sua mãe que também tem acesso a conta do seu pai fazer uma transacção e o programa de aplicação no processo dela utiliza igualmente o COMMIT? SQL tem 4 níveis de isolamento das transacções: 1. SERIALIZABLE 2. REPEATABLE READ 3. READ COMMITTED 4. READ UNCOMMITTED Compete ao programador especificar o nível de isolamento pretendido 23
SQL : Transacções em SQL Nível: 1. SERIALIZABLE 2. REPEATABLE READ 3. READ COMMITTED 4. READ UNCOMMITTED Escrevemos: SET TRANSACTION ISOLATION LEVEL <nivel> 24
SERIALIZABLE SQL : Transacções em SQL Se o programa da sessão do seu pai está a correr com o nível de isolamento SERIALIZABLE, só vai ver o seu saldo final depois a sessão da sua mãe que entrou pelo meio terminar pela sua vez. No meio delas não vai ver nada diferente do estado anterior da sua conta antes do inicio destas duas transacções feitas por dois processos concorrentes 25
READ COMMITTED SQL : Transacções em SQL Neste caso, é possível ver o estado parcial da conta após a primeira destas transacções serem tratadas REPETEABLE READ semelhante ao anterior a diferencia é que se um tuploé lido uma vez, então terá de ser forçosamente devolvido se a leitura for repetida 26
SQL : Transacções em SQL READ UNCOMMITTED Se a transacção utilizar esta opção então pode ler os dados transitórios que possam ter sido escritos por outras transacções Por exemplo, poderá ler um saldo inferior na conta, mesmo se a transacção concorrente que levantava dinheiro crashar no meio e a aplicação fazer um ROLLBACK 27
SQL : Transacções em SQL No caso do PostgreSQLsó existem as opções SERIALIZABLE e READ COMMITTED SERIALIZABLE Oferece um maior nível de isolamento. Faz como se as transacções tivessem sido feitas sequencialmente e não concorrentemente. READ COMMITTEDdá menos isolamento, mas é mais eficiente de implementar pelo SGBD. Pretende manter a consistência dos dados Ler sobre concurrency control no manual do PostreSQL 28
PostgreSQLe Php Transacções fim do módulo 29