Version 7 (modified by viani, 16 years ago) (diff) |
---|
Recomendações de Uso de Banco de Dados
WikiInclude(WF/tableofcontents)?
Classe
A classe que é utilizada nos processos de Workflow para fazer conexão com o banco de dados é a wf_db. Esta classe faz uso do ADOdb como camada de abstração de banco de dados.
A documentação da classe pode ser vista na documentação do código fonte do Workflow
Os métodos básicos da classe são:
- connect - conecta-se ao banco de dados (por padrão, conecta-se ao banco de dados onde da base de dados do processo de Workflow);
- disconnect - desconecta-se do banco de dados;
- query - executa um comando SQL no banco de dados.
Objeto
O objeto da classe wf_db já vem criado por padrão no desenvolvimento utilizando o MVC proposto - Arquitetura de Desenvolvimento.
Ele pode ser acessado em qualquer classe model através do atributo {{$this->model}}
Bind
A versão atual do ADOdb utilizada permite a utilização de bind para a execução de queries. A idéia do bind é aproveitar o mesmo plano de execução para as mesmas ações. Na utilização do bind os valores (inseridos, atualizados ou de consulta) são separados da query. Exemplo de utilização de bind:
/* SEM BIND */ $this->DAO->query("INSERT INTO usuario(usuario_id, nome) VALUES(1, 'João')"); //plano de execução 1 $this->DAO->query("INSERT INTO usuario(usuario_id, nome) VALUES(2, 'Maria')"); //plano de execução 2 /* COM BIND */ $this->DAO->query('INSERT INTO usuario(usuario_id, nome) VALUES(?, ?)', array(1, 'João')); //plano de execução 3 $this->DAO->query('INSERT INTO usuario(usuario_id, nome) VALUES(?, ?)', array(2, 'Maria')); //plano de execução 3
Repare que utilizando o bind, o plano de execução para as queries é o mesmo pois, a única coisa que muda são dos dados, a query é a mesma. Já sem a utilização de bind, as queries são diferentes, uma vez que os dados fazem parte da query, gerando diferentes queries para diferentes dados. Outras vantagens de se utilizar o bind sobre o método "tradicional" são:
- O parser do banco de dados não precisa analisar queries que podem ser de grande tamanho devido aos dados que estão sendo inseridos (e.g. inserção de arquivos em banco, neste caso a query terá praticamente o tamanho do arquivo inserido);
- Proteção prática e robusta contra SQL Injection.
Como pode ser visto no exemplo, ao invés de se inserir os valores na query, utiliza-se {{?}} para cada valor e, depois os valores são passados em uma {{array}} como segundo parâmetro do método query. Os itens da array seguem a ordem das {{?}} utilizadas.
Utilização
Antes de utilizar o objeto para acesso ao Banco de Dados, é necessário conectá-lo ao banco. Para isto, basta chamar o método {{connect}}. Caso o banco que se quer conectar é o banco do próprio processo, não é necessário passar parâmetros, sendo a chamada realizada da seguinte maneira:
$this->DAO->connect();
Em todos os exemplos vamos considerar que a conexão com o Banco de Dados já foi feita.
SELECT
/* Exemplo 01 */ $resultSet = $this->DAO->query('SELECT usuario_id, nome FROM usuario'); $data = array(); while ($row = $resultSet->fetchRow()) $data[] = $row; /* a variável $data será uma array com os valores selecionados */ echo $data[0]['nome']; //exemplo de acesso aos dados (nome do primeiro registro retornado) /* Exemplo 02 */ $resultSet = $this->DAO->query('SELECT usuario_id, nome FROM usuario WHERE (nome = ?)', array('José')); $data = array(); while ($row = $resultSet->fetchRow()) $data[] = $row;
INSERT
$result = $this->DAO->query("INSERT INTO area(area_id, nome) VALUES(?, ?)", array(1, 'DISER')); if ($result) echo "OK"; else echo "Erro na execução da query";
UPDATE
/* troca o nome do usuário José para Joselito $result = $this->DAO->query("UPDATE usuario SET nome = ? WHERE (nome = ?)", array('Joselito', 'José'));
DELETE
/* apaga o usuário cujo ID é 3 */ $result = $this->DAO->query("DELETE FROM usuario WHERE (usuario_id = ?)", array(3));
Casos Especiais
Inserção de Arquivos no Banco de Dados
O procedimento para inserir o conteúdo de um arquivo no Banco de Dados, requer uma pequena modificação que faz o tratamento do conteúdo antes de inseri-lo. Este tratamento é feito através da chamada ao método {{escapeBytea}}:
/* supondo que $bin possua o conteúdo do arquivo */ $bin = $this->DAO->escapeBytea($bin); $result = $this->DAO->query("INSERT INTO tabela_arquivo(nome, conteudo) VALUES(?, ?)", array('arquivo.dat', $bin));
Transações
Em alguns casos, é vital a utilização de transações. Sua utilização é muito simples, como pode ser visto abaixo:
/* neste exemplo criamos uma área e tentamos colocar o funcionário José nesta nova área. * Em caso de erro, esta área não deverá ser criada. */ $result = true; $this->DAO->startTrans(); $result = $result && $this->DAO->query("INSERT INTO area(area_id, nome) VALUES(?, ?)", array(10, 'NOVA ÁREA')); $result = $result && $this->DAO->query("UPDATE funcionario SET area_id = ? WHERE (nome = ?)", array(10, 'José')); if ($result) $this->DAO->completeTrans(); // faz o commit das alterações else $this->DAO->failTrans(); // faz o rollback das alterações