UNIVERSIDADE ESTADUAL DE MARINGÁ CENTRO DE TECNOLOGIA DEPARTAMENTO DE INFORMÁTICA RICARDO ALEXANDRE DA SILVA LAVARIAS DESENVOLVIMENTO DE APLICAÇÕES DE BANCO DE DADOS PARA A WEB: PHP E MYSQL VERSUS PHP E POSTGRESQL MARINGÁ 2005 RICARDO ALEXANDRE DA SILVA LAVARIAS DESENVOLVIMENTO DE APLICAÇÕES DE BANCO DE DADOS PARA A WEB: PHP E MYSQL VERSUS PHP E POSTGRESQL Monografia apresentada à Universidade Estadual de Maringá como requisito parcial para obtenção do título de Especialista em Desenvolvimento de Sistemas para Web. Orientador: Prof. Rodrigues Ciferri MARINGÁ 2005 Dr. Ricardo RICARDO ALEXANDRE DA SILVA LAVARIAS DESENVOLVIMENTO DE APLICAÇÕES DE BANCO DE DADOS PARA A WEB: PHP E MYSQL VERSUS PHP E POSTGRESQL Monografia apresentada à Universidade Estadual de Maringá como requisito parcial para obtenção do título de especialista em Desenvolvimento de Sistemas para Web. Aprovado em BANCA EXAMINADORA __________________________________________ Prof. Sérgio Roberto Pereira da Silva Universidade Estadual de Maringá – UEM __________________________________________ Profa. Tânia Fátima Calvi Tait Universidade Estadual de Maringá – UEM __________________________________________ Profa. Maria Madalena Dias Universidade Estadual de Maringá – UEM A DEUS. AGRADECIMENTOS Primeiramente agradeço a DEUS por quão maravilhosa é minha vida. Agradeço por todas oportunidades que me foram dadas, saúde, inteligência e por poder ter condições de cursar esta especialização e concluir esse trabalho. Agradeço aos meus pais Lairton e Marinez, por tudo. Se sou essa pessoa que sou hoje, é por “culpa” deles, que me ensinaram muitas coisas, dentre elas, que temos que ser honestos, ter caráter, educação, temos que trabalhar e conquistar nosso espaço naturalmente, enfim, agradeço eles pela vida que me foi dada. Com certeza vocês são os pilares que me sustentam. Amo vocês! A minha noiva Kelly, que sempre foi minha incentivadora e companheira que entendeu alguns momentos de ausência que tive que dedicar a execução deste trabalho. Ao meu amigão Luiz Arthur, que posso dizer que é meu irmão. Amigo desde a época da graduação e companheiro de republica em Maringá. Agradeço a ele, pois em alguns dos momentos mais importantes da minha vida até hoje, ele foi um conselheiro e incentivador. Devo agradecer fervorosamente a duas pessoas maravilhosas: Prof. Ricardo Rodrigues Ciferri e Prof. Cristina Dutra de Aguiar Ciferri. Graças a vocês esse trabalho foi concluído, graças aos vossos incentivos, apoio, puxão de orelha, pois eu já havia “jogado a toalha”. Sem o vosso apoio eu não teria concluído essa etapa! Enfim quero agradecer a todos de que alguma forma, direta ou indiretamente, me ajudaram e apoiaram para a concretização desse curso de especialização. A todos um sincero MUITO OBRIGADO! Resumo Esse trabalho realiza um estudo comparativo entre as funcionalidades do SGBD MySQL e do SGBD PostgreSQL, bem como uma análise da forma de acesso da linguagem PHP a esses SGBDs. Essa investigação se faz necessária, pois quando se trata de desenvolvimento de sistemas para internet, mais comumente usa-se a linguagem de programação PHP com o Sistema Gerenciador de Banco de Dados MySQL. Isto se dá ao fato da linguagem de programação PHP oferecer acesso nativo ao Banco de Dados MySQL, ou seja, o PHP disponibiliza várias funções de fácil utilização que permitem o acesso, a pesquisa e a manipulação dos dados armazenados no SGBD MySQL. Entretanto, esse SGBD possui algumas limitações quando comparado às funcionalidades oferecidas por outros SGBDs disponíveis no mercado, como exemplo, o PostgreSQL. Desta forma, surge a necessidade de se investigar quais funcionalidades que o SGBD PostgreSQL oferece que o SGBD MySQL não oferece, e vice-versa, e como o acesso ao SGBD PostgreSQL pode ser realizado por meio da linguagem PHP. O objetivo deste trabalho, mais especificamente, é realizar um estudo comparativo entre os SGBD MySQL e SGBD PostgreSQL, analisando suas funcionalidades e também as formas de acesso da linguagem de programação PHP aos dois SGBDs. Dentre as principais contribuições deste trabalho, destacam-se: (i) identificação de quais funcionalidades da linguagem SQL são oferecidas pelo SGBD MySQL e pelo SGBD PostgreSQL, e comparação desses SGBDs com relação a essas funcionalidades; (ii) pesquisa e investigação das funções oferecidas pela linguagem de implementação PHP para o acesso ao SGBD PostgreSQL; (iii) comparação das funções oferecidas pela linguagem de implementação PHP para o acesso ao SGBD MySQL e ao SGBD PostgreSQL; (iv) produção de roteiro para instalação dos softwares necessários para a realização dos estudos, no sistema operacional Windows e também no sistema operacional Linux. SUMÁRIO 1 Introdução.......................................................................................................... 009 1.1 Estruturação da Monografia................................................................................ 010 1.2 Metodologia de Pesquisa..................................................................................... 010 2 A utilização da SQL DDL e SQL DML nos Sistemas Gerenciadores de Banco de Dados MySQL e PostgreSQL............................................................. 011 2.1 Base de Dados...................................................................................................... 011 2.2 Tipos de Dados.................................................................................................... 018 2.3 DDL (Data Definition Language)…………………………………………….... 020 2.3.1 Create Table......................................................................................................... 020 2.3.2 Drop Table……………………………………………………………………. 021 2.3.3 Alter Table........................................................................................................... 021 2.3.4 Create View…………………………………………………………………... 021 2.3.5 Drop View……………………………………………………………………. 021 2.4 DML (Data Manipulation Language).................................................................. 022 2.4.1 Select.................................................................................................................... 022 2.4.2 From..................................................................................................................... 023 2.4.3 Where................................................................................................................... 023 2.4.4 Order By.............................................................................................................. 024 2.4.5 Group By............................................................................................................. 025 2.4.6 Having.................................................................................................................. 025 2.4.7 Null...................................................................................................................... 026 2.4.8 Union / Union All................................................................................................ 026 2.4.9 Intersect / Intersect All......................................................................................... 026 2.4.10 Except / Except All.............................................................................................. 027 2.4.11 In / Not In............................................................................................................. 027 2.4.12 Some.................................................................................................................... 028 2.4.13 All........................................................................................................................ 029 2.4.14 Exists / Not Exists................................................................................................ 029 2.4.15 Unique / Not Unique............................................................................................ 030 2.4.16 Relações Derivadas.............................................................................................. 031 2.4.17 Delete................................................................................................................... 031 2.4.18 Insert.................................................................................................................... 031 2.4.19 Update.................................................................................................................. 032 2.4.20 Join…………….......…………………………………………………………… 032 2.5 Funcionalidades oferecidas pelos SGBD MySql e PostgreSQL……......……... 033 2.6 Considerações Finais........................................................................................... 035 3 Funções de acesso da linguagem PHP ao Sistema Gerenciador de Banco de Dados MySQL............................................................................................... 037 3.1 Funções de acesso do PHP ao MySql.................................................................. 037 3.1.1 Função mysql_connect( )..................................................................................... 038 3.1.2 Função mysql_select_db( )………………......………………………………… 038 3.1.3 Função mysql_query( )……………..………………………………………….. 039 3.1.4 Função mysql_fetch_row( )................................................................................. 039 3.1.5 Função mysql_num_fields( )............................................................................... 040 3.1.6 Função mysql_close( )......................................................................................... 040 3.1.7 Função mysql_data_seek( )................................................................................. 040 3.1.8 Função mysql_fetch_array( )............................................................................... 041 3.1.9 Função mysql_fetch_object( )............................................................................. 041 3.1.10 Função mysql_free_result( )...................…......................................................... 042 3.1.11 Função mysql_num_rows( )……………………………..........……………….. 042 3.1.12 Função mysql_pconnect( )................................................................................... 043 3.1.13 Função mysql_change_user( )……………………..…………………………... 043 3.1.14 Função mysql_create_db( ).................................................................................. 044 3.1.15 Função mysql_drop_db( ).................................................................................... 044 3.1.16 Função mysql_fetch_field( )................................................................................ 045 3.1.17 Função mysql_list_tables( )……………………..……………………………... 046 3.1.18 Função mysql_tablename( )…………………….......………………………….. 046 3.1.19 Função mysql_errno( )......................................................................................... 047 3.1.20 Função mysql_error( )......................................................................................... 047 3.1.21 Função mysql_affected_rows( ).......................................................................... 047 3.1.22 Função mysql_insert_id( )……………………......……………………………. 048 3.2 Funções oferecidas pelo PHP para acesso aos dados no SGBD MySql.............. 049 3.3 Considerações Finais........................................................................................... 050 4 Funções de acesso da linguagem PHP ao Sistema Gerenciador de Banco de Dados PostgreSQL........................................................................................ 051 4.1 Funções de acesso do PHP ao PostgreSQL......................................................... 051 4.1.1 Função pg_connect( ).......................................................................................... 052 4.1.2 Função pg_query( )………………………...........……………………………... 052 4.1.3 Função pg_fetch_row( )....................................................................................... 053 4.1.4 Função pg_num_fields( )..................................................................................... 053 4.1.5 Função pg_close( )............................................................................................... 054 4.1.6 Função pg_fetch_array( )..................................................................................... 054 4.1.7 Função pg_fetch_object( )................................................................................... 055 4.1.8 Função pg_free_result( )...................................................................................... 055 4.1.9 Função pg_num_rows( )...................................................................................... 056 4.1.10 Função pg_pconnect( )........................................................................................ 056 4.1.11 Função pg_last_error( )………………………...………………………………. 057 4.1.12 Função pg_affected_rows( )................................................................................ 057 4.1.13 Função pg_getlastoid( )…………..........………………………………………. 058 4.2 Funções oferecidas pelo PHP para acesso aos dados no SGBD PostgreSQL..... 059 4.3 Funções oferecidas pelo PHP para acesso aos dados no SGBD MySql e no SGBD PostgreSQL.............................................................................................. 060 4.4 Considerações Finais........................................................................................... 061 5 Aplicação de Banco de Dados utilizando o SGBD PostgreSQL e a Linguagem de Programação PHP.................................................................... 062 5.1 Aplicação Base.................................................................................................... 062 5.2 Telas Principais da Aplicação.............................................................................. 062 5.3 Script para realização de uma consulta Simples.................................................. 068 5.4 Script para realização de uma consulta envolvendo duas tabelas........................ 070 5.5 Script para realização de uma consulta envolvendo três tabelas......................... 072 5.6 Script para Inserção de dados no SGBD.............................................................. 077 5.7 Script para alteração de dados no SGBD............................................................. 082 5.8 Considerações Finais........................................................................................... 093 6 Conclusão............................................................................................................ 094 Referências Bibliográficas................................................................................... 095 Apêndice A - Instalação dos softwares utilizados no Sistema Operacional Windows............................................................................................................. 096 Apêndice B - Instalação dos softwares utilizados no Sistema Operacional Linux................................................................................................................... 100 LISTA DE FIGURAS Figura 5.1 – Tela inicial da aplicação............................................................................... 063 Figura 5.2 – Primeira tela da consulta com 2 tabelas........................................................ 064 Figura 5.3 – Tela resultado da consulta com 2 tabelas..................................................... 065 Figura 5.4 – Primeira tela do script de alteração de registros........................................... 065 Figura 5.5 – Segunda tela do script de alteração de registros........................................... 066 Figura 5.6 – Terceira tela do script de alteração de registros............................................ 067 Figura 5.7 – Quarta tela do script de alteração de registros.............................................. 067 LISTA DE TABELAS Tabela 2.1 – Descrição semântica das relações e atributos............................................... 012 Tabela 2.2 – Comandos SQL DDL oferecidos pelos SGBD em estudo........................... 033 Tabela 2.3 – Tipos de dados disponíveis pelo SGBD MySql e PostgreSQL.................... 033 Tabela 2.4 – Comandos SQL DML oferecidos pelos SGBD em estudo.......................... 034 Tabela 3.1 – Funções PHP para conexão com o SGBD MySql....................................... 049 Tabela 4.1 – Funções PHP para conexão com o SGBD PostgreSQL............................... 059 Tabela 4.2 – Funções PHP para conexão com o SGBD Mysql e com o PostgreSQL...... 060 LISTA DE SIGLAS SGBD SISTEMA GERENCIADOR DE BANCO DE DADOS WEB ou WWW WORLD WIDE WEB PHP PERSONAL HOME PAGE SQL STRUCTURED QUERY LANGUAGE DDL DATA DEFINITION LANGUAGE DML DATA MANIPULATION LANGUAGE Capítulo 1 Introdução Com a expansão da Internet, surge um aumento da necessidade do desenvolvimento de sistemas para a World-Wide Web. Para o desenvolvimento desses sistemas tem-se comumente usado a linguagem de programação PHP e o sistema gerenciador de banco de dados (SGBD) MySQL. Isto se deve principalmente ao fato de que a linguagem PHP oferece várias funções de fácil utilização que permitem o armazenamento, a pesquisa e a manipulação dos dados armazenados no SGBD MySQL. Mas existem outras características que favorecem o uso conjunto de PHP e MySQL. O PHP, por exemplo, é uma linguagem de script eficiente e poderosa, desenvolvida para a criação de sites Web dinâmicos. Além de prover grande portabilidade, PHP é totalmente gratuita e oferece mais de 50 bibliotecas que podem ser facilmente utilizadas no desenvolvimento de sistemas complexos (Converse & Park, 2001). O SGBD relacional MySQL, por sua vez, assim como PHP, também é um produto livre, de código fonte aberto, e que possui grande portabilidade (Miloca, 2004). Este SGBD é voltado ao desenvolvimento de aplicações de banco de dados de porte médio, e oferece a maioria das funcionalidades de um SGBD de grande porte. Entretanto, o MySQL possui algumas limitações quando comparado às funcionalidades oferecidas por outros SGBD, como exemplo o PostgreSQL. O PostgreSQL é um sistema gerenciador de banco de dados híbrido relacional e orientado a objetos. É considerado um dos melhores SGBD para sistema operacional GNU LINUX, voltado para aplicações simples ou complexas com uma robustez excepcional (Neves, 2002). Conclui-se ainda (Neves, 2002), que MySQL e PHP, formam uma boa combinação para servir páginas da Web com conteúdo dinâmico, para projetos em que a velocidade e o número de acessos concorrentes sejam primordiais, mas não se dando muita importância para a questão segurança. Quando se trata de sistemas mais sérios e robustos, para os quais a segurança e a confiabilidade são as principais preocupações, PostgreSQL torna-se a melhor opção. Assim, surge a necessidade de se investigar o uso do SGBD PostgreSQL no desenvolvimento de aplicações de banco de dados para a Web. Para isso, deve-se comparar quais funcionalidades que o SGBD PostgreSQL oferece diferem das funcionalidades do SGBD MySQL e vice-versa, e como o acesso ao SGBD PostgreSQL pode ser realizado por meio da linguagem PHP. Este trabalho faz parte de um projeto de pesquisa mais amplo onde seu objetivo principal é realizar a comparação de diversos Sistemas de Gerenciamento de Base de Dados. 1.1 Estruturação da Monografia Além deste capítulo introdutório, esta monografia está estruturada em mais 5 capítulos. No Capítulo 2 são investigadas as funcionalidades da linguagem SQL voltadas à definição de dados e à manipulação dos dados. Neste capítulo também são destacadas quais destas funcionalidades podem ser encontradas no SGBD MySQL e no SGBD PostgreSQL. Funções de acesso aos SGBD MySQL usando a linguagem de programação PHP são descritas no Capítulo 3. Cada uma das funções é discutida em termos de sua descrição, de sua sintaxe e de um exemplo de utilização. Já no Capítulo 4 são apresentadas as funções de acesso da linguagem de programação PHP ao SGBD PostgreSQL. Este capítulo também apresenta uma tabela que compara as funções de acesso ao SGBD MySQL com as funções de acesso ao SGBD PostgreSQL. Uma aplicação de banco de dados para a Web usando a linguagem de programação PHP e o SGBD PostgreSQL é descrita no Capítulo 5. Neste capítulo são destacadas a interface da aplicação, além dos scripts desenvolvidos. No capítulo 6 são apresentadas as conclusões e as contribuições do trabalho. 1.2 Metodologia de Pesquisa Para realização deste trabalho foi utilizanda uma metodologia que inclui a leitura de livros sobre Banco de Dados e Banco de Dados e Web, além da leitura de livros e manuais sobre a linguagem de programação PHP e os SGBD MySql e PostgreSQL. Para o estudo, foram desenvolvidos estudos de casos envolvendo a linguagem de programação PHP e o SGBD PostgreSQL. Capítulo 2 A utilização da SQL DDL e SQL DML nos Sistemas Gerenciadores de Banco de Dados MySQL e PostgreSQL Durante o desenvolvimento deste capítulo são identificadas as características que um Sistema Gerenciador de Banco de Dados deve oferecer com relação às linguagens de definição de dados (DDL) e de manipulação de dados (DML). Após essa identificação, são mostradas em uma tabela comparativa quais as características encontradas e se as mesmas estão disponíveis para utilização nos SGBDs em estudo (MySQL e PostgreSQL). Para essa identificação de disponibilidades de características, são utilizadas as seguintes versões dos SGBD: MySQL 4.0.15 e PostgreSQL 7.4.2. Na Seção 2.1 deste capítulo é descrita a base de dados utilizada para a exemplificação dos comandos SQL. Os tipos de dados que a SQL oferece para a criação dos atributos nas relações são destacados na Seção 2.2. Nas Seções 2.3 e 2.4 são apresentados, respectivamente, a SQL DDL e SQL DML. Nestas seções são destacados os conceitos e os principais comandos destas linguagens. Na Seção 2.5 são apresentadas tabelas com os comandos SQL DDL e SQL DML descritos nas seções anteriores, e são identificados se os referidos comandos podem ser utilizados no SGBD MySQL como também no SGBD PostgreSQL. Este capítulo é finalizado na Seção 2.6, na qual são apresentadas as considerações finais. 2.1 Base de Dados Nessa seção é descrita a base de dados utilizada para a exemplificação dos comandos SQL, bem como para o desenvolvimento de protótipos para uso nos SGBDs MySQL e PostgreSQL. Esta base de dados foi retirada de Willians & Lane (2002), as relações que compõe esta base de dados são: • users (user _id, cust_id, user_name, password); • customer (cust_id, surname, firstname, initial, title, addressline1, addressline2, addressline3, city, state, zipcode, country, phone, fax, email, birth_date, salary); • grape_variety (variety_id, variety); • inventory (wine_id, inventory_id, on_hand, cost, case_cost, date_added); • items (cust_id, order_id, item_id, wine_id, qty, price, date); • orders (cust_id, order_id, date, discount, delivery, note); • region (region_id, region_name, description, map); • wine (wine_id, wine_name, type, year, winery_id, description); • wine_variety (wine_id, variety_id, id); • winery (winery_id, winery_name, region_id, description, phone, fax); A Tabela 2.1 mostra uma breve descrição semântica de cada uma dessas relações. Relação / Atributo Users Descrição Armazena informações sobre os usuários do sistema. user_id Código identificador do usuário cust_id Código identificador do cliente user_name Nome do usuário password Senha de acesso do usuário Customer Armazena informações sobre os clientes. cust_id Código identificador do cliente surname Sobrenome do cliente firstname Primeiro nome do cliente initial Letra inicial do nome do meio do cliente title Título do cliente, por exemplo, Sir addressline1 Linha de endereço do cliente addressline2 Linha de endereço do cliente addressline3 Linha de endereço do cliente city Cidade na qual o cliente mora state Estado no qual o cliente mora zipcode CEP associado ao endereço do cliente country País no qual o cliente mora phone Número do telefone do cliente fax Número do fax do cliente email Endereço de correio eletrônico do cliente birth_date Data de aniversário do cliente salary Salário do cliente Grape_variety Armazena informações sobre as variedades de uvas. variety_id Código identificador da variedade variety Nome da uva utilizada na fabricação do vinho Inventory Armazena informações sobre o estoque. wine_id Código identificador do vinho inventory_id Código identificador do estoque on_hand Quantidade do vinho em estoque cost Preço da garrafa de vinho case_cost Preço da caixa de vinho, a qual contém 12 garrafas date_added Data na qual a remessa de vinho foi adicionada ao estoque Items Armazena informações sobre os itens do estoque. cust_id Código identificador do cliente order_id Código identificador do pedido item_id Código identificador do item wine_id Código identificador do vinho qty Quantidade de garrafas do item a serem compradas price Preço do item por garrafa ou por caixa multiplicado pela quantidade date Data na qual o item foi adicionado ao carrinho de compras Orders Armazena informações sobre os pedidos. cust_id Código identificador do cliente order_id Código identificador do pedido date Data na qual o pedido é realizado discount Porcentagem de desconto no preço de um pedido delivery Taxa cobrada para a entrega dos produtos note Texto explicativo Region Armazena informações sobre as regiões. region_id Código identificador da região region_name Nome da região, área na qual a vinícola está localizada description Descrição da região map Mapa ou imagem da região Wine Armazena informações sobre os vinhos. wine_id Código identificador do vinho wine_name Nome do vinho type Tipo do vinho year Ano da safra de fabricação do vinho winery_id Código identificador da vinícola description Wine_variety Descrição do vinho Armazena informações sobre as variedades de vinhos. wine_id Código identificador do vinho variety_id Código identificador da variedade id Identificação Winery Armazena informações sobre as vinícolas. winery_id Código identificador da vinícola winery_name Nome da vinícola region_id Código de identificação da região description Descrição da vinícola phone Número do telefone da vinícola fax Número do fax da vinícola Tabela 2.1 – Descrição semântica das relações e dos atributos. Após a apresentação da base de dados, são descritos os comandos SQL para a criação das tabelas, obedecendo ao padrão SQL-92. Os comandos a seguir estendem os comandos descritos em Willians & Lane (2002) com a inclusão da especificação de chaves estrangeiras. CREATE TABLE users ( user_id int(4) DEFAULT '0' NOT NULL, cust_id int(4) DEFAULT '0' NOT NULL, user_name varchar(50) DEFAULT '' NOT NULL, password varchar(15) DEFAULT '' NOT NULL, PRIMARY KEY (user_id), KEY password (password), FOREIGN KEY (cust_id) REFERENCES customer (cust_id) ON UPDATE CASCADE ON DELETE CASCADE ); CREATE TABLE customer ( cust_id int(5) NOT NULL auto_increment, surname varchar(50) DEFAULT '' NOT NULL, firstname varchar(50) DEFAULT '' NOT NULL, initial char(1), title varchar(10), addressline1 varchar(50) DEFAULT '' NOT NULL, addressline2 varchar(50), addressline3 varchar(50), city varchar(20) DEFAULT '' NOT NULL, state varchar(20), zipcode varchar(5), country varchar(20), phone varchar(15), fax varchar(15), email varchar(30) DEFAULT '' NOT NULL, birth_date date DEFAULT '0000-00-00' NOT NULL, salary int(7) DEFAULT '0' NOT NULL, PRIMARY KEY (cust_id), KEY names (surname,firstname) ); CREATE TABLE grape_variety ( variety_id int(3) NOT NULL auto_increment, variety varchar(50) DEFAULT '' NOT NULL, PRIMARY KEY (variety_id), KEY var (variety) ); CREATE TABLE inventory ( wine_id int(5) DEFAULT '0' NOT NULL, inventory_id int(3) DEFAULT '0' NOT NULL, on_hand int(5) DEFAULT '0' NOT NULL, cost float(5,2) DEFAULT '0.00' NOT NULL, case_cost float(5,2) DEFAULT '0.00' NOT NULL, date_added timestamp(12), PRIMARY KEY (wine_id,inventory_id), FOREIGN KEY (wine_id) REFERENCES wine (wine_id) ON UPDATE CASCADE ON DELETE CASCADE ); CREATE TABLE items ( cust_id int(5) DEFAULT '0' NOT NULL, order_id int(5) DEFAULT '0' NOT NULL, item_id int(3) DEFAULT '1' NOT NULL, wine_id int(4) DEFAULT '0' NOT NULL, qty int(3), price float(5,2), date timestamp(12), PRIMARY KEY (cust_id,order_id,item_id), FOREIGN KEY (cust_id) REFERENCES customer (cust_id) ON UPDATE CASCADE ON DELETE CASCADE, FOREIGN KEY (order_id) REFERENCES orders (order_id) ON UPDATE CASCADE ON DELETE CASCADE, FOREIGN KEY (wine_id) REFERENCES wine (wine_id) ON UPDATE CASCADE ON DELETE CASCADE ); CREATE TABLE orders ( cust_id int(5) DEFAULT '0' NOT NULL, order_id int(5) DEFAULT '0' NOT NULL, date timestamp(12), discount float(3,1) DEFAULT '0.0', delivery float(4,2) DEFAULT '0.00', note varchar(120), PRIMARY KEY (cust_id,order_id), FOREIGN KEY (cust_id) REFERENCES customer (cust_id) ON UPDATE CASCADE ON DELETE CASCADE ); CREATE TABLE region ( region_id int(4) NOT NULL auto_increment, region_name varchar(100) DEFAULT '' NOT NULL, description blob, map mediumblob, PRIMARY KEY (region_id), KEY region (region_name) ); CREATE TABLE wine ( wine_id int(5) NOT NULL auto_increment, wine_name varchar(50) DEFAULT '' NOT NULL, type varchar(10) DEFAULT '' NOT NULL, year int(4) DEFAULT '0' NOT NULL, winery_id int(4) DEFAULT '0' NOT NULL, description blob, PRIMARY KEY (wine_id), KEY name (wine_name), KEY winery (winery_id), FOREIGN KEY (winery_id) REFERENCES winery (winery_id) ON UPDATE CASCADE ON DELETE CASCADE ); CREATE TABLE wine_variety ( wine_id int(5) DEFAULT '0' NOT NULL, variety_id int(3) DEFAULT '0' NOT NULL, id int(1) DEFAULT '0' NOT NULL, PRIMARY KEY (wine_id,variety_id), KEY wine (wine_id,variety_id), FOREIGN KEY (wine_id) REFERENCES wine (wine_id) ON UPDATE CASCADE ON DELETE CASCADE, FOREIGN KEY (variety_id) REFERENCES grape_variety (variety_id) ON UPDATE CASCADE ON DELETE CASCADE ); CREATE TABLE winery ( winery_id int(4) NOT NULL auto_increment, winery_name varchar(100) DEFAULT '' NOT NULL, region_id int(4) DEFAULT '0' NOT NULL, description blob, phone varchar(15), fax varchar(15), PRIMARY KEY (winery_id), KEY name (winery_name), KEY region (region_id), FOREIGN KEY (region_id) REFERENCES region (region_id) ON UPDATE CASCADE ON DELETE CASCADE ); 2.2 Tipos de Dados Para a definição dos atributos, deve-se especificar os seus tipos de dados. Segundo Elmasri & Navathe (2003), Silberschatz et al. (1999) e Williams & Lane (2002), o padrão SQL-92 possibilita a utilização de diversos tipos de dados, dentre os quais destacam-se: • Numéricos: os dados numéricos podem ser inteiros (integer) ou decimais (real), com subtipos que apenas diferem nas variações de tamanho. Os inteiros se subdividem em INTEGER ou INT e SMALLINT. Já os decimais subdividem-se em FLOAT, REAL e DOUBLE PRECISION; • Caracter-String: os tipos de dados destinados para o armazenamento dos caracteres alfa numéricos se dividem em dois grupos principais. O primeiro desses grupos refere-se aos tipos de dados que têm números fixos de caracteres. Para estes tipos de dados, o tamanho do atributo é atribuído logo depois da definição do tipo. Como exemplo pode-se citar o tipo CHAR(n), onde n é o número de caracteres. Já o segundo grupo diz respeito ao tipo de dado destinado para os atributos alfa numéricos cujo tamanho é variável. Para estes tipos de dados define-se apenas o tamanho máximo do atributo. Por exemplo, pode-se citar o tipo VARCHAR(n), onde n é o número máximo de caracteres; • Bit-String: semelhante ao tipo de dado caracter-string, mas com uma capacidade menor de armazenamento de dados. Também se divide em dois subgrupos: o de tamanho fixo, BIT(n), e o de tamanho variável, BIT VARYING(n), onde n é o número máximo de bits, sendo seu valor padrão um; • Data: destinado para o armazenamento de datas. Atributos com esse tipo de dados possuem 10 posições, sendo compostos por ano, mês e dia. Em geral, o tipo de dados DATE é disposto da seguinte forma: AAAA-MM-DD; e • Hora: o tipo de dados TIME é composto de oito posições, sendo nele armazenado a hora, o minuto e o segundo, de acordo com a forma HH:MM:SS. 2.3 DDL (Data Definition Language) A Linguagem de Definição de Dados é um conjunto de comandos para a definição de esquemas de relações, exclusão, alteração de relações e criação de índices. O desenvolvimento dessa seção é baseado nos materiais de Elmasri & Navathe (2003), Silberschatz et al. (1999) e Williams & Lane (2002). 2.3.1 CREATE TABLE Define a estrutura de uma tabela e suas restrições de integridade. O comando CREATE TABLE cria a tabela vazia, ou seja, sem dados. A seguir é exemplificado o comando CREATE TABLE para a relação orders. CREATE TABLE orders ( cust_id int(5) DEFAULT '0' NOT NULL, order_id int(5) DEFAULT '0' NOT NULL, date timestamp(12), discount float(3,1) DEFAULT '0.0', delivery float(4,2) DEFAULT '0.00', note varchar(120), PRIMARY KEY (cust_id,order_id), FOREIGN KEY (cust_id) REFERENCES customer (cust_id) ON UPDATE CASCADE ON DELETE CASCADE ); Na criação de uma tabela, são definidas algumas restrições de integridade. As seguintes restrições podem ser especificadas: • KEY: especifica que o atributo é chave; • PRIMARY KEY: descreve os atributos que são chaves primárias; • FOREIGN KEY: descreve os atributos que são chaves estrangeiras; • NOT NULL: especifica que o atributo não admite valor vazio; • DEFAULT: define o valor padrão do atributo; • UNIQUE: define que o atributo irá conter valor único; e • CHECK: assegura que os valores dos atributos satisfaçam determinadas condições. 2.3.2 DROP TABLE Elimina uma tabela da base de dados. Por exemplo: DROP TABLE orders; 2.3.3 ALTER TABLE Este comando modifica a definição de uma tabela, permitindo a inclusão e/ou exclusão de atributos e a inclusão e exclusão de restrições de integridade. Por exemplo, para se remover uma coluna da tabela orders, pode-se usar o seguinte comando: ALTER TABLE orders DROP date; Já o comando a seguir adiciona uma nova coluna à tabela orders, e especifica o valor default para esta coluna. ALTER TABLE orders ADD date DATE DEFAULT '2004-01-01'; 2.3.4 – CREATE VIEW Uma visão é uma tabela derivada de outras tabelas ou de outras visões. Para se definir uma visão em SQL, deve-se usar o comando CREATE VIEW: CREATE VIEW vinhos_e_idades AS (SELECT wine_name, type, (2004-year) as total_anos FROM wine WHERE winery_id =4); 2.3.5 DROP VIEW Este comando remove uma visão. No exemplo a seguir, o comando remove a visão vinhos_e_idades, criada no exemplo da seção 2.3.4. DROP VIEW vinhos_e_idades; 2.4 DML (Data Manipulation Language) Essa linguagem é uma linguagem de consulta baseada tanto na álgebra relacional quanto no cálculo relacional de tuplas. Engloba também comandos de inserção, exclusão e modificação de tuplas no banco de dados. Serviram como base para o desenvolvimento desta seção as seguintes referências: Elmasri & Navathe (2003), Silberschatz et al. (1999), Williams & Lane (2002), MySQL (2004) e PostgreSQL (2004). Os principais comandos dessa linguagem são: 2.4.1 SELECT É utilizado para relacionar os atributos desejados no final de uma consulta. O comando a seguir exibe para os usuários três colunas (cust_id, order_id e date) da tabela orders. SELECT cust_id, order_id, date FROM orders; Para selecionar todos os atributos de uma tabela deve-se usar o caractere *. SELECT * FROM orders; Vale lembrar que a SQL permite a duplicidade de dados e, conseqüentemente, duplicidade dos mesmos nos resultados das consultas. Caso seja desejado eliminar essa duplicidade na apresentação dos dados, deve-se utilizar a palavra DISTINCT depois do SELECT. No comando a seguir, vinícolas de mesmo nome são listadas uma única vez. SELECT DISTINCT winery_name FROM winery; Apesar da não eliminação da duplicidade ser padrão, pode-se especificar a cláusula ALL após o comando SELECT, ratificando assim a apresentação de valores duplicados. SELECT ALL winery_name FROM winery; A cláusula SELECT ainda pode ser utilizada para apresentar dados que não fazem parte de nenhuma tabela. Por exemplo, pode-se exibir: • A hora atual por meio do comando: SELECT curtime(); • O resultado de uma operação aritmética utilizando, por exemplo: SELECT 2+2; e • A data atual por meio do comando: SELECT curdate();. Pode-se ainda renomear as colunas para apresentação dos dados colocando-se após o nome do campo na cláusula SELECT o prefixo AS seguido do novo nome do campo. No exemplo a seguir, as colunas wine_name e year são renomeadas para nome_vinho e ano_produção, no momento de sua exibição. SELECT wine_name AS nome_vinho, year AS ano_produção FROM wine WHERE year BETWEEN 1985 AND 1990; 2.4.2 FROM Como já visto nos exemplos anteriores, na cláusula FROM deve-se especificar o lugar onde serão pesquisados os dados, ou seja, as tabelas que possuem os dados que serão mostrados em resposta à consulta. No comando a seguir são selecionados os campos nome do vinho e ano da tabela wine. SELECT wine_name, year FROM wine WHERE year BETWEEN 1985 AND 1990; Pode-se ainda renomear as tabelas que terão a sua base pesquisada na consulta, utilizando na cláusula FROM o prefixo AS seguido do novo nome da tabela. O exemplo a seguir mostra que a tabela wine é renomeada para w. SELECT wine_name, year FROM wine AS w WHERE year BETWEEN 1985 AND 1990; 2.4.3 WHERE Na cláusula WHERE é especificada a condição para que os dados sejam selecionados e apresentados no final da consulta. Ela funciona como um filtro para a consulta. Para ilustrar a utilização desta cláusula, considere a consulta: “Selecionar o nome do vinho e o ano, de todo o vinho cujo tipo é vermelho”. SELECT wine_name, year FROM wine WHERE type = 'RED'; Com o WHERE podemos utilizar os operadores lógicos AND, OR e NOT. Também é possível a utilização dos operadores de comparação <, <=, >, >=, =, <>. O operador de comparação BETWEEN, por sua vez, permite especificar um intervalo de dados que satisfaça à condição da consulta. Como exemplo, os nomes dos vinhos e os seus respectivos anos, para vinhos produzidos entre 1985 e 1990 são recuperados pelo comando: SELECT wine_name, year FROM wine WHERE year BETWEEN 1985 AND 1990; A cláusula WHERE permite uma manipulação especial de strings. Para tanto, é necessário o uso do operador LIKE. O LIKE faz uso de dois operadores especiais: o porcentagem ( % ), que compara qualquer substring; e o sublinhado ( _ ), que compara qualquer caractere. Como exemplo, o comando a seguir seleciona todo nome de vinho que comece com a letra k. SELECT wine_name FROM wine WHERE wine_name LIKE 'K%' 2.4.4 ORDER BY Esta cláusula é utilizada para a ordenação dos dados durante a apresentação. Essa ordem pode ser definida de forma ascendente (ASC) ou descendente (DESC). Para listar todos os dados dos vinhos em que o ano está entre 1985 e 1990 de forma que o nome do vinho seja apresentado em ordem alfabética, deve-se utilizar a seguinte consulta: SELECT * FROM wine WHERE year BETWEEN 1985 AND 1990 ORDER BY wine_name ASC; 2.4.5 GROUP BY A SQL oferece funções agregadas, as quais permitem que sejam selecionados um conjunto de dados como entrada, e seja retornado apenas um valor simples como saída. As funções agregadas tipicamente oferecidas por SGBD são: • AVG( ): média; • MIN( ): mínimo; • MAX( ): máximo; • SUM( ): total; e • COUNT( ): contagem. A aplicação das funções agregadas a um conjunto de registros é realizada conjuntamente com a cláusula GROUP BY. Esta cláusula tem a função de agrupar os dados. Como ilustração, o comando a seguir seleciona o nome do vinho e a quantidade do mesmo, para vinhos produzidos entre 1985 e 1990. O nome do vinho é apresentado em ordem alfabética. SELECT wine_name, count(wine_name) FROM wine WHERE year BETWEEN 1985 AND 1990 GROUP BY wine_name ORDER BY wine_name; 2.4.6 HAVING A cláusula HAVING é uma cláusula opcional, e somente deve ser utilizada com funções de agregação. Depois da formação dos grupos com o GROUP BY, a cláusula HAVING é usada para especificar condições que se aplicam sobre as funções de agregação. No comando a seguir, são listados os nomes do vinho e as suas quantidades, para vinhos produzidos entre 1985 e 1990 cuja quantidade seja maior ou igual a oito unidades: SELECT wine_name, count(wine_name) FROM wine WHERE year BETWEEN 1985 AND 1990 GROUP BY wine_name HAVING count(wine_name)>=8; 2.4.7 NULL Testa a existência de valores nulos na tabela. Por exemplo, para se selecionar todos os nomes dos vinhos que não tenham nenhum dado no campo descrição, deve-se utilizar o comando: SELECT DISTINCT wine_name FROM wine WHERE description IS NULL; Caso a intenção seja contrária, deve substituir IS NULL por IS NOT NULL. 2.4.8 UNION / UNION ALL Os comandos descritos nesta seção e nas seções 2.4.9 e 2.4.10 (respectivamente UNION, INTERSECT e EXCEPT) se referem a operações de conjuntos que manipulam resultados de dois comandos SELECT. Para tanto, as relações envolvidas devem ser compatíveis, ou seja, devem retornar o mesmo número de colunas e o mesmo tipo de dado. O comando UNION é equivalente à operação de união da álgebra relacional, e realiza a união de dois conjuntos. Por default, o comando UNION elimina as repetições. Caso deseje-se exibir valores duplicados, deve-se utilizar a cláusula UNION ALL. No exemplo a seguir, são listados os nomes dos clientes que moram em Maringá ou que têm pedido. (SELECT firstname, surname FROM customer WHERE city = ”Maringá”) UNION (SELECT firstname, surname FROM customer, orders WHERE orders.cust_id = customer.cust_id); 2.4.9 INTERSECT / INTERSECT ALL Utilizado para realizar a operação interseção entre dois conjuntos. Também elimina as repetições, mas caso as mesmas sejam necessárias deve-se utilizar o comando INTERSECT ALL. No exemplo a seguir, são listados os nomes dos clientes que moram em Maringá e que têm pedido. (SELECT firstname, surname FROM customer WHERE city = ”Maringá”) INTERSECT (SELECT firstname, surname FROM customer, orders WHERE orders.cust_id = customer.cust_id); 2.4.10 EXCEPT / EXCEPT ALL Equivale à operação de diferença entre conjuntos da álgebra relacional. Para manter as repetições, deve-se usar o comando EXCEPT ALL. No exemplo a seguir, são listados os nomes dos clientes que moram em Maringá, mas que não fizeram pedido. (SELECT firstname, surname FROM customer WHERE city = ”Maringá”) EXCEPT (SELECT firstname, surname FROM customer, orders WHERE orders.cust_id = customer.cust_id); 2.4.11 IN / NOT IN Da mesma forma que o operador INTERSECT, o comando IN é utilizado para verificar em dois conjuntos de dados quais informações estão em ambos os conjuntos. Cada conjunto é composto pelo resultado de um comando SELECT. O comando a seguir retorna o mesmo resultado que o comando da seção 2.4.9, ou seja, lista os clientes que moram em Maringá e que têm pedido: SELECT firstname, surname FROM customer WHERE city = ”Maringá” AND (firstname, surname) IN (SELECT firstname, surname FROM customer, orders WHERE orders.cust_id = customer.cust_id); Já a cláusula NOT IN corresponde à cláusula EXCEPT, verificando a diferença entre dois conjuntos. No comando a seguir são listados os nomes dos clientes que moram em Maringá, mas que não fizeram pedido. SELECT firstname, surname FROM customer WHERE city = ”Maringá” AND (firstname, surname) NOT IN (SELECT firstname, surname FROM customer, orders WHERE orders.cust_id = customer.cust_id); 2.4.12 SOME Para operações de comparação de conjuntos, a SQL oferece alternativas para se escrever as consultas de forma mais simplificada. Para tanto, são utilizadas as cláusulas SOME e ALL. Esta seção descreve a cláusula SOME, ao passo que a seção 2.4.13 descreve a cláusula ALL. A cláusula SOME permite a realização de diversas comparações: • < some: “maior que algum”; • <= some: “maior ou igual a algum”; • >= some: “menor ou igual a algum”; • = some: “igual a algum”; e • <> some: “diferente de algum”. A consulta SQL a seguir lista os nomes dos clientes que moram em Maringá e que recebem salário maior do que algum cliente que mora em São Paulo: SELECT firstname, surname FROM customer WHERE city = ”Maringá” AND salary > SOME (SELECT salary FROM customer WHERE city = “São Paulo”); 2.4.13 ALL Cláusula oferecida pela SQL para simplificar a comparação entre conjuntos. De forma semelhante à cláusula SOME, permite que diversas comparações sejam realizadas, dentre elas: • < all: “maior que todos”; • <= all: “maior ou igual a todos”; • >= all: “menor ou igual a todos”; • = all: “igual a todos”; e • <> all: “diferente de todos”. A consulta SQL a seguir lista os nomes dos clientes que moram em Maringá que recebem salário maior do que todos os clientes que moram em São Paulo: SELECT firstname, surname FROM customer WHERE city = ”Maringá” AND salary > ALL (SELECT salary FROM customer WHERE city = “São Paulo”); 2.4.14 EXISTS / NOT EXISTS A cláusula SQL EXISTS é utilizada para verificação de relações vazias. É um meio para testar se o resultado de uma subconsulta possui alguma tupla. O EXISTS retorna valor TRUE se o resultado da subconsulta não for nulo. Por exemplo, para se listar os nomes dos clientes de Maringá que possuem pedidos, pode-se usar o seguinte comando: SELECT firstname, surname FROM customer WHERE city = ”Maringá” AND EXISTS (SELECT * FROM orders WHERE orders.cust_id = customer.cust_id); A cláusula NOT EXISTS é o contrário da cláusula EXISTS, e retorna TRUE se o resultado da consulta for nulo. Assim, para se listar os nomes dos clientes de Maringá que não possuem pedidos, pode-se usar o seguinte comando: SELECT firstname, surname FROM customer WHERE city = ”Maringá” AND NOT EXISTS (SELECT * FROM orders WHERE orders.cust_id = customer.cust_id); 2.4.15 UNIQUE / NOT UNIQUE Construtor utilizado para a verificação de tuplas repetidas no resultado de uma sub-consulta. Caso o argumento da sub-consulta não possua valores repetidos, o UNIQUE retornará verdadeiro. Caso seja utilizada a cláusula NOT UNIQUE e a sub-consulta não possuir valores repetidos, o resultado será falso. No exemplo a seguir, são listados os clientes que moram em Maringá e que possuem apenas um pedido: SELECT firstname, surname FROM customer WHERE city = ”Maringá” AND UNIQUE (SELECT * FROM orders WHERE orders.cust_id = customer.cust_id); 2.4.16 RELAÇÕES DERIVADAS O nome de relações derivadas é atribuído à utilização de uma sub-consulta na cláusula FROM. Para a utilização das mesmas, deve-se obedecer ao critério de se atribuir um nome à relação resultante e de se renomear seus atributos. O comando a seguir lista a média dos salários dos clientes por cidade para médias de salário maiores de que R$ 1.200,00. SELECT cidade, salario_médio FROM (SELECT city, avg(salary) FROM customer GROUP BY city) AS resultado (cidade, salario_medio) WHERE salario_médio > 1200; 2.4.17 DELETE O comando DELETE remove uma ou mais tuplas de uma relação. Por exemplo, o comando a seguir remove da tabela wine todos os vinhos cujo tipo está definido como RED: DELETE FROM wine WHERE type = 'RED'; A cláusula WHERE pode ser vazia, o que causa a remoção de todas as tuplas da relação. Por exemplo: DELETE FROM wine; 2.4.18 INSERT A inserção de dados em uma relação pode ocorrer de duas formas. Na primeira forma, devese especificar a tupla a ser inserida na relação. Já a segunda forma diz respeito à inserção dos dados resultantes de uma consulta, respeitando-se os tipos de dados de cada atributo. Os comandos a seguir exemplificam estas duas formas de inserção. O primeiro exemplo é ilustra a especificação da tupla a ser inserida. Neste exemplo é inserido na tabela wine um registro com wine_id 172, que possui o nome Kinsala, do tipo Vermelho, do ano de 1970 e com o campo descrição em branco. INSERT INTO wine VALUES (172,'Kinsala','Red',1970,50,NULL); O próximo exemplo faz a inserção dos dados resultantes de uma consulta. Nele é inserido um registro na tabela wine baseado no resultado de uma consulta que busca o nome e descrição da região que possui wine_id 15. Esses dois dados são o nome do vinho e sua descrição. Já o tipo foi especificado na cláusula SELECT como sendo “tipo regional” e o ano especificado como “2005”. INSERT INTO wine (wine_name, type, year, description) SELECT region_name, ‘Tipo Regional’, 2005, description FROM region WHERE region_id = 15; 2.4.19 UPDATE Comando utilizado para alteração de valores dos atributos de uma tupla. O comando a seguir altera o tipo do vinho que possui o wine_id 26 para “red sweet” e seu ano para “2001”. UPDATE wine SET type= 'Red Sweet', year= 2001 WHERE wine_id=26; 2.4.20 JOIN Os comandos derivados da cláusula JOIN são responsáveis pela composição de relações, ou seja, com eles é possível realizar a junção de várias relações. Os tipos de junções que podem ser utilizados na SQL padrão SQL-92 são: INNER JOIN, LEFT OUTER JOIN, RIGHT OUTER JOIN e FULL OUTER JOIN. Esses tipos de junção são declarados na cláusula FROM. O comando a seguir lista os nomes dos clientes que moram em Maringá e que têm pedido. SELECT firstname, surname FROM customer JOIN orders ON customer.cust_id = orders.cust_id WHERE city = “Maringá”; 2.5 Funcionalidades oferecidas pelos SGBD MySQL e PostgreSQL A Tabela 2.2 ilustra as funcionalidades oferecidas pelos SGBD MySQL e PostgreSQL em termos de linguagem de definição de dados. COMANDOS SQL DDL CREATE TABLE KEY PRIMARY KEY FOREIGN KEY NOT NULL DEFAULT UNIQUE CHECK DROP TABLE ALTER TABLE CREATE VIEW DROP VIEW MySQL Sim Sim Sim Sim Sim Sim Sim Sim Sim Sim Não Não PostgreSQL Sim Sim Sim Sim Sim Sim Sim Sim Sim Sim Sim Sim Tabela 2.2 – Comandos SQL DDL oferecidos pelos SGBDs em estudo. Apenas por questões de completude, a Tabela 2.3 enumera os tipos de dados para os quais os SGBD MySQL e PostgreSQL oferecem suporte. Tipo de Dados Tipos Numéricos TINYINT SMALLINT MEDIUMINT INT BIGINT FLOAT DOUBLE DOUBLE PRECISION REAL MySQL PostgreSQL Sim Sim Sim Sim Sim Sim Sim Sim Sim Não Sim Não Sim Sim Sim Não Sim Sim DECIMAL SERIAL MONEY Tipos Data e Hora DATE DATETIME TIMESTAMP TIME YEAR INTERVAL TIME WITH TIME ZONE Tipos String CHAR VARCHAR TINYBLOB / TINYTEXT BLOB / TEXT MEDIUMBLOB / MEDIUMTEXT LONGBLOB / LONGTEXT ENUM SET BIT VARBIT Tipos Booleanos BOOL Tipos Geométricos POINT LINE LSEG BOX PATH POLYGON CIRCLE Tipos Endereço de Rede CIDR INET MASCADDR Sim Não Não Sim Sim Sim Sim Sim Sim Sim Sim Não Não Sim Não Sim Sim Não Sim Sim Sim Sim Sim Sim Sim Sim Sim Sim Não Não Sim Sim Não Sim Não Não Não Não Sim Sim Sim Sim Não Não Não Não Não Não Não Sim Sim Sim Sim Sim Sim Sim Não Não Não Sim Sim Sim Tabela 2.3 – Tipos de dados disponíveis pelo SGBD MySQL e PostgreSQL. A Tabela 2.4 ilustra as funcionalidades oferecidas pelos SGBD MySQL e PostgreSQL em termos de linguagem de manipulação de dados. COMANDOS SQL DML SELECT FROM WHERE ORDER BY GROUP BY MySQL Sim Sim Sim Sim Sim PostgreSQL Sim Sim Sim Sim Sim HAVING NULL UNION / UNION ALL INTERSECT / INTERSECT ALL EXCEPT / EXCEPT ALL IN / NOT IN SOME ALL EXISTS / NOT EXISTS UNIQUE / NOT UNIQUE RELAÇÕES DERIVADAS DELETE INSERT UPDATE JOIN INNER JOIN LEFT OUTER JOIN RIGHT OUTER JOIN FULL OUTER JOIN Sim Sim Sim Não Não Não Não Não Não Não Não Sim Sim Sim Sim Sim Sim Sim Sim Sim Sim Sim Sim Sim Sim Sim Sim Sim Não Não Sim Sim Sim Sim Sim Sim Sim Sim Tabela 2.4 – Comandos SQL DML oferecidos pelos SGBDs em estudo. O preenchimento das Tabelas 2.2 e 2.4 envolveram as seguintes atividades: • Criação da base de dados especificada na Seção 2.1, tanto no SGBD MySQL quanto no SGBD PostgreSQL; • Povoamento de cada uma das tabelas; e • Execução das mesmas consultas em ambos os SGBD. Note que o objetivo deste trabalho é apresentar e analisar a implementação dos comandos padrão SQL-92. No momento, não se pretende comparar as funções adicionais que um dos SGBD em estudo oferece em relação ao outro, tais como: • Funções matemáticas: abs( ), sin( ) e sqrt( ); • Funções para comparação e operação com Strings: concat( ), length( ) e lower( ); e • Funções de Data e Hora: curdate( ), dayname( ) e now( ). 2.6 Considerações Finais Este capítulo descreveu as principais características dos comandos SQL que um SGBD deve oferecer segundo o padrão SQL-92. Os comandos listados foram testados tanto no SGBD MySQL quanto no SGBD PostgreSQL, gerando uma tabela comparativa entre estes dois SGBD. Com base na comparação entre o MySQL e PostgreSQL, conclui-se que nas versões em estudo, o PostgreSQL oferece mais funcionalidades implementadas, seguindo de forma mais completa o padrão SQL-92. Mas observa-se em MySQL (2004) que o MySQL já tem em desenvolvimento suas próximas versões, que incorporarão, por exemplo, a implementação de visões. Capítulo 3 Funções de acesso da linguagem PHP ao Sistema Gerenciador de Banco de Dados MySQL O objetivo deste capítulo é identificar quais as funções de acesso que a linguagem de programação PHP oferece para que seja realizada a conexão com o SGBD MySQL. Na identificação das funções, é destacada a sintaxe de cada uma, seus parâmetros e um exemplo de utilização de cada função. Neste capítulo também são exibidas, na forma de uma tabela, todas as funções de acesso que o PHP dispõe para conexões com o SGBD sob estudo. Esta tabela será utilizada no Capítulo 4 para a realização de um estudo comparativo entre as funcionalidades descritas no presente capítulo e as funcionalidades oferecidas pela linguagem PHP para acesso ao SGBD PostGreSQL. Na Seção 3.1 são identificadas as funções de acesso do PHP ao MySQL. Uma tabela contendo um resumo das funções de conexão do PHP ao SGBD MySQL é apresentada na Seção 3.2. Na Seção 3.3 é finalizado o capítulo, com as considerações finais. 3.1 Funções de Acesso do PHP ao MySQL Essa seção destaca as principais funções de acesso da linguagem PHP ao SGBD MySQL, com base nos materiais de Williams & Lane (2002), MySQL (2004), Ciferri & Ciferri (2003) e Converse & Park (2001). Essas funções de acesso são descritas em termos de sua sintaxe e de seus parâmetros. Para cada função de acesso, é apresentado um exemplo de utilização. Na sintaxe das funções, parâmetros entre [ ] representam parâmetros opcionais. 3.1.1 Função mysql_connect( ) Inicia uma conexão com o SGBD MySQL. Sintaxe: • resource mysql_connect ( [string host],[string username], [string password] ) Parâmetros: • string host: Nome ou endereço da máquina servidora do SGBD MySQL; • string username: Nome do usuário no SGBD MySQL; e • string password: Senha do usuário no SGBD MySQL. Exemplo: • $conexão = mysql_connect ("localhost", "ricardo", "123456"); 3.1.2 Função mysql_select_db( ) Seleciona uma base de dados do MySQL. Em caso de erro, essa função retorna false. Sintaxe: • int mysql_select_db ( string database,[resource connection] ) Parâmetros: • string database: Nome do banco de dados; e • resource connection: Nome da conexão com o SGBD. Exemplo: • mysql_select_db ("winestore", $conexão); 3.1.3 Função mysql_query( ) Utiliza-se essa função para submeter uma consulta ao SGBD MySQL. Em caso de sucesso na realização da consulta, a função retorna o conjunto resultado contendo as tuplas solicitadas. Caso contrário, a função retorna false. Sintaxe: • resource mysql_query ( string command,[resource connection] ) Parâmetros: • string command: Comando SQL; e • resource connection: Nome da Conexão com o SGBD. Exemplo: • $resultado = mysql_query ("SELECT * FROM wine",$conexão); 3.1.4 Função mysql_fetch_row( ) Recupera uma tupla do conjunto resultado na forma de um array enumerado. Essa função retorna false se não existirem mais tuplas a serem recuperadas. Sintaxe: • array mysql_fetch_row ( resource result_set ) Parâmetros: • resource result_set: Conjunto resultado. Exemplo: • $linha = mysql_fetch_row ($resultado); echo "Código Cliente: $linha[0] <br>"; echo "Nome Cliente: $linha[1] <br>"; 3.1.5 Função mysql_num_fields( ) Retorna o número de atributos na tupla. Sintaxe: • int mysql_num_fields ( resource result_set ) Parâmetros: • resource result_set: Conjunto resultado. Exemplo: • $atributos = mysql_num_fields ($resultado); 3.1.6 Função mysql_close( ) Fecha a conexão com o SGBD MySQL. Sintaxe: • int mysql_close ( [resource connection] ) Parâmetros: • resource connection: Nome da conexão com o SGBD. Exemplo: • mysql_close ($conexão); 3.1.7 Função mysql_data_seek( ) Recupera apenas algumas tuplas do conjunto resultado de uma consulta. Em caso de erro, a função retorna false. Sintaxe: • int mysql_data_seek ( resource result_set, int row ) Parâmetros: • resource result_set: Conjunto resultado; e • int row: Linha a partir da qual as tuplas serão recuperadas. Exemplo: • mysql_data_seek ($resultado, 3 ) 3.1.8 Função mysql_fetch_array( ) Versão estendida do mysql_fetch_row( ), a qual recupera uma tupla do conjunto resultado na forma de um array associativo. Isto permite o acesso aos valores pelos nomes dos atributos da tabela. Quando não existirem mais tuplas a serem processadas, a função retornará o valor false. Sintaxe: • array mysql_fetch_array ( resource result_set, [int result_type] ) Parâmetros: • resource result_set: Conjunto resultado; e • int result_type: Tipo de resultado. Exemplo: • $linha = mysql_fetch_array ($resultado); echo "Código Cliente: $linha[cust_id] <br>"; echo "Nome Cliente: $linha[surname] <br>"; 3.1.9 Função mysql_fetch_object( ) Esta é mais uma versão estendida do mysql_fetch_row( ), a qual recupera uma tupla do conjunto resultado na forma de objeto. Isto permite que o acesso aos valores do objeto seja realizado pelos nomes dos atributos da tabela. Essa função retorna false quando não existirem mais tuplas a serem processadas. Sintaxe: • object mysql_fetch_object (resource result_set, [int result_type]) Parâmetros: • resource result_set: Conjunto resultado; e • int result_type: Tipo de resultado. (opcional) Exemplo: • $objeto = mysql_fetch_object ($resultado); echo "Código Cliente: $objeto->cust_id <br>"; echo "Nome Cliente: $objeto->surname <br>"; 3.1.10 Função mysql_free_result( ) Esta função tem a finalidade de liberar a memória utilizada pelo conjunto resultado. Em caso de erro, a função retorna false. Sintaxe: • int mysql_free_result (resource result_set) Parâmetros: • resource result_set: Conjunto resultado. Exemplo: • mysql_free_result ($resultado); 3.1.11 Função mysql_num_rows( ) Retorna o número de tuplas do conjunto resultado. Em caso de erro, a função retorna false. Sintaxe: • int mysql_num_rows ( resource result_set ) Parâmetros: • resource result_set: Conjunto resultado. Exemplo: • $nro_tuplas = mysql_num_rows ($resultado); 3.1.12 Função mysql_pconnect( ) Função que possui um objetivo semelhante ao objetivo da função mysql_connect( ): abrir uma conexão com o SGBD MySQL. Mas a função mysql_pconnect( ) abre uma conexão permanente com o SGBD. Isto significa que a conexão não é fechada quando o script termina. Adicionalmente, uma conexão aberta com mysql_connect( ) não pode ser fechada com a função mysql_close( ). Sintaxe: • resource mysql_pconnect ( [string host],[string username], [string password] ) • string host: Nome ou endereço da máquina servidora do SGBD MySQL; • string username: Nome do usuário no SGBD MySQL; e • string password: Senha do usuário no SGBD MySQL. Exemplo: • $conexão = mysql_pconnect ("localhost", "ricardo", "123456"); 3.1.13 Função mysql_change_user( ) O objetivo desta função é alterar o usuário corrente do SGBD MySQL para um novo usuário. Em caso de erro, a função retorna false e a conexão anterior permanece a corrente. Sintaxe: • int mysql_change_user (string user, string password, [string database,[resource connection]] ) Parâmetros: • string user: Nome do usuário; • string password: Senha de acesso do usuário; • string database: Nome da base de dados; e • resource connection: Nome da conexão. Exemplo: • mysql_change_user (root, 123mudar, "winestore", $conexão) 3.1.14 Função mysql_create_db( ) Função utilizada para se criar um novo banco de dados no MySQL, retornando false em caso de erro. Sintaxe: • int mysql_create_db (string database,[resource connection] ) Parâmetros: • string database: Nome do Banco de Dados; e • resource connection: Nome da conexão do SGBD MySQL. Exemplo: • mysql_create_db (“teste”, $conexão); 3.1.15 Função mysql_drop_db( ) Remove um banco de dados do SGBD MySQL, retornando false em caso de erro. Sintaxe: • int mysql_drop_db (string database,[resource connection] ) Parâmetros: • string database: Nome do banco de dados; e • resource connection: Nome da conexão. Exemplo: • mysql_drop_db(“teste”, $conexão); 3.1.16 Função mysql_fetch_field( ) Através desta função obtém-se o metadado para um atributo da relação. É retornado false em caso de erro. Caso contrário, a função retorna um objeto com as seguintes propriedades: • name: Nome do atributo; • table: Nome da tabela à qual o atributo pertence; • max_length: Comprimento máximo do atributo; • not_null 1: Se o atributo não pode ser NULL; • primary_key 1: Se o atributo faz parte da chave primária; • unique_key 1: Se existe a restrição UNIQUE; • multiple_key 1: Se o atributo não é uma chave única; • numeric 1: Se o atributo é do tipo numérico; • blob 1: Se o atributo é do tipo BLOB; • type: Tipo do atributo; • unsigned 1: Se o atributo é do tipo numérico sem sinal; e • zerofill 1: Se a coluna numérica é preenchida com 0. Sintaxe: • object mysql_fetch_field ( resource result_set,[int attribute_name]) Parâmetros: • resource result_set: Conjunto Resultado; e • int attribute_name: Número do atributo. Exemplo: $info = mysql_fetch_field ($resultado); 3.1.17 Função mysql_list_tables( ) Lista as tabelas do banco de dados. Em caso de erro, o valor retornado pela função é false. Sintaxe: • resource mysql_list_tables ( string database,[resource connection] ) Parâmetros: • string database: Nome da base de dados; e • resource connection: Nome da conexão. Exemplo: • $tabelas = mysql_list_tables ("winestore",$conexão); 3.1.18 Função mysql_tablename( ) Esta função tem o objetivo de retornar o nome de uma tabela. Caso haja erro durante a execução do comando, o valor retornado pela função é false. Esta função deve ser utilizada em conjunto com a função mysql_list_tables( ). Sintaxe: • string mysql_tablename ( resource result, int table_number ) Parâmetros: • resource result: Conjunto resultado; e • int table_number: Número da tabela. Exemplo: • $tabelas = mysql_list_tables ("winestore",$conexão); echo mysql_tablename ($tabelas, 3); 3.1.19 Função mysql_errno( ) Retorna o número do último erro ocorrido na conexão passada por parâmetro. Sintaxe: • int mysql_errno ([resource connection]) Parâmetros: • resource connection: Nome da conexão. Exemplo: • mysql_errno ($conexão); 3.1.20 Função mysql_error( ) Esta função retorna a descrição do último erro ocorrido na conexão que teve seu nome passado como parâmetro. Esta descrição é retornada na forma de string. Sintaxe: • int mysql_error ( [resource 4connection] ) Parâmetros: • resource connection: Nome da conexão. Exemplo: • mysql_error ($conexão); 3.1.21 Função mysql_affected_rows( ) Essa função tem a finalidade de retornar a quantidade de linhas que foram alteradas depois da execução de um comando SQL que foi executado de forma correta. Em outras palavras, depois da execução dos comandos INSERT, UPDATE ou DELETE, pode-se utilizar a função mysql_affected_rows( ) para verificar quantas linhas foram alteradas em decorrência do processamento de algum desses comandos. Sintaxe: • int mysql_affected_rows ( [resource connection] ) Parâmetros: • resource connection: Nome da conexão. Exemplo: • $operação = "UPDATE customer SET firstname = 'Ricardo' WHERE cust_id = 2"; mysql_query($operação, $connection); $alt = mysql_affected_rows($conexão); if (alt == 1) {echo "Alteração feita com Sucesso!";} else {echo "Alteração não realizada!";} 3.1.22 Função mysql_insert_id( ) Retorna o valor da chave primária da última tupla inserida no banco de dados. Sintaxe: • int mysql_insert_id ([resource connection]) Parâmetros: • resource connection: Nome da conexão. Exemplo: • $operação = "INSERT INTO customer (cust_id, firstname) VALUES (NULL, 'Kelly')"; mysql_query($operação, $conexão); $alt = mysql_affected_rows($conexão); if (alt == 1) { echo "Inclusão realizada com Sucesso!"; $cod_cli = mysql_insert_id($conexão); echo $cód_cli; } else {echo "Alteração não realizada!";} 3.2 Funções oferecidas pelo PHP para acesso aos dados no SGBD MySQL As funções da linguagem PHP para acesso ao SGBD MySQL são descritas resumidamente na Tabela 3.1. Funções de Conexão do PHP com MySQL Descrição mysql_connect( ) Inicia uma conexão com o SGBD MySQL mysql_select_db( ) Seleciona uma base de dados do SGBD MySQL mysql_query( ) Submete uma consulta ao SGBD MySQL mysql_fetch_row( ) Recupera uma tupla do conjunto resultado na forma de um array enumerado mysql_num_fields( ) Retorna o número de atributos na tupla mysql_close( ) Fecha a conexão com o SGBD MySQL mysql_data_seek( ) Recupera algumas tuplas do conjunto resultado mysql_fetch_array( ) Recupera uma tupla do conjunto resultado na forma de um array associativo mysql_fetch_object( ) Recupera uma tupla do conjunto resultado na forma de objeto mysql_free_result( ) Libera a memória utilizada pelo conjunto resultado mysql_num_rows( ) Retorna o número de tuplas do conjunto resultado mysql_pconnect( ) Abre uma conexão permanente com o SGBD MySQL mysql_change_user( ) Altera o usuário corrente para um novo usuário mysql_create_db( ) Cria um novo banco de dados no SGBD MySQL mysql_drop_db( ) Remove um banco de dados do SGBD MySQL mysql_fetch_field( ) Obtém o metadado para um atributo da relação mysql_list_tables( ) Lista as tabelas do banco de dados mysql_tablename( ) Retorna o nome de uma tabela mysql_errno( ) Retorna o número do último erro ocorrido na conexão mysql_error( ) Retorna a descrição do último erro ocorrido na conexão mysql_affected_rows( ) Retorna a quantidade de linhas que foram alteradas depois da execução de um comando SQL mysql_insert_id( ) Retorna o valor da chave primária da última tupla inserida Tabela 3.1 Funções PHP para conexão com o SGBD MySQL 3.3 – Considerações Finais Neste capítulo foram apresentadas as funções que a linguagem de programação PHP oferece para o acesso ao SGBD MySQL. A Tabela 3.1 apresenta um resumo destas funções. Esta tabela será utilizada no Capítulo 4 para a realização de um estudo comparativo entre as funcionalidades descritas no presente capítulo e as funcionalidades oferecidas pela linguagem PHP para acesso ao SGBD PostgreSQL. Capítulo 4 Funções de acesso da linguagem PHP ao Sistema Gerenciador de Banco de Dados PostgreSQL O objetivo deste capítulo é identificar quais as funções de acesso que a linguagem de programação PHP oferece para que seja realizada a conexão com o SGBD PostgreSQL. Na identificação das funções, é destacada a sintaxe de cada uma, seus parâmetros e um exemplo de utilização de cada função. As funções investigadas no desenvolvimento desta monografia de especialização são resumidas na forma de uma tabela. Adicionalmente, este capítulo também exibe, em uma tabela comparativa, todas as funções de acesso que o PHP dispõe para conexões com os SGBD sob estudo. Por meio desta tabela, podese verificar a equivalência entre as funções do PHP para o MySQL e as funções do PHP para o PostgreSQL. Na Seção 4.1 são identificadas as funções de acesso do PHP ao PostgreSQL. Na Seção 4.2 é exibida a tabela que resume as funções estudadas e investigadas. Uma tabela comparativa contendo as funções de conexão do PHP com cada um dos SGBD em estudo é apresentada na Seção 4.3. Na Seção 4.4 é finalizado o capítulo, com as considerações finais. 4.1 Funções de Acesso do PHP ao PostgreSQL Nesta seção são apresentadas as principais funções da linguagem PHP para que seja efetuado o acesso ao SGBD PosgreSQL. A elaboração desta seção é baseada em Neves (2002), Niederauer (2001) e PostgreSQL 7.3.2 (2004). As funções de acesso são descritas em termos de sua sintaxe e de seus parâmetros. Para cada função de acesso, é apresentado um exemplo de utilização. 4.1.1 Função pg_connect( ) Abre uma conexão com um servidor de banco de dados PostgreSQL especificado no parâmetro. Retorna um recurso (i.e., resource) de conexão, o qual é necessário para outras funções PostgreSQL. Sintaxe: • resource pg_connect ( [string host], [string port], [string dbname], [string username], [string password] ) Parâmetros: • string host: Nome ou endereço da máquina servidora do SGBD PostgreSQL; • string port: Porta que será usada para conexão com o servidor PostgreSQL; • string dbname: Nome do banco de dados; • string username: Nome do usuário no SGBD PostgreSQL; e • string password: Senha do usuário no SGBD PostgreSQL.. Exemplo: • $conexão = pg_connect("host=ovelha port=5432 dbname=imasters user=joao password=123"); 4.1.2 Função pg_query( ) Envia um comando SQL para o banco de dados PostgreSQL especificado pelo recurso de conexão connection. O valor de retorno dessa função é um recurso (i.e., resource), o qual contém o resultado da consulta. Sintaxe: • resource pg_query( resource connection, string query ) Parâmetros: • resource connection: Nome da Conexão com o SGBD; e • string query: Comando SQL. Exemplo: • $resultado = pg_query ($conexão, "SELECT * FROM wine"); 4.1.3 Função pg_fetch_row( ) Essa função retorna uma linha de dados, a qual é recuperada como um array. Cada coluna do resultado é armazenada em um índice do array, iniciando-se no índice 0. Caso não existam mais linhas, a função pg_fetch_row ( ) retorna false. Sintaxe: • array pg_fetch_row( resource result, int row ) Parâmetros: • resource result: Conjunto resultado; e • int row: Número da linha. Exemplo: • $row = pg_fetch_row($result,2) 4.1.4 Função pg_num_fields ( ) Retorna o número de colunas de um conjunto resultado. O argumento é um recurso (i.e., resource) de resultado criado a partir de pg_query( ). Esta função retorna -1 em caso de erro. Sintaxe: • int pg_num_fields(resource result) Parâmetros: • resource result: Conjunto resultado. Exemplo: • $resultado = pg_query ($conexão, "SELECT * FROM wine"); $atributos = pg_num_fields ($resultado); 4.1.5 Função pg_close( ) Fecha uma conexão não persistente com o servidor de banco de dados PostgreSQL. Retorna true em caso de sucesso ou false caso haja falha. Sintaxe: • bool pg_close(resource connection) Parâmetros: • resource connection: Nome da conexão com o SGBD. Exemplo: • pg_close($conexao); 4.1.6 Função pg_fetch_array( ) Retorna um array que corresponde a uma linha, ou false se não existirem mais linhas. É uma versão estendida da função pg_fetch_row( ). Além de armazenar os dados em índices numéricos no array resultante, pg_fetch_array( ) também armazena os dados em chaves associativas (i.e., nome do campo) como padrão. Sintaxe: • array pg_fetch_array(resource result, [int row, result_type]]) Parâmetros: • resource result: Conjunto resultado; • int row: Número da linha; e • int result_type: Tipo de Dados. Exemplo: • $result = pg_query($conn, "SELECT * FROM customer"); $arr = pg_fetch_array($result, 0, PGSQL_NUM); echo $arr[0] . " <- array\n"; $arr = pg_fetch_array($result, 1, PGSQL_ASSOC); echo $arr["firstname"] . " <- array\n"; [int 4.1.7 Função pg_fetch_object( ) Retorna um objeto com propriedades que correspondem à linha recuperada. Caso não existam mais linhas ou ocorra um erro, esta função retorna false. A função pg_fetch_object ( ) é similar à função pg_fetch_array( ), com a diferença de que retorna um objeto, ao invés de um array. Como resultado, os dados podem ser acessados somente através dos nomes de campos. Sintaxe: • objeto pg_fetch_object(resource result, int row, [int result_type]) Parâmetros: • resource result:Conjunto resultado; • int row: Número da linha; e • int result_type: Tipo de resultado. Exemplo: • $result = pg_query($db_conn, "SELECT * FROM customer"); $dados = pg_fetch_object($result, 1); echo $dados->cust_id ."\n"; echo $dados->surname .\n"; 4.1.8 Função pg_free_result( ) Tem a finalidade de liberar a memória utilizada pelo conjunto resultado. Todos os resultados são liberados da memória automaticamente assim que o script terminar a sua execução. Esta função retorna true em caso de sucesso ou false caso haja falha. Sintaxe: • bool pg_free_result( resource result ) Parâmetros: • resource result: Conjunto resultado. Exemplo: • pg_free_result($result); 4.1.9 Função pg_num_rows( ) Esta função retorna o número de linhas no conjunto resultado, ou -1 em caso de erro. Sintaxe: • int pg_num_rows(resource result) Parâmetros: • resource resul: Conjunto resultado. Exemplo: • $nro_tuplas = pg_num_rows ($resultado); 4.1.10 Função pg_pconnect( ) Abre uma conexão com um banco de dados PostgreSQL. Esta conexão não é fechada quando o script termina. Sintaxe: • resource pg_pconnect([string host], [string port], dbname], [string username], [string password]) Parâmetros: • string host: Nome ou endereço da máquina servidora do SGBD PostgreSQL; • string port: Porta que será usada para conexão com o servidor PostgreSQL; • string dbname: Nome do banco de dados; • string username: Nome do usuário no SGBD PostgreSQL; e • string password: Senha do usuário no SGBD PostgreSQL.. [string Exemplo: • $conexão = pg_pconnect("host=ovelha port=5432 dbname=imasters user=joao password=123"); 4.1.11 Função pg_last_error( ) Retorna a última mensagem de erro para a conexão representada por connection. As mensagens de erro podem ser sobrescritas por chamadas internas ao PostgreSQL(libpq). Se múltiplos erros ocorrerem dentro de um módulo de função do PostgreSQL, então a função pode não retornar a mensagem de erro correta. Sintaxe: • string pg_last_error(resource connection) Parâmetros: • resource connection: Nome da conexão. Exemplo: • pg_last_error ($conexão); 4.1.12 Função pg_affected_rows( ) Retorna o número de linhas afetadas por consultas INSERT, UPDATE e DELETE executados pela função pg_query( ). Se nenhuma linha foi afetada, pg_affected_rows( ) retorna 0. Sintaxe: • int pg_affected_rows(resource result) Parâmetros: • resource result: Conjunto Resultado. Exemplo: • $operação = "INSERT INTO customer (cust_id, firstname) VALUES (NULL,'Ricardo')"; $resultado = pg_query($conexao, $operação); $numLinhas = pg_affected_rows($resultado); echo $numLinhas; 4.1.13 Função pg_getlastoid( ) Retorna o identificador da última tupla inserida no banco de dados, ou -1 em caso de erro. Sintaxe: • int pg_getlastoid (resource result) Parâmetros: • resource result: Conjunto Resultado. Exemplo: • $operação = "INSERT INTO customer (cust_id, firstname) VALUES (NULL,'Ricardo')"; $resultado = pg_query($conexao, $operação); $identificador = pg_getlastoid($resultado); echo $identificador; 4.2 Funções oferecidas pelo PHP para acesso aos dados no SGBD PostgreSQL As funções da linguagem PHP para acesso ao SGBD PostgreSQL são descritas resumidamente na Tabela 4.1. Funções de Conexão do PHP com PostgreSQL Descrição pg_connect( ) Inicia uma conexão com o SGBD PostgreSQL pg_query( ) Envia um comando SQL para o SGBD PostgreSQL pg_fetch_row( ) Retorna uma linha de dados em um array pg_num_fields ( ) Retorna o número de colunas de um conjunto resultado pg_close( ) Fecha uma conexão não persistente com o SGBD PostgreSQL pg_fetch_array( ) Retorna um array que corresponde a uma linha pg_fetch_object( ) Retorna um objeto com propriedades que correspondem à linha recuperada pg_free_result( ) Libera a memória utilizada pelo conjunto resultado pg_num_rows( ) Retorna o número de linhas no conjunto resultado pg_pconnect( ) Abre uma conexão persistente com o SGBD PostgreSQL pg_last_error( ) Retorna a última mensagem de erro para a conexão pg_affected_rows( ) Retorna o número de linhas afetadas por consultas INSERT, UPDATE e DELETE pg_getlastoid( ) Retorna o identificador da última tupla inserida Tabela 4.1 Funções PHP para conexão com o SGBD PostgreeSQL 4.3 Funções oferecidas pelo PHP para acesso aos dados no SGBD MySQL e no SGBD PostgreSQL A Tabela 4.2 é uma tabela comparativa das funções da linguagem PHP para acesso aos SGBD MySQL e SGBD PostgreSQL. Esta tabela é fruto do estudo de toda referência apresentada no Capítulo 3 e nas Seções 4.1 e 4.2. Funções de Conexão do PHP com MySQL Funções de Conexão do PHP com PostgreSQL mysql_connect( ) pg_connect( ) mysql_select_db( ) * Base selecionada na conexão: pg_connect( ) mysql_query( ) pg_query( ) mysql_fetch_row( ) pg_fetch_row( ) mysql_num_fields( ) pg_num_fields( ) mysql_close( ) pg_close( ) mysql_data_seek( ) mysql_fetch_array( ) pg_fetch_array( ) mysql_fetch_object( ) pg_fetch_object( ) mysql_free_result( ) pg_free_result( ) mysql_num_rows( ) pg_num_rows( ) mysql_pconnect( ) pg_pconnect( ) mysql_change_user( ) mysql_create_db( ) mysql_drop_db( ) mysql_fetch_field( ) mysql_list_tables( ) mysql_tablename( ) mysql_errno( ) mysql_error( ) pg_last_error( ) mysql_affected_rows( ) pg_affected_rows( ) mysql_insert_id( ) pg_getlastoid( ) Tabela 4.2 Funções PHP para conexão com o SGBD MySQL e com o SGBD PostgreSQL Observando a Tabela 4.1, vale destacar que a função pg_connect( ) tem a mesma funcionalidade que duas funções diferentes do PHP para o MySQL: a função mysql_connect( ) e a função mysql_select_db( ). A função pg_connect( ), além de realizar a conexão com o banco de dados, também seleciona a base de dados. Em se tratando de um script que acessa apenas uma base de dados, isso significa que serão necessárias menos linhas de programação. Por outro lado, para se trabalhar com outra base de dados no mesmo script, deve-se abrir uma nova conexão selecionando a base desejada. Isto torna esse processo um pouco mais trabalhoso do que o processo similar realizado utilizando-se o SGBD MySQL. 4.4 Considerações Finais Neste capítulo foram apresentadas, primeiramente, as funções que a linguagem de programação PHP oferece para o acesso ao SGBD PostgreSQL. As funções de acesso identificadas foram comparadas com as funções que a linguagem PHP oferece para o acesso ao SGBD MySQL. Essa atividade gerou a tabela comparativa descrita na Seção 4.3, a qual apresenta a equivalência entre as funções para cada SGBD. Pode-se verificar que atualmente o PHP oferece maior diversidade de funções para conexão com o MySQL. A principal razão para este fato é que o SGBD MySQL tem sido amplamente utilizado no desenvolvimento de aplicações para a Web, contribuindo para que as funções PHP de acesso sejam melhoradas e estendidas. Em contrapartida, somente mais recentemente o SGBD PostgreSQL tem sido utilizado para o desenvolvimento de aplicações para a Web. Entretanto, pelo fato do SGBD PostgreSQL disponibilizar maior funcionalidade com relação à DDL SQL e à DML SQL, como pode ser observado no Capítulo 2, o uso deste SGBD está sendo amplamente difundido. Capítulo 5 Aplicação de Banco de Dados utilizando o SGBD PostgreSQL e a Linguagem de Programação PHP Neste capítulo foi utilizada a base de dados winestore, descrita na Seção 2.1, para aplicar as funções de acesso ao SGBD PostgreSQL da linguagem PHP. Este capítulo apresenta os scripts desenvolvidos durante este trabalho. Esses scripts são voltados à realização de consultas simples (Seção 5.3) e à realização de consultas utilizando mais de uma tabela (Seções 5.4 e 5.5). Nas seções 5.6 e 5.7, são apresentados respectivamente, scripts de inclusão e alteração de registros. Informações complementares são discutidas na Seção 5.1, a qual destaca alguns detalhes adicionais relativos à descrição da aplicação. Já a Seção 5.2 apresenta as telas principais da aplicação (i.e., interface). A Seção 5.8, por sua vez, conclui o capítulo. 5.1 – Aplicação Base Na Seção 2.1 foram apresentados os comandos SQL para a criação do banco de dados da vinícola winestore. Esses comandos foram submetidos ao SGBD PostgreSQL, criando a base de dados a ser utilizada no desenvolvimento da aplicação descrita neste capítulo. 5.2 – Telas Principais da Aplicação A Figura 5.1 ilustra a tela inicial da aplicação desenvolvida. Esta tela é exibida ao se executar a aplicação. Figura 5.1 – Tela inicial da aplicação. Nesta tela são exibidas cinco opções: • Consulta Simples: utiliza apenas uma tabela; • Consulta com 2 Tabelas: utiliza duas tabelas; • Consulta com 3 Tabelas: utiliza três tabelas; • Inserção de Dados: inclui registros no SGBD; e • Alteração de Dados: altera registros no SGBD. Figura 5.2 – Primeira tela da Consulta com 2 Tabelas A Figura 5.2 exibe a primeira tela da consulta utilizando 2 tabelas, nela o usuário seleciona o cliente, para que seja apresentado na próxima tela a quantidade de vinhos comprados pelo mesmo. O resultado dessa consulta observa-se na Figura 5.3. Figura 5.3 – Tela resultado da Consulta com 2 Tabelas Figura 5.4 – Primeira tela do script de alteração de registros A Figura 5.4 mostra a primeira tela do script de alteração de registros. Para realização efetiva da alteração de um registro utilizamos mais três telas. Na tela mostrada pela Figura 5.4, o usuário informa ao sistema as iniciais da vinícola que se pretende alterar. Logo após é apresentada uma tela na qual são listadas todas vinícolas que atendem a condição, solicitando ao usuário que selecione a vinícola que se pretende alterar (Figura 5.5). Na Figura 5.6 temos na tela subseqüente que traz os atuais dados da vinícola, permitindo a alteração dos mesmos. A Figura 5.7 mostra a tela de confirmação da alteração dos dados. Figura 5.5 – Segunda tela do script de alteração de registros Figura 5.6 – Terceira tela do script de alteração de registros Figura 5.7 – Quarta tela do script de alteração de registros 5.3 – Script para realização de uma consulta Simples Esta seção descreve um script para uma consulta simples. Esta consulta tem como objetivo pesquisar no banco de dados todos os compradores que moram em determinada cidade, utilizando apenas uma tabela e apresentar os resultados obtidos. Primeira parte do Script: 001.php (Formulário) <HTML><HEAD><TITLE>Desenvolvimento de Sistemas para Web</TITLE> </HEAD> <BODY> <html> <center> <font color=blue><h1>Desenvolvimento de Sistemas para Web</h1></font> <h1>Banco de Dados</h1> <hr> <font color=red><h2>Consulta Simples</h2></font><hr> <font color=blue><h4>Selecionar os Compradores de Moram em Determinada Cidade.</h4></font> <font color=black><h4>SQL:&nbsp;&nbsp;&nbsp;&nbsp; SELECT surname, firstname, city FROM customer WHERE city LIKE '%".$cidade."%'</h4></font> <hr> <FORM method='post' name='busca' action='valida001.php'> <center>Digite o nome da Cidade: <input type="text" name="cidade"><br><br> <input type="button" value="Enviar" onClick='verifica()'> </form> </body> </html> <!-- Java Script de Verificação de Campos --> <script language="JavaScript"> function rtrim( palavra ) { while ( palavra.substring(palavra.length -1, palavra.length) == " ") { palavra = palavra.substring(0,palavra.length - 1); } return palavra; } function ltrim (palavra) { while (palavra.substring(0, 1) == " ") { palavra = palavra.substring(1, palavra.length); } return palavra; } function verifica() { if (ltrim(document.busca.cidade.value) == "") { window.alert("Favor preencher o campo CIDADE!"); document.busca.cidade.focus(); return false; } else { } </script> } document.busca.submit(); Segunda parte do Script: valida001.php (Validador) <HTML><HEAD><TITLE>Desenvolvimento de Sistemas para Web</TITLE> </HEAD> <BODY> <html> <center> <font color=blue><h1>Desenvolvimento de Sistemas para Web</h1></font> <h1>Banco de Dados</h1> <hr> <font color=red><h2>Consulta Simples</h2></font> <font color=blue><h4>Listar os Compradores de Moram em Determinada Cidade.</h4></font> <hr> <?php include 'error.inc'; include 'db.inc'; $conexao="dbname=".$databasename." user=".$username." password=".$password; if (!($connection = pg_connect($conexao))) die("Erro na abertura da conexão."); echo $cidade; $query = "select firstname, surname, city from customer where city like '%".$cidade."%'"; if (!($result = pg_query ($connection, $query))) showerror($connection); $numero_tuplas = pg_num_rows($result); if ($numero_tuplas != 0) { echo "<TABLE border=1 width=50%>"; echo "<TR><TD><b><center>Nome</b></TD><TD><b><center>Sobrenome</b></TD><TD><b><center >Cidade</b></TD></TR>"; $i = 0; // tupla corrente while ($row = pg_fetch_row($result)) { $i++; echo "<TR><TD>$row[0]</TD>"; echo "<TD>$row[1]</TD>"; echo "<TD>$row[2]</TD></TR>"; } echo "</TABLE>"; } else { echo "<br><br><br><b><font color=red><h3>Nenhum Comprador Localizado!</h3></font></b><br><br><br>"; } echo "<br><br><input type=\"button\" value=\"Voltar\" title=\"Voltar para Janela Anterior!\" onclick=\"history.back()\">"; if (!(pg_free_result($result))) showerror($connection); if (!(pg_close($connection))) showerror($connection); ?> 5.4 – Script para realização de uma consulta envolvendo duas tabelas Esta seção descreve um script de uma consulta envolvendo duas tabelas. O objetivo da mesma é realizar uma pesquisa da quantidade de vinhos comprados por determinado cliente e apresentar os resultados obtidos. Primeira parte do Script: 002.php (Formulário) <HTML><HEAD><TITLE>Desenvolvimento de Sistemas para Web</TITLE> </HEAD> <BODY> <html> <center> <font color=blue><h1>Desenvolvimento de Sistemas para Web</h1></font> <h1>Banco de Dados</h1> <hr> <font color=red><h2>Consulta com 2 Tabelas</h2></font><hr> <font color=blue><h4>Selecionar Quantidade de Vinhos Comprados por determinado Cliente.</h4></font> <font color=black><h4>SQL:&nbsp;&nbsp;&nbsp;&nbsp; SELECT w.wine_name, sum(i.qty) FROM wine w, items i WHERE w.wine_id = i.wine_id AND cust_id = ".$cliente." group by w.wine_name</h4></font> <hr> <FORM method='post' name='busca' action='valida002.php'> <center>Selecione o Cliente: <select name="cliente"> <?php include 'error.inc'; include 'db.inc'; $conexao="dbname=".$databasename." user=".$username." password=".$password; if (!($connection = pg_connect($conexao))) die("Erro na abertura da conexão."); surname"; $query = "select cust_id, firstname, surname from customer ORDER BY if (!($result = pg_query ($connection, $query))) showerror($connection); $i = 0; // tupla corrente while ($row = pg_fetch_row($result)) { $i++; echo "<option value=\"$row[0]\">$row[1] $row[2]</option>"; } ?> </select><br><br> <input type="button" value="Enviar" onClick='verifica()'> </form> </body> </html> <!-- Java Script de Verificação de Campos --> <script language="JavaScript"> function rtrim( palavra ) { while ( palavra.substring(palavra.length -1, palavra.length) == " ") { palavra = palavra.substring(0,palavra.length - 1); } return palavra; } function ltrim (palavra) { while (palavra.substring(0, 1) == " ") { palavra = palavra.substring(1, palavra.length); } return palavra; } function verifica() { if (ltrim(document.busca.cliente.value) == "") { window.alert("Favor preencher o campo CLIENTE!"); document.busca.cliente.focus(); return false; } else { document.busca.submit(); } } </script> Segunda parte do Script: valida002.php (Validador) <HTML><HEAD><TITLE>Desenvolvimento de Sistemas para Web</TITLE> </HEAD> <BODY> <html> <center> <font color=blue><h1>Desenvolvimento de Sistemas para Web</h1></font> <h1>Banco de Dados</h1> <hr> <font color=red><h2>Consulta com 2 Tabelas</h2></font><hr> <font color=blue><h4>Selecionar Quantidade de Vinhos Comprados por determinado Cliente.</h4></font> <hr> <?php include 'error.inc'; include 'db.inc'; $conexao="dbname=".$databasename." user=".$username." password=".$password; if (!($connection = pg_connect($conexao))) die("Erro na abertura da conexão."); $query = "SELECT w.wine_name, sum(i.qty) FROM wine w, items i WHERE w.wine_id = i.wine_id AND cust_id = ".$cliente." group by w.wine_name"; if (!($result = pg_query ($connection, $query))) showerror($connection); $numero_tuplas = pg_num_rows($result); echo "<center><b>Resultado da Pesquisa</b><br><br>"; if ($numero_tuplas != 0) { echo "<TABLE border=1 width=50%>"; echo "<TR><TD><b><center>Nome do Vinho</b></TD><TD><b><center>Quantidade</b></TD></TR>"; $i = 0; // tupla corrente while ($row = pg_fetch_row($result)) { $i++; echo "<TR><TD>$row[0]</TD>"; echo "<TD><center>$row[1]</center></TD></TR>"; } echo "</TABLE>"; } else { echo "<br><br><br><b><font color=red><h3>Nenhum Registro Localizado!</h3></font></b><br><br><br>"; } echo "<br><br><input type=\"button\" value=\"Voltar\" title=\"Voltar para Janela Anterior!\" onclick=\"history.back()\">"; //libera memória if (!(pg_free_result($result))) showerror($connection); // fecha a conexão com o banco de dados if (!(pg_close($connection))) showerror($connection); ?> 5.5 – Script para realização de uma consulta envolvendo três tabelas Esta seção descreve um script de uma consulta envolvendo três tabelas. O objetivo da consulta é mostrar os vinhos produzidos em determinada vinícola e listá-los para o usuário. Após selecionar o vinho, o usuário terá informação dos clientes que compraram o vinho selecionado, juntamente com a quantidade comprada pelos mesmos. Primeira parte do Script: 003.php (Formulário) <HTML><HEAD><TITLE>Desenvolvimento de Sistemas para Web</TITLE> </HEAD> <BODY> <html> <center> <font color=blue><h1>Desenvolvimento de Sistemas para Web</h1></font> <h1>Banco de Dados</h1> <hr> <font color=red><h2>Consulta com 3 Tabelas</h2></font><hr> <font color=blue><h4>Selecionar os clientes e a quantidade de um determinado Vinho adquirido em uma Vinicola.</h4></font> <font color=black><h4> <br>SQL1:&nbsp;&nbsp;&nbsp;&nbsp;select winery_id, winery_name from winery ORDER BY winery_name - LISTA AS VINICOLAS </h4></font> <hr> <FORM method='post' name='busca' action='valida003.php'> <center>Selecione a Vinicola: <select name="vini"> <?php include 'error.inc'; include 'db.inc'; $conexao="dbname=".$databasename." user=".$username." password=".$password; if (!($connection = pg_connect($conexao))) die("Erro na abertura da conexão."); $query = "select winery_id, winery_name from winery ORDER BY winery_name"; if (!($result = pg_query ($connection, $query))) showerror($connection); $i = 0; // tupla corrente while ($row = pg_fetch_row($result)) { $i++; echo "<option value=\"$row[0]\">$row[1]</option>"; } ?> </select><br><br> <input type="hidden" value="<?php $vinicola; ?>"> <input type="submit" value="Enviar"> </form> </body> </html> Segunda parte do Script: valida003.php (Validador) <HTML><HEAD><TITLE>Desenvolvimento de Sistemas para Web</TITLE> </HEAD> <BODY> <html> <center> <font color=blue><h1>Desenvolvimento de Sistemas para Web</h1></font> <h1>Banco de Dados</h1> <hr> <font color=red><h2>Consulta com 3 Tabelas</h2></font><hr> <font color=black><h4><br>SQL2:&nbsp;&nbsp;&nbsp;&nbsp;select wy.winery_name, w.wine_id, w.wine_name from winery wy, wine w where wy.winery_id=w.winery_id and wy.winery_id=".$vini." order by w.wine_name - LISTA OS VINHOS PRODUZIDOS PELA VINICOLA </h4></font> <hr> <FORM method='post' name='busca' action='valida003.php'> <?php if (!($vinho)) { include 'error.inc'; include 'db.inc'; $conexao="dbname=".$databasename."user=".$username." password=".$password; if (!($connection = pg_connect($conexao))) die("Erro na abertura da conexão."); $query = "select wy.winery_name, w.wine_id, w.wine_name from winery wy, wine w where wy.winery_id=w.winery_id and wy.winery_id=".$vini." order by w.wine_name"; if (!($result = pg_query ($connection, $query))) showerror($connection); if (!($result2 = pg_query ($connection, $query))) showerror($connection); $numero_tuplas = pg_num_rows($result); echo "<center><b>Resultado da Pesquisa</b><br><br>"; if ($numero_tuplas != 0) { if ($row2 = pg_fetch_row($result2)) { echo "<font color=#3300FF><b><center>Vinhos da Vinicola $row2[0]</center></b></font><br><br>"; } echo "<TABLE border=1 width=30%>"; echo "<TR><TD colspan=2><b><center>Selecione o Vinho:</b></TD></TR>"; $i = 0; // tupla corrente while ($row = pg_fetch_row($result)) { $i++; echo "<TR><TD width=5%><input type='radio' value='".$row[1]."' name='vinho' checked></TD>"; echo "<TD><center>$row[2]</center></TD></TR>"; } echo "</TABLE>"; } else { echo "<br><br><br><b><font color=red><h3>Nenhum Registro Localizado!</h3></font></b><br><br><br>"; } echo "<br><br><input type='submit' value='Enviar'>"; echo "<input type=\"button\" value=\"Voltar\" title=\"Voltar para Janela Anterior!\" onclick=\"history.back()\">"; if (!(pg_free_result($result))) showerror($connection); if (!(pg_close($connection))) showerror($connection); } else { echo "<font color=black><h4>SQL3:&nbsp;&nbsp;&nbsp;&nbsp;SELECT c.firstname, c.surname, sum(i.qty) FROM customer c, items i WHERE c.cust_id = i.cust_id AND i.wine_id = $vinho group by c.firstname - LISTA OS CLIENTES E A QUANTIDADE DOS VINHOS ADQUIRIDOS"; echo "</h4></font><hr>"; if (!($connection = pg_connect($conexao))) die("Erro na abertura da conexão."); $query = "SELECT c.firstname, c.surname, sum(i.qty) FROM customer c, items i WHERE c.cust_id = i.cust_id AND i.wine_id = ".$vinho." group by c.firstname"; if (!($result = pg_query ($connection, $query))) showerror($connection); $numero_tuplas = pg_num_rows($result); echo "<center><b>Resultado da Pesquisa</b><br><br>"; if ($numero_tuplas != 0) { echo "<TABLE border=1 width=30%>"; echo "<TR><TD colspan=2><b><center>Quantidade de Vinhos comprados pelos Clientes </b></TD></TR>"; $i = 0; // tupla corrente while ($row = pg_fetch_row($result)) { $i++; echo "<tr><TD><center>$row[0] $row[1]</center></TD>"; echo "<TD><center>$row[2]</center></TD></TR>"; } echo "</TABLE>"; } else { echo"<br><br><br><b><font color=red><h3>Nenhum Registro Localizado!</h3></font></b><br><br><br>"; } echo "<br><br><input type=\"button\" value=\"Voltar\" title=\"Voltar para Janela Anterior!\" onclick=\"history.back()\">"; //libera memória if (!(pg_free_result($result))) showerror($connection); // fecha a conexão com o banco de dados if (!(pg_close($connection))) showerror($connection); } ?> 5.6 – Script para inserção de dados no SGBD Esta seção descreve um script para inclusão de dados no SGBD. O objetivo é que após a digitação dos dados o script faça a inclusão de uma nova vinícola. Primeira parte do Script: 004.php (Formulário) <?php include 'db.inc'; include 'error.inc'; if (empty($winery_name) || empty($region_id) || empty($description) || empty($phone) || empty($fax)) { ?> <HTML><HEAD><TITLE>Desenvolvimento de Sistemas para Web</TITLE> </HEAD> <BODY> <html> <center> <font color=blue><h1>Desenvolvimento de Sistemas para Web</h1></font> <h1>Banco de Dados</h1> <hr> <font color=red><h2>Inclusão de Registros</h2></font><hr> <font color=black><h4>SQL:&nbsp;&nbsp;&nbsp;&nbsp; select region_id, region_name from region order by region_name</h4></font> <hr> <form action="" method="POST" name="cadastro"> <TABLE> <TR> <TD>Digite o nome da Vinicola:</TD> <TD><input type="text" name="winery_name" size=30 maxlength=100></TD> </TR> <TR> <TD>Selecione a Região:</TD> <TD><select name="region_id"> <?php $conexao="dbname=".$databasename." user=".$username." password=".$password; if (!($connection = pg_connect($conexao))) die("Erro na abertura da conexão."); $query = "select region_id, region_name from region order by region_name"; if (!($result = pg_query ($connection, $query))) showerror($connection); $i = 0; // tupla corrente while ($row = pg_fetch_row($result)) { $i++; echo "<option value=\"$row[0]\">$row[1]</option>"; } ?> </select></TD></TR> <TR> <TD>Digite a Descrição:</TD> <TD><textarea rows="5" name="description" cols="23" maxlength=500></textarea></TD> </TR> <TR> <TD>Digite o Telefone:</TD> <TD><input type="text" name="phone" size=15 maxlength=15></TD> </TR> <TR> <TD>Digite o Fax:</TD> <TD><input type="text" name="fax" size=15 maxlength=15></TD> </TR> </TABLE> <br> <input type="button" value="Enviar" onclick="verifica()"> <input type="reset" value="Limpar"> </form> </body> </html> <?php } else { $conexao="dbname=".$databasename." user=".$username." password=".$password; if (!($connection = pg_connect($conexao))) die("Erro na abertura da conexão."); $operação = "INSERT INTO winery (winery_id, winery_name, region_id, description, phone, fax) VALUES (NULL, '".$winery_name."', ".$region_id.", '".$description."', '".$phone."', '".$fax."')"; if (( @ pg_query($connection, $operação)) && @ pg_affected_rows( ) == 1) { $winery_id = pg_getlastoid($connection); header("Location: valida004.php?vini_id="."$winery_id"."&status=T"); } else { echo "erro!"; header("Location: valida004.php?"."status=F"); } } ?> <!-- Java Script de Verificação de Campos --> <script language="JavaScript"> function rtrim( palavra ) { while ( palavra.substring(palavra.length -1, palavra.length) == " ") { palavra = palavra.substring(0,palavra.length - 1); } return palavra; } function ltrim (palavra) { while (palavra.substring(0, 1) == " ") { palavra = palavra.substring(1, palavra.length); } return palavra; } function verifica() { if (ltrim(document.cadastro.winery_name.value) == "") { window.alert("Favor preencher o campo VINICOLA!"); document.cadastro.winery_name.focus(); return false; } else if (ltrim(document.cadastro.region_id.value) == "") { window.alert("Favor preencher o campo REGIÃO!"); document.cadastro.region_id.focus(); return false; } else if (ltrim(document.cadastro.description.value) == "") { window.alert("Favor preencher o campo DESCRIÇÃO!"); document.cadastro.description.focus(); return false; } else if (ltrim(document.cadastro.phone.value) == "") { window.alert("Favor preencher o campo TELEFONE!"); document.cadastro.phone.focus(); return false; } else if (ltrim(document.cadastro.fax.value) == "") { window.alert("Favor preencher o campo FAX!"); document.cadastro.fax.focus(); return false; } else { document.cadastro.submit(); } } </script> Segunda parte do Script: valida004.php (Formulário) <HTML><HEAD><TITLE>Desenvolvimento de Sistemas para Web</TITLE> </HEAD> <BODY> <html> <center> <font color=blue><h1>Desenvolvimento de Sistemas para Web</h1></font> <h1>Banco de Dados</h1> <hr> <font color=red><h2>Inclusão de Registros</h2></font><hr> <font color=black><h4>SQL:&nbsp;&nbsp;&nbsp;&nbsp; INSERT INTO winery (winery_id, winery_name, region_id, description, phone, fax) <br>VALUES (NULL, '".$winery_name."', ".$region_id.", '".$description."', '".$phone."', '".$fax."')</h4></font> <hr> <?php include 'db.inc'; include 'error.inc'; $winery_id = $vini_id; $status = $status; switch ($status) { case "T": $consulta = "SELECT w.winery_id, w.winery_name, w.region_id, r.region_name, w.description, w.phone, w.fax FROM winery w, region r WHERE w.region_id=r.region_id and winery_id = ".$winery_id.""; $conexao="dbname=".$databasename." user=".$username." password=".$password; if (!($connection = pg_connect($conexao))) die("Erro na abertura da conexão."); if (!($resultado = @ pg_query($connection, $consulta))) showerror($connection); if ($linha = @ pg_fetch_array($resultado)) { echo "<b>A seguinte Vinicola foi inserida com sucesso:</b><br><BR>"; echo "<TABLE border=0 width=40%>"; echo "<TR>"; echo " <TD><b>Código da Vinicola:</TD>"; echo " <TD>".$linha["winery_id"]."</TD>"; echo "</TR>"; echo "<TR>"; echo " <TD><b>Nome da Vinicola:</TD>"; echo " <TD>".$linha["winery_name"]."</TD>"; echo "</TR>"; echo " <TR>"; echo " <TD><b>Região:</TD>"; echo " <TD>".$linha["region_id"]." - ".$linha["region_name"]."</TD>"; echo " </TR>"; echo " <TR>"; echo " <TD><b>Descrição:</TD>"; echo " <TD>".$linha["description"]."</TD>"; echo " </TR>"; echo " <TR>"; echo " <TD><b>Telefone:</TD>"; echo " <TD>".$linha["phone"]."</TD>"; echo " </TR>"; echo " <TR>"; echo " <TD><b>Fax:</TD>"; echo " <TD>".$linha["fax"]."</TD>"; echo " </TR>"; echo " </TABLE>"; echo "<br><br><input type=\"button\" value=\"Voltar\" title=\"Voltar para Janela Anterior!\" onclick=\"history.back()\">"; } break; case "F": echo "Não foi possível inserir os dados solicitados."; break; default: echo "Esta página deve ser executada por um script."; } ?> </body> </html> 5.7 – Script para alteração de dados no SGBD Esta seção descreve um script para alteração de dados no SGBD. Seu objetivo é que após selecionar um registro, o usuário possa alterar seus dados e gravando-os após a confirmação das alterações realizadas. Primeira parte do Script: 005.php (Formulário) <?php include 'db.inc'; include 'error.inc'; ?> <HTML><HEAD><TITLE>Desenvolvimento de Sistemas para Web</TITLE> </HEAD> <BODY> <html> <center> <font color=blue><h1>Desenvolvimento de Sistemas para Web</h1></font> <h1>Banco de Dados</h1> <hr> <font color=red><h2>Alteração de Registros</h2></font><hr> <font color=black><h4>SQL:&nbsp;&nbsp;&nbsp;&nbsp; SELECT w.winery_id, w.winery_name, w.region_id, r.region_name, w.description, w.phone, w.fax FROM winery w, region r WHERE w.region_id=r.region_id and w.winery_name like '".$nome."%' order by w.winery_name</h4></font> <hr> <FORM method='post' name='busca' action='valida005.php'> <center>Digite o nome ou primeira(s) letra(s) da Vinicola:<br><br> <input type="text" name="nome"><br><br> <input type="button" value="Enviar" onclick="verifica()"> <input type="reset" value="Limpar"> </form> </TR> </TABLE> </body> </html> <!-- Java Script de Verificação de Campos --> <script language="JavaScript"> function rtrim( palavra ) { while ( palavra.substring(palavra.length -1, palavra.length) == " ") { palavra = palavra.substring(0,palavra.length - 1); } return palavra; } function ltrim (palavra) { while (palavra.substring(0, 1) == " ") { palavra = palavra.substring(1, palavra.length); } return palavra; } function verifica() { if (ltrim(document.busca.nome.value) == "") { window.alert("Favor preencher o campo NOME!"); document.busca.nome.focus(); return false; } else { document.busca.submit(); } } </script> Segunda parte do Script: valida005.php (Validação) <?php include 'db.inc'; include 'error.inc'; ?> <HTML><HEAD><TITLE>Desenvolvimento de Sistemas para Web</TITLE> </HEAD> <BODY> <html> <center> <font color=blue><h1>Desenvolvimento de Sistemas para Web</h1></font> <h1>Banco de Dados</h1> <hr> <font color=red><h2>Alteração de Registros</h2></font><hr> <font color=black><h4>SQL:&nbsp;&nbsp;&nbsp;&nbsp; SELECT w.winery_id, w.winery_name, w.region_id, r.region_name, w.description, w.phone, w.fax FROM winery w, region r WHERE w.region_id=r.region_id w.winery_name like '".$nome."%' order by w.winery_name</h4></font> <hr> <form action="valida005b.php" method="POST" name="busca"> and <TABLE border=1 width="80%"> <TR> <TD>&nbsp;</TD> <TD><b><center>Nome Vinicola</TD> <TD><b><center>Região</TD> <TD><b><center>Telefone</TD> <TD><b><center>Fax</TD> </TR> <?php $conexao="dbname=".$databasename." user=".$username." password=".$password; if (!($connection = pg_connect($conexao))) die("Erro na abertura da conexão."); $query = "SELECT w.winery_id, w.winery_name, w.region_id, r.region_name, w.description, w.phone, w.fax FROM winery w, region r WHERE w.region_id=r.region_id and w.winery_name like '".$nome."%' order by w.winery_name"; if (!($result = pg_query ($connection, $query))) showerror($connection); while ($row = pg_fetch_row($result)) { echo "<tr><TD><center><input type='radio' value='".$row[0]."' name='vinicola' checked></TD>"; echo "<TD>".$row[1]."</TD>"; echo "<TD>".$row[3]."</TD>"; echo "<TD><center>".$row[5]."</center></TD>"; echo "<TD><center>".$row[5]."</center></TD></tr>"; } if (!(pg_free_result($result))) showerror($connection); if (!(pg_close($connection))) showerror($connection); ?> </TABLE> <br> <input type="submit" value="Enviar"> <input type="button" value="Voltar" title="Voltar para Janela Anterior!" onclick="history.back()"> </form> </body> </html> Terceira parte do Script: valida005b.php (Validação) <?php include 'db.inc'; include 'error.inc'; if (empty($a_winery_name) || empty($a_region_id) || empty($a_description) || empty($a_phone) || empty($a_fax)) { ?> <HTML><HEAD><TITLE>Desenvolvimento de Sistemas para Web</TITLE> </HEAD> <BODY> <html> <center> <font color=blue><h1>Desenvolvimento de Sistemas para Web</h1></font> <h1>Banco de Dados</h1> <hr> <font color=red><h2>Alteração de Registros</h2></font><hr> <font color=black><h4>SQL:&nbsp;&nbsp;&nbsp;&nbsp; SELECT w.winery_id, w.winery_name, w.region_id, r.region_name, w.description, w.phone, w.fax FROM winery w, region r WHERE w.region_id=r.region_id and w.winery_name like '".$nome."%' order by w.winery_name</h4></font> <hr> <? $conexao="dbname=".$databasename." user=".$username." password=".$password; if (!($connection = pg_connect($conexao))) die("Erro na abertura da conexão."); $query = "SELECT w.winery_id, w.winery_name, w.region_id, r.region_name, w.description, w.phone, w.fax FROM winery w, region r WHERE w.region_id=r.region_id and w.winery_id = ".$vinicola." order by w.winery_name"; if (!($result = pg_query ($connection, $query))) showerror($connection); echo "<form action='valida005c.php' method='POST' name='cadastro'>"; echo "<TABLE>"; while ($row = pg_fetch_row($result)) { echo "<TR>"; echo "<TD>Digite o nome da Vinicola:</TD>"; echo "<TD><input type='text' name='a_winery_name' value='".$row[1]."' size=30 maxlength=100></TD>"; echo "</TR>"; echo "<TR>"; echo "<TD>Selecione a Região:</TD>"; echo "<TD><select name='a_region_id'>"; $conexao="dbname=".$databasename." user=".$username." password=".$password; if (!($connection = pg_connect($conexao))) die("Erro na abertura da conexão."); $query2 = "select region_id, region_name from region order by region_name"; if (!($result2 = pg_query ($connection, $query2))) showerror($connection); while ($row2 = pg_fetch_row($result2)) { if ($row[3] == $row2[1]) echo "<option selected value=\"$row2[0]\">$row2[1]</option>"; else echo "<option value=\"$row2[0]\">$row2[1]</option>"; } echo "</select></TD></TR>"; echo "<TR>"; echo "<TD>Digite a Descrição:</TD>"; echo "<TD><textarea rows='5' name='a_description' cols='23' maxlength=500>"; echo $row[4]; echo "</textarea></TD>"; echo "</TR>"; echo "<TR>"; echo "<TD>Digite o Telefone:</TD>"; echo "<TD><input type='text' name='a_phone' value='".$row[5]."' size=15 maxlength=15></TD>"; echo "<input type='hidden' name='vini_id' value='".$vinicola."' size=15 maxlength=15>"; echo "<input type='hidden' name='status' value='T' size=15 maxlength=15>"; echo "</TR>"; echo "<TR>"; echo "<TD>Digite o Fax:</TD>"; echo "<TD><input type='text' name='a_fax' value='".$row[6]."' size=15 maxlength=15></TD>"; echo "</TR>"; echo "</TABLE>"; } if (!(pg_free_result($result))) showerror($connection); if (!(pg_close($connection))) showerror($connection); ?> <br> <input type="button" value="Enviar" onclick="verifica()"> <input type="reset" value="Valores Anteriores"> <input type="button" value="Voltar" title="Voltar para Janela Anterior!" onclick="history.back()"> </form> </body> </html> <? } ?> <!-- Java Script de Verificação de Campos --> <script language="JavaScript"> function rtrim( palavra ) { while ( palavra.substring(palavra.length -1, palavra.length) == " ") { palavra = palavra.substring(0,palavra.length - 1); } return palavra; } function ltrim (palavra) { while (palavra.substring(0, 1) == " ") { palavra = palavra.substring(1, palavra.length); } return palavra; } function verifica() { if (ltrim(document.cadastro.a_winery_name.value) == "") { window.alert("Favor preencher o campo VINICOLA!"); document.cadastro.a_winery_name.focus(); return false; } else if (ltrim(document.cadastro.a_region_id.value) == "") { window.alert("Favor preencher o campo REGIÃO!"); document.cadastro.a_region_id.focus(); return false; } else if (ltrim(document.cadastro.a_description.value) == "") { window.alert("Favor preencher o campo DESCRIÇÃO!"); document.cadastro.a_description.focus(); return false; } else if (ltrim(document.cadastro.a_phone.value) == "") { window.alert("Favor preencher o campo TELEFONE!"); document.cadastro.a_phone.focus(); return false; } else if (ltrim(document.cadastro.a_fax.value) == "") { window.alert("Favor preencher o campo FAX!"); document.cadastro.a_fax.focus(); return false; } else { document.cadastro.submit(); } } </script> Quarta parte do Script: valida005c.php (Validação) <HTML><HEAD><TITLE>Desenvolvimento de Sistemas para Web</TITLE> </HEAD> <BODY> <html> <center> <font color=blue><h1>Desenvolvimento de Sistemas para Web</h1></font> <h1>Banco de Dados</h1> <hr> <font color=red><h2>Alteração de Registros</h2></font><hr> <font color=black><h4>SQL:&nbsp;&nbsp;&nbsp;&nbsp; SELECT w.winery_id, w.winery_name, w.region_id, r.region_name, w.description, w.phone, w.fax FROM winery w, region r WHERE w.region_id=r.region_id and w.winery_name like '".$nome."%' order by w.winery_name</h4></font> <hr> <?php include 'db.inc'; include 'error.inc'; $winery_id = $vini_id; $status = $status; $a_winery_name = $a_winery_name; $a_region_id $a_description $a_phone = $a_region_id; = $a_description; = $a_phone; $a_fax = $a_fax; switch ($status) { case "T": $conexao="dbname=".$databasename." user=".$username." password=".$password; if (!($connection = pg_connect($conexao))) die("Erro na abertura da conexão."); $operação = "UPDATE winery SET winery_name= '".$a_winery_name."', region_id= ".$a_region_id.", description= '".$a_description."', phone= '".$a_phone."', fax= '".$a_fax."' WHERE winery_id=".$winery_id.""; if (( @ pg_query($connection, $operação)) && @ pg_affected_rows( ) == 1) { echo "&nbsp;"; } else { echo "erro!"; } $consulta = "SELECT w.winery_id, w.winery_name, w.region_id, r.region_name, w.description, w.phone, w.fax FROM winery w, region r WHERE w.region_id=r.region_id and winery_id = ".$winery_id.""; $conexao="dbname=".$databasename." user=".$username." password=".$password; if (!($connection = pg_connect($conexao))) die("Erro na abertura da conexão."); if (!($resultado = @ pg_query($connection, $consulta, ))) showerror($connection); if ($linha = @ pg_fetch_array($resultado)) { echo "<b>O seguinte Registro foi alterado com sucesso:</b><br><BR>"; echo "<TABLE border=0 width=40%>"; echo "<TR>"; echo " <TD><b>Código da Vinicola:</TD>"; echo " <TD>".$linha["winery_id"]."</TD>"; echo "</TR>"; echo "<TR>"; echo " <TD><b>Nome da Vinicola:</TD>"; echo " <TD>".$linha["winery_name"]."</TD>"; echo "</TR>"; echo " <TR>"; echo " <TD><b>Região:</TD>"; echo " <TD>".$linha["region_id"]." - ".$linha["region_name"]."</TD>"; echo " </TR>"; echo " <TR>"; echo " <TD><b>Descrição:</TD>"; echo " <TD>".$linha["description"]."</TD>"; echo " </TR>"; echo " <TR>"; echo " <TD><b>Telefone:</TD>"; echo " <TD>".$linha["phone"]."</TD>"; echo " </TR>"; echo " <TR>"; echo " <TD><b>Fax:</TD>"; echo " <TD>".$linha["fax"]."</TD>"; echo " </TR>"; echo " </TABLE>"; echo "<FORM method='post' name='dir' action='005.php'>"; echo "<input type=\"submit\" value=\"Voltar\">"; echo "</form>"; } break; case "F": echo "Não foi possível inserir os dados solicitados."; break; default: echo "Esta página deve ser executada por um script."; } ?> </body> </html> 5.8 – Considerações Finais Este capítulo apresentou uma aplicação de banco de dados utilizando o SGBD PostgreSQL e a linguagem de programação PHP. A aplicação utilizou como fundamentação a base de dados winestore, proposta por Williams & Lane (2002). Para o desenvolvimento da aplicação, esta base de dados foi criada e povoada no SGBD PostgreSQL. Para o desenvolvimento da aplicação não houve grandes problemas na utilização das funções de acesso ao SGBD PostgreSQL da linguagem PHP. A investigação da sintaxe dessas funções e a realização de testes durante a identificação destas funções facilitaram o desenvolvimento da aplicação apresentada neste capítulo. Capítulo 6 Conclusão Esta monografia teve como objetivo analisar o desenvolvimento de aplicações de banco de dados para a Web usando a linguagem de programação PHP, juntamente com o SGBD MySQL e com o SGBD PostgreSQL. O trabalho inclui um estudo comparativo entre as funcionalidades oferecidas pelo SGBD MySQL e pelo SGBD PostgreSQL. Também foram investigadas as funções de acesso que a linguagem de programação PHP oferece aos dois SGBDs em estudo, sendo criada como resultado, uma tabela comparativa entre essas funcionalidades. As principais contribuições do desenvolvimento deste trabalho são: • Identificação de quais funcionalidades da linguagem SQL são oferecidas pelo SGBD MySQL e pelo SGBD PostgreSQL, e comparação desses SGBDs com relação a estas funcionalidades; • Pesquisa e investigação das funções oferecidas pela linguagem de implementação PHP para o acesso ao SGBD PostgreSQL; • Comparação das funções oferecidas pela linguagem de implementação PHP para o acesso ao SGBD MySQL e ao SGBD PostgreSQL; • Produção de material didático para instalação, no sistema operacional Windows: (i) da linguagem PHP versão 5.0.1; (ii) do servidor Apache versão 1.3.29; (iii) do SGBD MySQL versão 4.0.21; e (iv) do SGBD PostgreSQL versões 7.3.x utilizando o Cygwin e do SGBD PostgreSQL Beta 4 utilizando o PeerDirect UltraSQL (Apêndice A). • Produção de material didático para instalação, no sistema operacional Linux: (i) da linguagem PHP versão 5.0.1; (ii) do servidor Apache versão 1.3.29; (iii) do SGBD MySQL versão 4.0.21; e (iv) do SGBD PostgreSQL versão 7.3.1 (Apêndice B). Trabalhos futuros podem ser desenvolvidos realizando estudos comparativos entre outros SGBDs e comparando-os com a linguagem de programação PHP. Outra sugestão é realizar um estudo comparativo entre os SGBDs MySQL e PostgreSQL com outras linguagens de programação para desenvolvimento de sistemas para WEB, como exemplo a linguagem JSP. Referências Bibliográficas CIFERRI, C. D. de A., CIFERRI, R. R., Transparências da disciplina Banco de Dados e Web, Curso de Especialização Desenvolvimento de Sistemas para a Web, Departamento de Informática (DIN), Universidade Estadual de Maringá (UEM), Maringá, PR, BR, 2003. CONVERSE, T., PARK, J., PHP 4: A Bíblia, Campus, 2001, 697 pp. ELMASRI, R., NAVATHE, S. Fundamentals of Database Systems, 4th edition. Addison-Wesley, 2003. MySQL AB. MySQL Reference Manual. Internet. Available at URL http://www.mysql.com, 09/2004. NEVES, D. L. F., PostgreSQL: Conceitos e Aplicações, Editora Erica, 2002. 192p. ISBN 8571948909. NIEDERAUER, J., PosgreSQL: Guia de Consulta Rápida, Editora Novatec, 2001. 127p. ISBN 8575220128. SILBERSCHATZ, A., KORTH, H. F., SUDARSHAN, S., Sistema de Banco de Dados, MAKRON Books, 1999, 764 pp. The PostgreSQL Global Development Group. Manual de Referência do PostgreSQL 7.3.2. Internet. Available at URL http://www.postgresql.org, 09/2004. WILLIAMS, H. E.; LANE, D. Web Database Applications with PHP and MySQL. O´Reilly & Associates, 2002. 563p. ISBN 0-596-00041-3. MILOCA, K. C. Desenvolvimento de uma Aplicação de Banco de Dados para a Web usando PHP e MySQL: Enfoque Consultas e Operações de Inserção e Remoção. Trabalho de Final de Curso. Departamento de Informática (DIN), Universidade Estadual de Maringá (UEM), Maringá, PR, BR, 2004. Apêndice A Instalação dos softwares utilizados no Sistema Operacional Windows Este apêndice descreve os passos que devem ser seguidos para a instalação (i) da linguagem PHP versão 5.0.1; (ii) do servidor Apache versão 1.3.29; (iii) do SGBD MySQL versão 4.0.21; e (iv) do SGBD PostgreSQL versões 7.3.x utilizando o Cygwin e do SGBD PostgreSQL Beta 4 utilizando o PeerDirect UltraSQL. As instalações aqui descritas são realizadas sobre o sistema operacional Windows. Instalação da Linguagem PHP versão 5.0.1 • Realizar o download do arquivo php-5.0.1-win32.zip, presente na URL http://www.php.net; • Descompactar o arquivo na unidade de disco C: usando o software winzip; • Abrir o Windows Explorer e localizar o diretório com o nome php-5.0.1-win32; • Renomear esse diretório para PHP; • Copiar o arquivo php.ini-dist para o diretório C:/WINDOWS; • Renomear o arquivo php.ini-dist do diretório WINDOWS para php.ini; e • Abrir o arquivo php.ini e colocar o path das extensions do PHP ( C:/php/extensions ). Instalação do servidor APACHE versão 1.3.29 • Realizar o download do arquivo executável de instalação do Apache na URL http://www.apache.org; • Executar o arquivo, instalando dessa forma o Apache na unidade C:; • Renomear o diretório APACHE GROUP para APACHE; • Testar se a instalação foi bem sucedida abrindo o browser e digitando na barra de endereços o endereço de loopback (http://127.0.0.1). Deverá aparecer uma página contendo o símbolo do Apache com o conteúdo informando que o Apache está funcionando corretamente; • Editar o arquivo httpd.conf localizado em C:/apache/conf/httpd.conf, o qual armazena as configurações do Apache. Este passo é realizado visando-se configurar o Apache; • Localizar a linha SCRIPTALIAS e adicionar os seguintes códigos: ScriptAlias /php/ "c:/php/" AddType application/x-httpd-php .php Action application/x-httpd-php "/php/php.exe" • Localizar a linha que contém a palavra DOCUMENTROOT e acrescentar o path que indica onde as páginas estão localizadas. O padrão do Apache é C:/apache/htdocs. Como conseqüência, qualquer página desenvolvida deve ser armazenada nesse diretório; • Localizar a linha DIRECTORYINDEX e identificar os arquivos iniciais que o Apache deve atribuir como páginas iniciais, como por exemplo, index.php e index.phtml; • Fechar o arquivo httpd.conf e salvar todas as alterações; e • Iniciar o Apache novamente para que o mesmo assuma as novas configurações. O teste da instalação do servidor Apache deve ser realizado da seguinte forma: • Criar um arquivo chamado index.php com o seguinte conteúdo: <? phpinfo(); ?> • Salvar o arquivo no diretório definido nas configurações de DocumentRoot; e • Abrir o browser e digitar na barra de endereços a URL http://127.0.0.1. Nesse momento, deverá abrir no browser uma página contendo as informações sobre as configurações do PHP. Instalação do SGBD MySQL versão 4.0.21 • Realizar o download do arquivo de instalação do MySQL na URL http://www.mysql.com; • Descompactar o arquivo na unidade de disco C: usando o software winzip; • Abrir o Windows Explorer e localizar o diretório cujos arquivos foram descompactados; • Executar o arquivo SETUP.EXE; • Instalar o serviço do MySQL no WINDOWS 2000 / XP após a conclusão do setup. Para isso, deve-se executar o seguinte comando no DOS, dentro do diretório c:\mysql\bin: c:\MYSQL\BIN> mysqld-nt --install • Reiniciar a máquina após a exibição da mensagem de êxito: SERVICE SUCESSFULLY INSTALLED. O teste da instalação do SGBD MySQL deve ser realizado como segue. Para acessar este SGBD, o comando mysql deve ser digitado dentro do diretório BIN. Na seqüência, o sistema deve assumir o prompt do MySQL. Para sair, digite o comando EXIT. Instalação do SGBD PostgreSQL Existem duas formas de se instalar o SGBD PostgreSQL para ambiente Windows. Uma delas consiste na utilização do programa chamado Cygwin. Esse software é um ambiente UNIX que consiste em duas partes: o Uma DLL (cygwin1.dll), que atua como uma camada de emulação UNIX provendo funcionalidades de API UNIX; e o Uma coleção de ferramentas, importadas do UNIX, que provê um visual UNIX/Linux. A DLL Cygwin trabalha com todas as versões não beta do Windows desde o Windows 95, com exceção do Windows CE. Para instalar o Cygwin, deve-se seguir os seguintes passos: • Realizar o download do arquivo disponível na URL http://www.cygwin.com e executá-lo; • Localizar os pacotes. Durante a execução, alguns pacotes já vêm selecionados, que são os mínimos necessários para a instalação. No canto superior da janela de instalação existe o botão VIEW. Pressionar até a palavra ao lado aparecer FULL. Serão exibidos todos os pacotes em ordem alfabética; • Localizar o pacote do PostgreSQL e pressionar o botão até aparecer a versão C; • Repetir o procedimento para os pacotes bzip2 e less. Estas aplicações serão necessárias mais adiante; • Prosseguir até o término da instalação. Será criado um ícone no menu iniciar e no desktop; • Instalar o CygIPC, que é um servidor IPC pré-compilado. Seu arquivo de instalação pode ser obtido na URL http://www.neuro.gatech.edu/users/cwilson/cygutils e deve ser gravado no diretório de instalação do Cygwin, normalmente c:\cygwin; • Abrir um shell do Cygwin (shell é como o prompt do DOS); • Descompactar o pacote cygipc no diretório raiz: claudio@CLAUDIO ~ $ cd / claudio@CLAUDIO / $ tar xvfj cygipc-1.13-2.tar.bz2 • Inicializar a base de dados através do comando initdb. Após a execução dos passos acima, o ipc-daemon está pronto para rodar. Como resultado, após a inicialização do ipcdaemon, a base de dados pode ser utilizada. Na sintaxe do comando initdb pode-se definir o diretório base do banco de dados através da opção -D <diretório>; e • Inicializar o PostgreSQL, por meio do comando postmaster com as opções –i-D <diretório>, onde -i indica que o postmaster deve aceitar conexões através de soquetes TCP/IP. Caso contrário, só aceitará conexões através de soquetes UNIX localmente. Outra forma de se instalar o PosgreSQL em Windows é utilizando-se uma versão BETA do PeerDirect UltraSQL, um PostgreSQL compilado para Windows que não necessita do Cygwin (emulador UNIX) para executá-lo. Para instalá-lo, deve-se: • Realizar o download do arquivo postgres_beta4.zip na URL ftp://209.61.187.152/postgres/postgres_beta4.zip; • Criar um diretório para descompactar o arquivo (c:\winpsql) e extrair todos os arquivos de postgres_beta4.zip para este diretório; • Mover os arquivos e diretórios do subdiretório postgres_beta4 que foi criado para o diretório C:\winpsql; • Criar as variáveis de ambiente necessárias. Essas variáveis estão armazenadas no arquivo C:\winpsql\setenv.bat. As definições devem ser copiadas para o arquivo autoexec.bat, caso o Windows 98 esteja sendo usado. Em contrapartida, caso o sistema operacional seja Windows 2000/NT/XP, deve-se clicar com o botão direito do mouse no ícone Meu Computador, e escolher a opção Propriedades. Ao ser exibida a caixa de Propriedades do Sistema, selecionar a ficha Avançado e clicar no botão Variáveis de Ambiente. Clicar no botão Novo localizado na caixa de Variáveis do Sistema para aparecer uma caixa de diálogo, onde será definida cada uma das variáveis, preenchendo seu nome (PGHOME) e seu conteúdo (C:winpsql). Deve-se também adicionar à variável de sistema PATH o conteúdo ";%PGHOME%in"; e • Inicializar o diretório dos dados. Para fazer isso, clicar em Iniciar, depois em Executar e finalmente digitar o comando: initdb. Caso o sistema operacional não seja o Windows98, para instalar o serviço deve-se clicar em Iniciar, então em Executar e em seguida digitar: post_svc –install. O serviço pode ser removido digitando-se: post_svc –remove. Para iniciar o serviço manualmente, deve-se clicar em Iniciar, então em Executar e em seguida digitar: pg_ctl start. Para parar o serviço manualmente, deve-se digitar: pg_ctl stop. Para os sistemas operacionais Windows 2000/XP/NT, o serviço também pode ser parado e iniciado automaticamente através da administração dos Serviços em Ferramentas Administrativas no Painel de Controle. Apêndice B Instalação dos softwares utilizados no Sistema Operacional Linux Este apêndice descreve os passos que devem ser seguidos para a instalação (i) da linguagem PHP versão 5.0.1; (ii) do servidor Apache versão 1.3.29; (iii) do SGBD MySQL versão 4.0.21; e (iv) do SGBD PostgreSQL versão 7.3.1. As instalações aqui descritas são realizadas sobre o sistema operacional Linux. Instalação da Linguagem PHP versão 5.0.1 • Realizar o download do arquivo php-5.0.1.tar.gz, presente na URL http://www.php.net; • Descompactar o arquivo utilizando os seguintes comandos: $ cd /usr/src $ tar xvzf php-5.0.1.tar.gz • Configurar o PHP digitando os comandos: $ cd php-5.0.1 $ ./configure --with-mysql --with-apache=../apache_1.3.x --enable-track-vars $ make $ make install $ cp php.ini-dst /usr/local/lib/php.ini Instalação do servidor APACHE versão 1.3.29 • Realizar o download do arquivo apache_1.3.29.tar.gz, http://www.apache.org; • Descompactar o arquivo utilizando os seguintes comandos: $ cd /usr/src $ tar xvzf apache_1.3.29.tar.gz disponível na URL • Instalar o Apache com os comandos: $ cd apache_1.3.29 $ ./configure --prefix=/www • Instalar o PHP para que o Apache o reconheça na biblioteca do PHP; • Concluir a instalação do Apache por meio dos comandos: $ cd / usr/src/apache_1.3.x $ ./configure --prefix=/www --activate-module= src/modules/php3/libphp3.a $ make $ make install • Editar o arquivo httpd.conf ou o arquivo srm.conf, que se encontram no diretório conf do Apache (/www/conf) e inserir a linha abaixo, que indicará ao Apache que todas as páginas com formato .php devem ser processadas pelo módulo PHP: AddType application/x-httpd-php .php Instalação do SGBD MySQL versão 4.0.21 • Realizar o download do arquivo de instalação do MySQL (mysql-4.0.21-alpha.tar.gz), encontrado na URL http://www.mysql.com, • Descompactar o arquivo utilizando o seguinte comando: tar xvzf mysql-4.0.21-alpha.tar.gz • Mudar o diretório atual para o diretório do MySQL: cd /usr/src/mysql-4.0.21-alpha • Configurar o MySQL: ./configure --prefix=/usr/local/mysql • Compilar o MySQL: make • Instalar o MySQL: make install • Acrescentar a biblioteca do MySQL ao arquivo /etc/ld.so.conf; vi /etc/ld.so.conf • Acrescentar a seguinte linha no fim desse arquivo: /usr/local/mysql/lib/mysql • Criar a tabela de permissões do MySQL: scripts/mysql_install_db • Iniciar o servidor MySQL: /usr/local/mysql/bin/safe_mysqld & Instalação do SGBD PostgreSQL versão 7.3.1 • Realizar o download do cógido-fonte do PostgreSQL a partir da URL http://www.postgresql.org/mirrors-ftp.html; • Executar os seguintes comandos: $ ./configure $ gmake $ su(senha de root) $ gmake install • Configurar o PostgreSQL seguindo os passos descritos a seguir: $ su -(senha de root) # adduser postgres # echo "PATH=/usr/local/pgsql/bin:$PATH" /home/postgres/.bashrc # echo "export PATH" >> /home/postgres/.bashrc # mkdir /usr/local/pgsql/data # chown postgres /usr/local/pgsql/data # su – postgres • Iniciar o PostgreSQL utilizando a seguinte sintaxe: initdb -D /usr/local/pgsql/data postmaster -D /usr/local/pgsql/data >logfile 2>&1 & >>