Prévia do material em texto
® IPM Informática Pública Municipal Programa Jovens Talentos 1 Módulo III – Banco de Dados ® IPM Informática Pública Municipal Programa Jovens Talentos 2 SUMÁRIO O que espera-se que o aluno saiba ao final deste módulo ................................................................................................................. 1 Conceitos de sgbdr e postgresql ......................................................................................................................................................... 1 Conceitos do sgbdr.......................................................................................................................................................................... 1 PosTgresql ....................................................................................................................................................................................... 2 Instalação do postgresql no windows ............................................................................................................................................. 2 Os arquivos postgresql.conf e pg_hba.conf ................................................................................................................................ 3 A ferramenta PGADMIN .................................................................................................................................................................. 3 Conectando a um servidor .......................................................................................................................................................... 3 Possíveis problemas de conexão ................................................................................................................................................ 4 Visualizando objetos ................................................................................................................................................................... 4 Criando um usuário ..................................................................................................................................................................... 5 Criando um database .................................................................................................................................................................. 5 Criando um schema .................................................................................................................................................................... 5 A ferramenta de edição de consultas ......................................................................................................................................... 5 Modelagem de dados ......................................................................................................................................................................... 7 O diagrama entidade relacionamento ............................................................................................................................................ 7 Dicas de modelagem de dados ................................................................................................................................................... 7 O padrão p006 – padrão de modelagem de dados da ipm ............................................................................................................. 9 Sql ....................................................................................................................................................................................................... 9 Conceitos gerais .............................................................................................................................................................................. 9 Técnicas de organização de código sql ......................................................................................................................................... 10 GERAL ........................................................................................................................................................................................ 10 Cláusula SELECT......................................................................................................................................................................... 11 Cláusula FROM .......................................................................................................................................................................... 11 Cláusula JOIN ............................................................................................................................................................................ 11 Cláusula WHERE ........................................................................................................................................................................ 11 Outras Dicas .............................................................................................................................................................................. 12 SQL - DML .......................................................................................................................................................................................... 12 Seleção de informações - SELECT .................................................................................................................................................. 12 Rótulos de colunas .................................................................................................................................................................... 14 Cláusula FROM/JOIN ................................................................................................................................................................. 14 SUB-SELECT ............................................................................................................................................................................... 16 SUB-SELECT X JOIN ............................................................................................................................................................................ 17 Operadores de agregação ......................................................................................................................................................... 19 Agrupamento – GROUP BY ....................................................................................................................................................... 20 HAVING ..................................................................................................................................................................................... 21 ® IPM Informática Pública Municipal Programa Jovens Talentos 3 Ordenação - ORDER BY ............................................................................................................................................................. 22 LIMIT e OFFSET .......................................................................................................................................................................... 23 Exercícios .................................................................................................................................................................................. 23 A cláusula where ....................................................................................................................................................................... 24 Operadores lógicos ........................................................................................................................................................................... 25 Operadores de comparação .............................................................................................................................................................25 Operador in ....................................................................................................................................................................................... 26 Operador EXISTS ............................................................................................................................................................................... 26 Expressão condicional – CASE ................................................................................................................................................... 27 Expressão condicional – COALESCE .......................................................................................................................................... 29 Exercícios .................................................................................................................................................................................. 29 Conversão de tipos ....................................................................................................................................................................... 30 Operadores de formação de dados .............................................................................................................................................. 31 Operações com conjuntos - UNION, INTERSECT E EXCEPT ........................................................................................................... 31 Exercícios ...................................................................................................................................................................................... 32 Inserção de informações – INSERT................................................................................................................................................ 32 Exercícios .................................................................................................................................................................................. 33 Alteração de informações – UPDATE ............................................................................................................................................ 37 Exercícios .................................................................................................................................................................................. 38 Exclusão de dados – DELETE / TRUNCATE .................................................................................................................................... 38 Exercícios .................................................................................................................................................................................. 38 SQL – DDL .......................................................................................................................................................................................... 39 Organização de objetos no POSTGRESQL ..................................................................................................................................... 39 Usuários .................................................................................................................................................................................... 39 Database ................................................................................................................................................................................... 40 SCHEMA .................................................................................................................................................................................... 41 O schema publico (PUBLIC) ............................................................................................................................................................... 41 Tabela ........................................................................................................................................................................................ 41 Exercícios .................................................................................................................................................................................. 43 Chaves primárias (PK) ............................................................................................................................................................... 43 Chave estrangeria (FK) .............................................................................................................................................................. 44 Índices ....................................................................................................................................................................................... 46 Exercícios .................................................................................................................................................................................. 48 Views ......................................................................................................................................................................................... 48 Funções e gatilhos ..................................................................................................................................................................... 50 POSTGRESQL – Administração básica ............................................................................................................................................... 51 ® IPM Informática Pública Municipal Programa Jovens Talentos 4 Server status ............................................................................................................................................................................. 51 Explicando uma consulta - modo gráfico .................................................................................................................................. 52 Colunas do sistema ................................................................................................................................................................... 53 Controle de transações ............................................................................................................................................................. 54 backup ....................................................................................................................................................................................... 55 restore ....................................................................................................................................................................................... 55 O QUE ESPERA-SE QUE O ALUNO SAIBA AO FINAL DESTE MÓDULO Espera-se que o aluno conheça os conceitos básicos de um SGBD e seus componentes. Entenda o que é um modelo no paradigma relacional baseado em um DER e o padrão P006 da IPM para modelagem de dados. Conheça os conceitos da linguagem SQL, suas divisões (DDL e DML), além da estrutura básica dos comandos e a melhor forma de organização dos mesmos. Deverá também conhecer a fundo as principais instruções SQL (INSERT, UPDATE, DELETE, TRUNCATE, SELECT, JOIN, DISTINCT, GROUP BY, ORDER BY, HAVING, LIMIT, OFFSET, UNION, INTERSECT, EXCEPT, CREATE, ALTER, DROP, EXPLAIN, CURSOR, SAVEPOINT). Conceitos e diferenças de triggers e functions para o banco de dados. Entenda como funciona o controle de transações do SGBD e conceitos de administração básica (como backup, restore, explain). CONCEITOS DE SGBDR E POSTGRESQL CONCEITOS DO SGBDR A Sigla SGBD vem de Sistema Gerenciador de Banco de Dados. Trata-se de um software que exclusivamente irá comandar o relacionamento entre o Software aplicativo e os dados do banco de dados, principalmenteatravés da interpretação e execução de comandos SQL (linguagem que é exposta mais à frente). Banco de dados (ou base de dados), é um conjunto de registros dispostos em estrutura regular que possibilita a reorganização dos mesmos e produção de informação. Um banco de dados normalmente agrupa registros utilizáveis para um mesmo fim. Um banco de dados é usualmente mantido e acessado por meio de um software conhecido como Sistema Gerenciador de Banco de Dados (SGBD). Normalmente um SGBD adota um modelo de dados, de forma pura, reduzida ou estendida. ® IPM Informática Pública Municipal Programa Jovens Talentos 5 O modelo de dados mais adotado hoje em dia é o modelo relacional, onde as estruturas têm a forma de tabelas, compostas por tuplas(linhas) e colunas (veja mais de DER). Um Sistema de Gestão de Bases de Dados, (SGBD) não é nada mais do que um conjunto de programas que permitem armazenar, modificar e extrair informação de um banco de dados. Há muitos tipos diferentes de SGBD. Desde pequenos sistemas que funcionam em computadores pessoais a sistemas enormes que estão associados a mainframes. Um Sistema de Gestão de Base de Dados implica a criação e manutenção de bases de dados, elimina a necessidade de especificação de definição de dados, age como interface entre os programas de aplicação e os arquivos de dados físicos e separa as visões lógica e de concepção dos dados. Assim sendo, são basicamente três as componentes de um SGBD: 1. Linguagem de definição de dados (DDL) (especifica conteúdos, estrutura a base de dados e define os elementos de dados); 2. Linguagem de manipulação de dados (DML) (para poder alterar os dados na base); 3. Dicionário de dados (guarda definições de elementos de dados e respectivas características – descreve os dados, quem os acede, etc.) Por outro lado, um SGBD é um software muito complexo que não apenas se preocupa em armazenar ou buscar os dados dos mais diversos locais, mas também de todo o comportamento definido para o banco de dados durante a sua implementação, como os relacionamentos entre as tabelas, os gatilhos que devem ser disparados para cada evento que ocorre, etc. POSTGRESQL O PostgreSQL é um SGBDR – Sistema Gerenciador de Base de Dados Relacional (ou mais comumente indicado, do inglês RDBMS – Relational Database Management System) que está baseado nos padrões SQL ANSI-92, 96 e 99, de alta performance, de fácil administração e utilização em projetos. Ele permite a utilização de SQL, Triggers e toda a gama de programação e construção pertinente aos mais famosos RDBMs do mercado (como o Oracle). Além de permitir “Embedded SQL” como pré-compilação (com as linguagens C e C++) e possuir drivers ODBC e JDBC para interface com ambientes e linguagens de programação. O PostgreSQL começa a sua construção em meados de 1996, na Universidade Norte-Americana da Califórnia, a Universidade de Berkley (a partir do seu descendente o Ingres). Desde então, com quase 18 anos de experiência o PostgreSQL vem sendo aprimorado com muitos benefícios e funcionalidades. O PostgreSQL é um descendente de código fonte aberto deste código original de Berkeley. É suportada grande parte do padrão SQL:2003 Devido à sua licença liberal, o PostgreSQL pode ser utilizado, modificado e distribuído por qualquer pessoa para qualquer finalidade, seja privada, comercial ou acadêmica, livre de encargos. INSTALAÇÃO DO POSTGRESQL NO WINDOWS A instalação do PostgreSQL no windows é bem simples, através de um assistente todo o processo de instalação é automatizado, bastando informar a este instalador para prosseguir nas etapas que são exibidas. A seguir são mostradas as principais telas que fazem interface entre a instalação e o usuário: Na primeira etapa informe apenas o idioma de preferência, o idioma Português do Brasil está disponível. O idioma selecionado aqui é apenas para uso do instalador. As duas próximas etapas são apenas informativas, sendo que a terceira etapa mostra um termo com informações sobre o PostgreSQL e o grupo postgresql.org, clique em próximo para prosseguir. ® IPM Informática Pública Municipal Programa Jovens Talentos 6 Na etapa seguinte são exibidas opções de instalação, por padrão as opções que já vem marcadas são utilizadas, não selecionando nenhuma outra opção. Da mesma forma a pasta de instalação que é informada pelo instalador pode ser utilizada para instalação, que por padrão fica em C:\ARQUIVOS DE PROGRAMAS\POSTGRESQL\8.X\. Na etapa que segue, deverá ser informada uma senha que serve para configurar um usuário de sistema operacional no computador local. Este usuário ficará invisível e será utilizado apenas pelo PostgreSQL para iniciar os serviços necessários. A senha a ser informada poderá ser definida no momento da instalação, como se trata de um usuário do sistema operacional que ficará invisível pode-se informar uma senha básica (por exemplo: 123456). Quando clica-se em Próximo e a senha não foi definida o instalador perguntará se ele deve definir uma, caso seja escolhida a opção sim, a senha a ser criada poderá ser anotada na mensagem que será exibida pelo instalador. Etapa de criação do usuário de SO. Na etapa seguinte serve basicamente para iniciar o serviço do PostgreSQL, selecionando configurações básicas de cluster, como porta, se aceita conexões externas, o locale (que é a definição de regionalismo para a instalação do postgreSQL, o padrão é C), a codificação do banco de dados (padrão LATIN1, para banco de dados IPM) e o nome do superusuário (do banco de dados) que deve ser postgres. Informe a senha para este usuário. A senha aqui deve ser sigilosa pois o usuário postgres possuirá todos os privilégios sobre todos os bancos de dados do cluster. ® IPM Informática Pública Municipal Programa Jovens Talentos 7 Etapa de criação de usuário de BD. Na etapa final são apresentadas informações coletadas durante as etapas anteriores do instalador e opção de concluir deve ser acionada. Pronto! A instalação do PostgreSQL foi realizada com sucesso, neste momento já é possível fazer acesso ao banco de dados utilizando a ferramenta pgAdminII. A instalação do PostgreSQL no Linux é feita seguindo outras instruções que estão disponíveis em ftp.ipm.com.br/util. OS ARQUIVOS POSTGRESQL.CONF E PG_HBA.CON F O arquivo PostgreSQL.conf e o arquivo pg_hba.conf ficam localizados na pasta onde a basta DATA está localizada. Esta pasta geralmente fica dentro da pasta de instalação do SGBD, mas pode ser modificada. São arquivos de configuração que possuem todos os parâmetros disponíveis e possíveis de serem customizados para a instância do SGBD instalada. No arquivo PostgreSQL.conf estão definidos dados genéricos de configuração, os principais itens de configuração estão listados abaixo: Parâmetro Descrição listen_addresses Indica qual a regra geral para escuta IPs de entrada. Pode-se definir um host específico que será o único a acessar o SGBD ou então todos através do * Port Porta que o SGBD está escutando no servidor. Por padrão é 5432 max_connections Indica o número máximo de conexões simultâneas disponíveis para o servidor. Padrão 100 No arquivo pg_hba.conf estão definidas as regras de conexão ao SGBD. Pode-se através dele determinar quais as máquinas (hosts) que podem fazer acesso ao SGBD, incluindo definir a política de quais databases podem acessar e através de quais usuários do SGBD. Para cada linha de configuração pode-se definir o método de autenticação, podendo ser TRUST (confiável, não exige senha para acesso) ou MD5 (seguro, exige senha para autenticação). A FERRAMENTA PGADMIN ftp://ftp.ipm.com.br/util ® IPM Informática Pública Municipal Programa Jovens Talentos 8 Toda aplicação utilizada para acessar a camada de softwares do SGBD é conhecida por cliente ou console de acesso. Os consoles de acesso geralmente permitem que sejam registrados um ou vários servidorese permite a navegação entre os databases e seus objetos. Além disso pode-se executar instruções SQL como forma de consulta e/ou manutenção do banco. Abaixo é mostrada a tela principal do pgAdminIII. Neste caso é mostrado que existem 45 databases (Bancos de Dados) cadastrados, 3 TableSpaces (Espaços de Tabelas) configurados e 388 Users (Utilizadores ou Usuários), na área marcada como 1. Na área 6, são mostradas informações detalhadas sobre o servidor selecionado, como descrição, nome da máquina (IP) e porta. Na parte inferior da tela são exibidos códigos SQL quando for o caso. 1. Indica qual o servidor que está conectado no momento; 2. Serve para selecionar um ou mais bancos de dados para utilização bem como informa a quantidade de bancos de dados que estão disponíveis para visualização na seção; 3. Os tablespaces criados estão disponíveis nesta visualização com possibilidade de manutenção; 4. Mostra os grupos criados e/ou disponíveis para utilização no PostgreSQL; 5. Lista de usuários que estão criados no servidor disponíveis para utlização. Na lista de usuários existirão tanto usuários de sistema como usuários comuns do banco de dados. Para qualquer objeto selecionado pode-se acessar funções disponíveis através do menu pop-down, visível através do botão direito do mouse sobre o objeto. Para cada objeto um menu é acionado, com as funções disponíveis. CONECTANDO A UM SERVIDOR Para registrar um novo servidor no pgAdmin, clique no menu "Ficheiro/Adicionar Servidor...", conforme demonstrado abaixo: ® IPM Informática Pública Municipal Programa Jovens Talentos 9 Será exibida a seguinte tela solicitando informações para conexão: 1. Informe o nome do servidor, este nome pode ser qualquer um, serve para identificar o servidor posteriomente; 2. Informe neste campo o IP do servidor; 3. Neste campo é solicitada a porta em que o PostgreSQL está instalado e sendo executado, a porta padrão do PostgreSQL é 5432, porém esta pode mudar de instalação para instalação. 4. Informe neste campo a configuração para SSL (acesso seguro), por padrão esta opção fica em branco; 5. Informe o nome do banco de dados de manutenção, que é o primeiro banco de dados que será acessado quando conecta-se ao servidor. Por padrão coloca-se pgipm ou então pode-se colocar postgres, conforme mostra na figura; 6. Informe o nome do usuário de acesso ao banco de dados (não o usuário do servidor). Se a configuração do servidor não exige autenticação por senha, pode-se utilizar o usuário postgres, caso exija deverá ser informada a senha do usuário postgres; 7. Neste campo deve-se inserir a senha de acesso do usuário do banco de dados. Se for o primeiro acesso a senha e o nome do usuário (6) devem ser os que foram informados na instalação do banco de dados; 8. Selecione esta opção caso deseja armazenar a senha de acesso para uma próxima seção; ® IPM Informática Pública Municipal Programa Jovens Talentos 10 9. Caso você deseja que o pgAdmin restaure informações da última seção, selecione esta opção; 10. Informe neste campo uma condição (SQL) válida para seleção de database na seção do pgAdmin. Ex: datname IN ('live_db', 'test_db'); 11. Serviço é utilizado para especificar parâmetros de controle de serviços do processo do banco de dados (depende do sistema operacional). Por padrão fica em branco; 12. Marque esta opção caso deseja conectar imediatamente no banco de dados quando clicar em OK. POSSÍVEIS PROBLEMAS DE CONEXÃO Ao realizar a primeira conexão podem acontecer alguns problemas, conforme relacionado abaixo: could not connect to Server. Connection refused: Este erro ocorre por que o servidor especificado não está aceitando conexão seja por que o ip foi informado errado ou na configuração do servidor não está aceitando conexões esternas, verifique a configuração da instalação do servidor de banco de dados; FATAL: no pg_hba.conf entry: Este erro é exibido caso no arquivo de configuração de acesso pg_hba.conf, não esteja informada uma regra que possibilite o cliente (computador local) se conectar ao host (servidor). Em caso de erro o pgAdminIII exibe mensagens como abaixo, que exibem o erro com clareza, e explicam os motivos pelos quais os erros ocorrem. VISUALIZANDO OBJETOS Uma parte muito importante que compete aos administradores de bancos de dados é a visualização dos objetos do banco e sua manutenção, além dos processos de Vacuum e Backup já comentados, existem ainda outras importantes estratégias de manutenção que devem ser seguidas como a constante verificação de índices, chaves primárias e constraints dos objetos do banco de dados. O pgAdmin fornece visualização simples e rápida do estado dos objetos, para que medidas possam ser adotadas pelo administrador no sentido de corrigir falhas. Na imagem mostrada abaixo é exibida uma tabela e suas constraints (chave ® IPM Informática Pública Municipal Programa Jovens Talentos 11 primária, índice e campos) (1), são exibidas também informações sobre o objeto atualmente selecionado (2) e o código SQL de criação do objeto (3). Para cada objeto selecionado pode-se clicar com o botão direito do mouse sobre o mesmo para que um menu pop- down seja mostrado com as opções disponíveis. CRIANDO UM USUÁRIO Por padrão o PostgreSQL possui o usuário postgres para acesso ao sgbd, mas pode-se estabelecer e manter uma política de acesso e usuários a nível de SGBD conforme necessidade. Para criar um usuário utilizando a ferramenta pgAdmin, na visualização de objetos, vá até o item usuários e clique com o botão direito do mouse sobre o mesmo, escolha a opção Novo Usuário... Informe o nome do usuário, no campo ID deixe em branco, pois o banco criará um ID automático, informe a senha e, se necessário, informe uma data para expiração da senha. Na parte inferior da tela informe se é usuário supervisor (marcando a opção Superusuário) e se o mesmo tem privilégios necessários para criação de banco de dados. CRIANDO UM DATABASE Para criar um database no pgAdmin, basta clicar com o botão direito do mouse sobre o item Banco de Dados, na visualização de objetos e em seguida na opção Novo Banco de Dados..., ou então clicar no botão (na barra de ferramentas) com o item banco de dados selecionado. ® IPM Informática Pública Municipal Programa Jovens Talentos 12 Ao clicar na opção Novo Banco de Dados, a seguinte tela será exibida: 1. Informe um nome para o banco de dados, não podem ser utilizados caracteres acentuados nem espaços. Ao informar um nome com letras maiúsculas e minúsculas, o nome do banco passa a ser case sensitive (sensitivo ao texto), ou seja toda vez que o banco for referenciado em códigos SQL deve ser informado com o nome igual (considerando letras maiúsculas e minúsculas). Por padrão recomenda-se criar um nome com todas as letras em minúsculo para evitar problemas futuros; 2. Informe o dono do banco de dados (owner) que deverá ser um usuário previamente configurado; 3. Na codificação utilizamos padrão SQL_ASCII, que irá aceitar todos os caracteres possíveis, outros formados (como UTF8 ou LATIN) podem não aceitar determinados conjuntos de caracteres; 4. Modelo a ser utilizado como base para criação do database, pode ser escolhido qualquer outro database previamente configurado no servidor, utiliza-se por padrão template1 ou template0 (quando template1 está sendo utilizado); 5. Informe o tablespace a ser utilizado para gravar os dados fisicamente do banco de dados. O PostgreSQL ao ser instalado por padrão já cria um tablespace chamado default, este tablespace é definido como padrão para utilização, dependendo da configuração do servidor podem existir outros tablespaces configurados. Veja mais informações no tópico Tablespace; 6. No campo schema restriction informe nomes de schemas que não podem ser visualizados. Já no campo comentário informe um texto para identificação do bancode dados, este texto é exportado com os dados em backups. CRIANDO UM SCHEMA ® IPM Informática Pública Municipal Programa Jovens Talentos 13 Para criar um schema utilizando o pgAdmin, clique com o botão direito do mouse sobre o item selecionado banco de dados, na visualização de objetos e selecione a opção Novo Objeto, em seguida no menu da direta clique em Novo Esquema... Para criar um schema basta informar o seu nome e o dono, o nome do schema vale a mesma regra de nomes do banco de dados. A FERRAMENTA DE EDIÇÃO DE CONSULTAS O pgAdminIII disponibiliza uma ferramenta completa para edição de consultas (queryes), com possibilidades avançadas como verificação de performance (explain), mensagems detalhadas de erros, e histórico de execução de códigos SQL. Existem também outras funcionalidades como, Macros, Favoritos, etc. 1. Barra de ferramentas (menu), disponibiliza as funções para execução de códigos SQL; 2. Mostra em qual conexão (banco de dados) está se executando o comando; ® IPM Informática Pública Municipal Programa Jovens Talentos 14 3. Área de execução de códigos SQL. Conforme mostrado na imagem os quadros mostram o final de linha, isto pode ser habilitado/desabilitado no menu Visualizar/Fins de linha. Outras opções de visualização estão disponíveis para edição de códigos; 4. Neste painel podem ser inseridos comentários ou textos para anotações ref. ao trabalho atual; 5. Abas, que mostram as opções disponíveis para esta tela. Na aba Saída de Dados estão disponíveis os dados que retornaram da consulta, na ava Mensagens são exibidas mensagens de erro e na ava Histórico são exibidos os códigos recentemente executados; 6. Na aba Explain pode ser exibida uma explicação do banco de dados sobre a execução do comando atual, para exibir a explicação pressione F7 ou vá no menu Consultas/Explicação. Para executar apenas um bloco de comandos basta selecioná-lo e clicar no botão para executar ou pressionar CTRL+E, conforme mostrado abaixo: ® IPM Informática Pública Municipal Programa Jovens Talentos 15 MODELAGEM DE DADOS O DIAGRAMA ENTIDADE RELACIONAMENTO As estruturas necessárias para armazenar os dados no banco de dados são conhecidas como estruturas de dados e podem ser representadas por diagramas como o DER (Diagrama Entidade Relacionamento). Por motivos de facilidade de manuseio/uso, performance, pesquisas, etc., faz-se necessária uma boa modelagem de dados para armazenamento dos mesmos no banco de dados. A estruturação de um banco de dados começa com uma definição básica (porém objetiva) dos dados necessários para armazenamento no banco de dados. Isto é conseguido em parte através da análise realizada pelos analistas, na fase de concepção do software aplicativo de banco de dados. Em seguida deve-se estabelecer um primeiro modelo de dados, chamado modelo conceitual, onde leva-se para um diagrama exatamente a estrutura que está definida na análise - bruta - sem qualquer normalização. O próximo passo é a definição de um modelo lógico de dados, onde devem ser definidas as entidades mais importantes e aplicadas regras de relacionamento entre elas, deve-se também nesta fase resolver problemas de normalização. Por fim, deve-se criar o modelo físico que considere todas as características do SGBD alvo. Muitos problemas encontrados após a implementação de um banco de dados têm sua origem em uma modelagem de dados feita sem uma análise mais profunda do escopo do projeto. Outro fator que colabora para uma má modelagem é o desconhecimento de técnicas como normalização e desnormalização de tabelas, bem como a não adoção de integridade referencial, que auxiliam na definição mais ajustada do modelo à realidade que atenderá. O modelo de dados (conhecido como MER ou DER), é muito importante para guiar o processo de construção de queryes de consulta, dentre as funções do MER destacamos: Tabelas/Entidades e Campos/Atributos Tipos de dados Ligações/Relacionamentos entre tabelas Chaves Primárias Chaves Estrangeiras DICAS DE MODELAGEM DE DADOS 1. Sempre faça modelagem de dados, isso ajuda no entendimento do problema e no planejamento de uma solução mais aderente aos seus objetivos. O objetivo do modelo conceitual é a definição do problema, não a solução; 2. Elimine qualquer redundância de dados. Redundâncias permitidas são aquelas relativas as chaves estrangeiras, que fazem referência à chave primária de outra tabela. Por exemplo, não se deve repetir nomes/descrições em tabelas relacionadas, pois eles podem ser facilmente obtidos através de relacionamentos; 3. Utilizar um padrão para dar nomes a entidades. Normalmente, nomes de entidades são no singular; 4. Atribuir nomes significativos a entidades, atributos e relacionamentos. Nomes que não representam seu real objetivo dificultam a compreensão do modelo; 5. Deve-se determinar os relacionamentos e, decidir como é a relação de dependência entre cada entidade é sempre importante. Os tipos de relacionamentos podem ser: a. 0:1 (mínimo: nenhum - máximo: um); b. 0:N (mínimo: nenhum - máximo: muitos); c. 1:1 (mínimo: um - máximo: um); d. 1:N (mínimo: um - máximo: muitos); e. N:N (mínimo: muitos - máximo: muitos); 6. Relacionamentos N:N ou que possuem atributos normalmente geram novas tabelas no modelo lógico. O nome do relacionamento pode ser utilizado como nome da tabela e deve ser cuidadosamente escolhido; ® IPM Informática Pública Municipal Programa Jovens Talentos 16 7. Atenção especial para entidades desconectadas no diagrama. Podem não ser um problema, mas precisam ser verificadas. Por exemplo, é comum que entidades que representem parâmetros estejam soltas no diagrama. 8. Definir corretamente a obrigatoriedade para atributos das entidades de forma a retratar o objetivo da entidade. Por exemplo, o nome de cliente deve ser obrigatoriamente preenchido, pois não faz sentido cadastrar um cliente sem seu nome. Muitas vezes preocupa-se apenas com obrigatoriedade de atributos chave, mas esta questão é importante para todos os atributos, tomando-se o devido cuidado de não impor restrições demais que impeçam que novos registros possam ser inseridos; 9. Não é recomendado armazenar o resultado de cálculos nas tabelas. O correto é que o cálculo seja gerado sob demanda, normalmente em consultas, relatórios, etc; 10. Toda tabela deve ter uma chave primária, que pode ser simples ou composta. A chave primária é o identificador do registro e deve ser única dentro de uma tabela; 11. Ao determinar a chave primária, deve-se escolher, em cada tabela, quais colunas formarão a chave primária. Para uma coluna ser candidata à chave primária, deverá atender aos principais requisitos: a. Deverá ser a menor possível; b. O seu valor deverá ser diferente de vazio ou zero (not null); c. Deverá ser de preferência numérica; d. O seu valor deverá ser único para toda a tabela; 12. Chaves estrangeiras devem corresponder a chaves primárias da relação associada ou ser nulas, quando não for um campo obrigatório; 13. Relacionamentos são representados por chaves estrangeiras, ou Foreign Keys (FK), atributos correspondentes à chave primária de outra tabela, estabelecendo a base para a integridade referencial. No exemplo abaixo o atributo PESCODIGO chave primária da tabela TBPESSOA, foi repetido na tabela TBPESSOACONTATO para representar o relacionamento. Desta forma, um contato deve estar presente na tabela TBPESSOA através do código da pessoa. 14. Relacionamentos 1:1 podem ser mapeados numa única tabela (quando possuem a mesma chave primária), em duas tabelas (quando as chaves primárias são diferentes e um dos lados do relacionamento é obrigatório) ou em três tabelas (quando o relacionamento é opcional em ambos os lados). Caso a pessoa possa possuir apenas três contatos pré-determinados, poderiamos resolver a situação na própria tabela TBPESSOA. Quando uma pessoapode possuir vários contatos, precisaremos de uma tabela a mais para armazenar esses contatos. No caso 2 um imóvel deverá ser de uma pessoa. Neste caso pode-se utilizar uma tabela para armazenar os dados do imóvel e outra para os dados da pessoa: ® IPM Informática Pública Municipal Programa Jovens Talentos 17 No caso 3 teremos várias pessoas que devem possuir vários imóveis (N:N), porém o imóvel não precisa ser de alguém e a pessoa não precisa ter imóvel, neste caso se faz necessária a criação de uma terceira tabela entre TBPESSOA e TBIMOVEL para armazenar este relacionamento: 15. Sempre utilizar normalização dos dados. É uma forma de verificar sua qualidade, diminuindo redundâncias e incoerências no modelo de dados. O processo de normalização aplica uma série de regras sobre as tabelas de um modelo para verificar se estas estão corretamente planejadas. Embora existam seis formas normais, ou regras de normalização (são cinco Formas Normais e a Forma normal de Boyce-codd), normalmente utiliza-se as três primeiras formas normais; 16. A primeira forma normal, preocupa-se em eliminar atributos compostos. Assim, atributos como Endereçco devem ser decompostos em Logradouro, Número, Complemento, Bairro, Cidade, Estado, CEP; 17. A primeira forma norma também se refere a eliminar valores multivalorados, no caso de pessoa e contatos da pessoa, se a tabela TBPESSOA possuísse apenas o campo PESTelContato, como mostrado no exemplo anterior, estaria errado, neste caso poderiam ser adotadas duas soluções: 1 - criar vários campos com telefones úteis para cada pessoa; 2 - criar uma outra tabela que armazene os dados de contato (como é o caso do nosso modelo); 18. A segunda forma normal determina que atributos não chave devem ser funcionalmente dependentes apenas da chave primária, ou seja, deve-se analisar se todo atributo que não é chave primária depende totalmente dela. Assim, não é necessário se preocupar com esta forma normal para tabelas que tenham chaves primárias simples, com apenas um atributo. No exemplo abaixo esta situação fica evidente, não está correto os campos TAXLARGURA e TAXCOMPRIMENTO, na tabela TBTAXA, já que são informações do imóvel, devem estar em TBIMOVEL. 19. A terceira forma normal refere-se a atributos não chave mutuamente independentes, ou seja, que não dependam um do outro. Desta forma, é verificado se existe dependência funcional entre atributos não chave. No exemplo abaixo, a primeira representação de TBPESSOA possui os campos LOGCODIGO e LOGNOME, são campos dependentes (considere que a tabela TBLOGRADOURO não exista neste momento), esta representação está nas primeira e segunda formas normais. A segunda representação, porém é a correta, pois aplicando-se a terceira forma normal, os atributos LOGCODIGO e LOGNOME transforma-se em uma outra tabela TBLOGRADOURO. ® IPM Informática Pública Municipal Programa Jovens Talentos 18 20. Utilizar uma ferramenta CASE para modelagem de dados. Caso contrário, o modelo tenderá a ficar desatualizado rapidamente, pois dificilmente as modificações que são necessárias no esquema de dados são refletidas para a documentação sem o auxilio de uma ferramenta apropriada. O PADRÃO P006 – PADRÃO DE MODELAGEM DE DADOS DA IPM A IPM possui o documento P006 que trata de um padrão de modelagem de dados adotado por toda a fábrica do novo software Atende.NET Web. Este documento tem por objetivo definir padrões para o desenvolvimento de modelos de dados, lógico e conceitual, quanto a sua definição, ferramenta de desenvolvimento e deverá ser utilizado por todos os desenvolvedores e analistas como base na construção de modelagem. O documento está logicamente dividido em áreas de interesse. O padrão P006 encontra-se disponível através do arquivo p006_-_padro_para_modelagem_de_dados.pdf e também no repositório central do dicionário. SQL CONCEITOS GERAIS SQL vem do inglês Structured Query Language (em português Linguagem Estruturada de Consulta), linguagem desenvolvida pela IBM que usa comandos simples, baseados em palavras em inglês, para realizar buscas em bancos de dados. É suportado por várias plataformas de bancos de dados. Uma entrada SQL é constituída por uma seqüência de comandos. Um comando é composto por uma seqüência de termos (tokens), terminada por um ponto-e-vírgula (“;”). O fim do fluxo de entrada também termina o comando. Quais termos são válidos depende da sintaxe particular de cada comando. Nos exemplos abaixo, o comando com ";" irá executar corretamente. Já o comando sem o ";" poderá não funcionar se não for o único comando da seqüência a ser executado. SELECT * FROM SCHEMA.TABELA; SELECT * FROM SCHEMA.TABELA Um termo pode ser uma palavra chave, um identificador, um identificador entre aspas, um literal (ou constante), ou um caractere especial. Geralmente os termos são separados por espaço em branco (espaço, tabulação ou nova-linha), mas não há necessidade se não houver ambigüidade (normalmente só acontece quando um caractere especial está adjacente a um termo de outro tipo). Exemplos de identificador. SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ADD, ETC. Além disso, podem existir comentários na entrada SQL. Os comentários não são termos, na realidade são equivalentes a espaço em branco. --EXEMPLO DE COMENTÁRIO EM SQL Abaixo é exibida uma estrutura padrão de um comando SQL, podendo este variar de acordo com a seleção de dados necessária bem como a estrutura de tabelas do banco de dados em questão. 1 - Definição da lista de campos da seleção SELECT CAMPO1, ...., CAMPON 2 - Definição da origem dos campos/dados ® IPM Informática Pública Municipal Programa Jovens Talentos 19 FROM TABELA1, ..., TABELAN 3 - Definição das junções com outras tabelas (quando não definido no FROM) [LEFT|INNER|RIGTH|FULL] JOIN TABELAX ON TABELAX.CAMPO1 = TABELA1.CAMPO1 4 - Definição de restrições de seleção WHERE TABELA1.CAMPO1 > VALORX AND [CONDICAON] 5 - Definição de agrupamentos GROUP BY TABELA1.CAMPO1, TABELAX.CAMPOX 6 - Definição de restrição sobre operador de agregação HAVING COUNT(*) > 0 7 - Definição da ordem dos dados ORDER BY TABELA1.CAMPO1 8 - União/Interseção/Exclusão com outro comando SQL com o mesmo número de colunas [UNION|INTERSECT|EXCEPT] [ALL] Para os nomes de objetos (Tabelas, Colunas, etc), vale a regra de literal, ou seja, um campo com o nome "Opção", informado entre aspas (") tem seu nome exatamente igual a "Opção", neste caso o campo opcao não existe para o banco de dados. Porém se o campo é criado com o nome OPCAO, poderá ser identificado por opcao normalmente. Os códigos SQL dividem-se em 2 (usualmente) 4 (tecnicamente) grandes grupos: Dois grupos: DDL e DML; Quatro grupos: DDL, DCL, DML e DQL. DDL: Data Definition Language. Exemplo de comandos: CREATE, ALTER e DROP; DML: Data Manipulation Language. Exemplo de comandos: INSERT, UPDATE e DELETE; DCL: Data Control Language, também conhecido como DDL. Exemplo de comandos: GRANT, REVOKE; DQL: Data Query Language, também conhecido como DML: Exemplo de comandos: SELECT. TÉCNICAS DE ORGANIZAÇÃO DE CÓDIGO SQL Abaixo segue uma listagem com algumas técnicas reconhecidas como boas para a escrita de instruções SQL: GERAL 1. Código sempre em maiúsculo. 2. Respeitar 7 espaços iniciais para palavras reservadas do código SQL. Tem como objetivo indicar onde começa cada cláusula. Ex: SELECT CAST(TABELA1.CAMPO1 AS VARCHAR(100)) AS CAMPO1, CAST(TABELA2.CAMPO2 AS VARCHAR(100)) AS CAMPO2 FROM SCHEMA1.TABELA1 LEFT JOIN SCHEMA1.TABELA2 ON TABELA2.CODIGO = TABELA1.CODIGO WHERE TABELA1.CODIGO < 100 CLÁUSULA SELECT ® IPM Informática Pública Municipal Programa Jovens Talentos 20 1. Para cada campo deve-se respeitar uma linha. 2. Cada campo deve ser nomeado sem caracteres especiais através do comando “AS”. 3. Para cada campo deve-se usar o comando“CAST” para definir o seu tipo. 4. A referencia de cada campo deve-ser precedida do nome da sua tabela mais o caractere ponto(.). CLÁUSULA FROM 1. Todas as tabelas devem ser referencias através do seu schema ou usuario (dependendo do banco de dados), mais o nome da tabela. CLÁUSULA JOIN 1. Cada relação que o SQL possuir deve ser declarado da seguinte maneira: TIPO [LEFT, INNER, RIGHT, FULL] + JOIN + SCHEMA OU USUÁRIO + ON Obs: Deve-se respeitar uma linha para esta declaração. 2. As condições devem ser declaradas da seguinte maneira: CAMPO OU VALOR + OPERADOR [=, <, >, <>] + CAMPO OU VALOR + OPERADOR DE LIGAÇÃO [AND, OR] Obs: Deve-se respeitar uma linha para esta declaração. CLÁUSULA WHERE 1. Cada condições deve ser declarada da seguinte maneira CAMPO OU VALOR + OPERADOR [=, <, >, <>] + CAMPO OU VALOR + OPERADOR DE LIGAÇÃO [AND, OR] OUTRAS DICAS 1. Usar sempre SUBSTR em vez de SUBSTRING, pois o SUBSTRING não é reconhecido pelo banco de dados Oracle. 2. Ao relacionar tabelas no quesito performance é sempre melhor usar JOIN, porém quando há necessidade de retornar apenas uma coluna ou apenas um valor somado, pode-se utilizar sub-select, pois deixará o código mais organizado. 3. Ao relacionar tabelas deve-se sempre observar as chaves primárias das tabelas envolvidas ou a utilização de índices, tendo como objetivo melhorar a performance. SQL - DML SELEÇÃO DE INFORMAÇÕES - SELECT O comando SELECT retorna linhas de uma ou mais tabelas. As linhas que satisfazem a condição WHERE são candidatas para seleção; se WHERE for omitido, todas as linhas são candidatas. Veja abaixo a utilização de forma geral: SELECT [ ALL | DISTINCT [ ON ( EXPRESSÃO [, ...] ) ] ] * | EXPRESSÃO [ AS NOME_SAÍDA ] [, ...] [ FROM ITEM_DE [, ...] ] [ WHERE CONDIÇÃO ] [ GROUP BY EXPRESSÃO [, ...] ] [ HAVING CONDIÇÃO [, ...] ] [ { UNION | INTERSECT | EXCEPT } [ ALL ] SELECT ] [ ORDER BY EXPRESSÃO [ ASC | DESC | USING OPERADOR ] [, ...] ] [ FOR UPDATE [ OF NOME_DA_TABELA [, ...] ] ] [ LIMIT { CONTADOR | ALL } ] [ OFFSET INÍCIO ] onde item_de pode ser: ® IPM Informática Pública Municipal Programa Jovens Talentos 21 [ ONLY ] NOME_DA_TABELA [ * ] [ [ AS ] ALIÁS [ ( LISTA_COLUNA_ALIAS ) ] ] | ( SELECT ) [ AS ] ALIÁS [ ( LISTA_COLUNA_ALIAS ) ] | ITEM_DE [ NATURAL ] TIPO_DE_JUNÇÃO ITEM_DE [ ON CONDIÇÃO_DE_JUNÇÃO | USING ( LISTA_COLUNA_JUNÇÃO ) ] Entradas: Expressão: O nome de uma coluna da tabela ou uma expressão. Nome_saída: Especifica outro nome para uma coluna retornada utilizando a cláusula AS. Este nome é utilizado, principalmente, como o título da coluna exibida. Também pode ser utilizados para fazer referência ao valor da coluna nas cláusulas ORDER BY e GROUP BY. Mas o nome_saída não pode ser usado nas cláusulas WHERE e HAVING; nestes casos deve-se escrever novamente a expressão. Item_de: A referência a uma tabela, uma subconsulta ou uma cláusula de junção. Veja abaixo para obter detalhes. Condição: Uma expressão booleana produzindo um resultado falso ou verdadeiro. Veja a descrição das cláusulas WHERE e HAVING abaixo. Select: Um comando SELECT com todas as suas funcionalidades, exceto as cláusulas ORDER BY, FOR UPDATE e LIMIT (mesmo estas podem ser utilizadas quando o SELECT está entre parênteses). Os itens da cláusula FROM podem conter: Nome_da_tabela: O nome de uma tabela ou de uma visão existente. Se ONLY for especificado, somente esta tabela é consultada. Se ONLY não for especificado a tabela, e todas as suas tabelas descendentes porventura existentes, serão consultadas. O * pode ser apensado ao nome da tabela para indicar que as tabelas descendentes devem ser consultadas, mas na versão corrente este é o comportamento padrão (Nas versões anteriores a 7.1 ONLY era o comportamento padrão). Alias: Um nome substituto para o nome_da_tabela precedente. Um aliás é utilizado para abreviar ou para eliminar ambigüidade em autojunções (onde a mesma tabela é referenciada várias vezes). Se um, aliás, for escrito, uma lista de aliás de coluna também pode ser escrita para fornecer nomes substitutos para uma ou mais colunas da tabela. Select: Uma subconsulta pode aparecer na cláusula FROM, agindo como se sua saída fosse criada como uma tabela temporária pela duração do comando SELECT. Observe que a subconsulta deve estar entre parênteses, e que um aliás deve ser fornecido para esta subconsulta. Tipo_de_junção: Um entre [ INNER ] JOIN, LEFT [ OUTER ] JOIN, RIGHT [ OUTER ] JOIN, FULL [ OUTER ] JOIN, ou CROSS JOIN. Para os tipos de junção INNER e OUTER, exatamente um entre NATURAL, ON condição_de_junção, ou USING (lista_coluna_junção) deve estar presente. Para CROSS JOIN, nenhum destes itens pode aparecer. Condição_de_junção: Uma condição de qualificação, similar à condição WHERE, exceto que somente se aplica aos dois itens sendo unidos por esta cláusula JOIN. Lista_coluna_junção: A condição USING lista de colunas ( a, b, ... ) é uma forma abreviada da condição ON tabela_esquerda.a = tabela_direita.a AND tabela_esquerda.b = tabela_direita.b... Na verdade, as linhas retornadas não são as linhas produzidas pelas cláusulas FROM/WHERE/GROUP BY/HAVING diretamente; mais precisamente, as linhas da saída são formadas computando-se as expressões de saída do SELECT para cada linha selecionada. O * pode ser escrito na lista de saída como uma abreviação para todas as colunas das linhas selecionadas. Pode-se escrever também nome_da_tabela.* como uma abreviação para as colunas provenientes de apenas uma tabela, ex: ® IPM Informática Pública Municipal Programa Jovens Talentos 22 SELECT TBCLIENTE.CLICODIGO, TBTELEFONE.TELNUMERO FROM TBCLIENTE, TBTELEFONE WHERE TBCLIENTE.CLICODIGO = TBTELEFONE.CLICODIGO A opção DISTINCT elimina as linhas repetidas do resultado, enquanto que a opção ALL (o padrão) retorna todas as linhas candidatas, incluindo as repetidas. DISTINCT ON elimina as linhas que correspondem a todas as expressões especificadas, mantendo apenas a primeira linha de cada conjunto de repetidas. As expressões do DISTINCT ON são interpretadas usando as mesmas regras dos itens do ORDER BY; veja abaixo. Observe que a "primeira linha" de cada conjunto não pode ser prevista, a menos que ORDER BY seja usado para garantir que a linha desejada apareça primeiro. Por exemplo, SELECT DISTINCT ON (CLICODIGO) CLICODIGO, TELNUMERO FROM TBTELEFONE ORDER BY CLICODIGO, TELNUMERO; RÓTULOS DE COLUNAS Podem ser atribuídos nomes para as entradas da lista de seleção para processamento posterior. Neste caso "processamento posterior" é uma especificação opcional de ordenação e a aplicação cliente (por exemplo, os títulos das colunas para exibição). Por exemplo: SELECT A AS VALOR, B + C AS SOMA FROM ... Se nenhum nome de coluna de saída for especificado utilizando AS, o sistema atribui um nome padrão. Para referências simples a colunas é o nome da coluna referenciada. Para chamadas de função é o mesmo nome da função. Para expressões complexas o sistema gera um nome genérico. A nomeação das colunas de saída neste caso é diferente daquela feita na cláusula FROM. Este duto na verdade permite renomear a mesma coluna duas vezes, mas o nome escolhido na lista de seleção é que será passado adiante. Nomes temporários podem ser atribuídos a tabelas, e a referências de tabela complexas, para ser utilizado como referência à tabela derivada em processamentos posteriores. Isto é chamado de aliás de tabela. Para criar um aliás de tabela deve ser escrito FROM REFERÊNCIA_TABELA AS ALIÁS ou FROM REFERÊNCIA_TABELA ALIÁS A palavra chave AS é opcional. O aliás pode ser qualquer identificador. Uma aplicação típica de aliases de tabelas é atribuir identificadores curtos para nomes longos de tabelas, para manter a cláusula de junção legível. Por exemplo: SELECT * FROM UM_NOME_MUITO_COMPRIDOU JOIN OUTRO_NOME_MUITO_COMPRIDO O ON U.ID = O.NUM; CLÁUSULA FROM/JOIN A cláusula FROM especifica uma ou mais tabelas de origem para o SELECT. Se múltiplas tabelas de origem forem especificadas o resultado será, conceitualmente, o produto Cartesiano de todas as linhas de todas estas tabelas -- mas, geralmente, condições de qualificação são adicionadas para restringir as linhas retornadas a um pequeno subconjunto do produto Cartesiano. ® IPM Informática Pública Municipal Programa Jovens Talentos 23 Quando o item da cláusula FROM é simplesmente o nome de uma tabela, implicitamente são incluídas as linhas das subtabelas desta tabela (filhas que herdam). Especificando-se ONLY causa a supressão das linhas das subtabelas da tabela. Um item da cláusula FROM pode ser também uma subconsulta entre parênteses (note que uma cláusula aliás é exigida para a subconsulta!). Esta característica é extremamente útil porque esta é a única maneira de se obter múltiplos níveis de agrupamento, agregação ou ordenação em uma única consulta. Finalmente, um item da cláusula FROM pode ser uma cláusula JOIN, que combina dois itens do FROM (Use parênteses, se for necessário, para determinar a ordem de aninhamento). O CROSS JOIN e o INNER JOIN são um produto Cartesiano simples, o mesmo que seria obtido listando-se os dois itens no nível superior do FROM. O CROSS JOIN é equivalente ao INNER JOIN ON (TRUE), ou seja, nenhuma linha é removida pela qualificação. Estes tipos de junção são apenas uma notação conveniente, porque não fazem nada que não poderia ser feito usando simplesmente o FROM e o WHERE. O LEFT OUTER JOIN retorna todas as linhas do produto Cartesiano qualificado (i.e., todas as linhas combinadas que passam pela condição ON), mais uma cópia de cada linha da tabela à esquerda para a qual não há uma linha da tabela à direita que tenha passado pela condição ON. Esta linha da tabela à esquerda é estendida por toda a largura da tabela combinada inserindo-se nulos para as colunas da tabela à direita. Observe que somente as condições ON ou USING do próprio JOIN são consideradas na hora de decidir quais linhas possuem correspondência. Condições ON ou WHERE externas são aplicadas depois. De forma inversa, o RIGHT OUTER JOIN retorna todas as linhas da junção, mais uma linha para cada linha da tabela à direita sem correspondência (estendida com nulos na tabela à esquerda). Isto é apenas uma conveniência da notação, porque poderia ser convertida em um LEFT OUTER JOIN trocando-se a tabela à direita pela tabela à esquerda. O FULL OUTER JOIN retorna todas as linhas da junção, mais uma linha para cada linha da tabela à esquerda sem correspondência (estendida com nulos na tabela à direita), mais uma linha da tabela à direita sem correspondência (estendida com nulos na tabela à esquerda) Verifique a imagem a seguir, ela especifica como seria o funcionamento do JOIN em cada uma de suas possibilidades de acordo com os dados contidos nas tabelas TBPESSOA e TBPESSOACONTATO. ® IPM Informática Pública Municipal Programa Jovens Talentos 24 Existe uma outra forma de se fazer join com o uso de NATURAL onde não se faz necessário o uso do ON, este tipo de join faz a junção de todas as colunas de mesmo nome em ambas das tabelas envolvidas. Deve-se tomar cuidado ao usar o NATURAL pois colunas que não fazem parte da ligação, podem ser utilizadas equivocadamente para fazer isto. Ex: SELECT * FROM TBPESSOA NATURAL LEFT JOIN TBPESSOACONTATO Neste caso irá funcionar corretamente, agora considere a seguinte situação: SELECT * FROM TBPESSOA NATURAL LEFT JOIN TBIMOVEL Neste caso existe além dos campos PESCODIGO em comum nas duas tabelas, também o campo LOGCODIGO (coincidentemente), o que fará com que a junção não seja realizada de forma correta. Pode-se utilizar como alternativa à este problema do NATURAL o USING, conforme exemplo abaixo: SELECT * FROM TBPESSOA LEFT JOIN TBIMOVEL USING(PESCODIGO) Neste caso o using especifica qual é a(s) coluna(s) que deve(m) ser utilizada(s) na junção das tabelas. Para todos os tipos de JOIN, exceto CROSS JOIN, deve-se escrever exatamente um entre ON condição_de_junção, USING (lista_coluna_junção), ou NATURAL. A cláusula ON é o caso mais geral: pode ser escrita qualquer expressão de qualificação envolvendo as duas tabelas da junção. A forma USING lista de colunas (a, b, ...) é uma abreviação para a condição ON tabela_esquerda.a = tabela_direita.a AND tabela_esquerda.b = tabela_direita.b... Além disso, USING implica em que somente uma coluna de cada par de colunas equivalentes será incluída na saída do JOIN, e não as duas. NATURAL é uma abreviação para USING quando a lista menciona todas as colunas das tabelas com mesmo nome. Observe o exemplo abaixo: SELECT * FROM SPUNICO.UNICO LEFT JOIN SPUNICO.LOGRADOU ON LOGRADOU.CODIGO = UNICO.LOGRADOURO WHERE UNICO.CODIGO BETWEEN 19 AND 200 Utilizando-se da opção explicação da consulta no pgAdmimIII, verifica-se que a execução está correta pois a ligação foi realizada utilizando-se a chave primária da tabela logradou. Isto faz com que a consulta seja executada em menor tempo. Quando não é possível utilizar campos da chave primária para fazer a ligação entre as tabelas, tente utilizar campos que façam parte de algum índice. Caso existam índices parciais (que possuam os campos exigidos pela ligação, porém possuem mais campos) insira condições obvias mas que utilizem esses campos a mais para que o índice seja utilizado. Ex: Observe o exemplo abaixo: SELECT HISLIQ.HISTORICO FROM CPARQ.HISLIQ LEFT JOIN CPARQ.LIQEMP ON HISLIQ.CODCLI = LIQEMP.CODCLI AND HISLIQ.ANO = LIQEMP.ANO AND HISLIQ.SEQLIQ = LIQEMP.SEQUENCIA AND HISLIQ.TIPEMP = 'E' AND HISLIQ.SEQ > 0 ® IPM Informática Pública Municipal Programa Jovens Talentos 25 No caso acima, para uma ligação entre as tabelas hisliq e liqemp, não existem todos os campos da chave primária disponíveis, neste caso foram adicionadas condições explícitas onde a chave primária seja evidenciada para que o banco de dados utilize o índice da chave primária para executar a consulta. SUB-SELECT Uma subconsulta escalar é um comando SELECT comum, entre parênteses, que retorna exatamente uma linha com uma coluna. O comando SELECT é executado e o único valor retornado é utilizado na expressão de valor. É errado utilizar uma consulta que retorne mais de uma linha ou mais de uma coluna como subconsulta escalar. Por exemplo, a consulta abaixo retorna a maior população de cidade de cada estado: SELECT NOME, (SELECT MAX(POPULACAO) FROM CIDADES WHERE CIDADES.ESTADO = ESTADOS.NOME) FROM ESTADOS; Pode-se utilizar também uma sub-consulta na cláusula from, como sendo uma "tabela virtual", que pode retornar várias linhas e várias colunas. Trata-se de um SELECT normal. Neste caso sempre deve-se nomear a sub-consulta. SELECT ORIGEM.LOGCODIGO AS "CÓDIGO", ORIGEM.LOGTIPO AS "TIPO", ORIGEM.LOGDESCRICAO AS "DESCRIÇÃO" FROM (SELECT * FROM TBLOGRADOURO WHERE TBLOGRADOURO.LOGCODIGO > 10) ORIGEM WHERE ORIGEM.LOGCODIGO < 15 Resultado da consulta: 11 Rua Logr. 11 12 Beco Logr. 12 13 Rua Logr. 13 14 Travessa Logr. 14 Observe as tabelas abaixo: Processamento do Banco de dados: Para cada linha processada de TBPESSOA o sub-select irá realizar um outro comando SQL em TBLOGRADOURO, para isto deve-se especificar a chave de junção dos dois comandos SELECT. Ex: SELECT PESNOME, (SELECT LOGDESCRICAO FROM TBLOGRADOURO WHERE TBLOGRADOURO.LOGCODIGO = TBPESSOA.LOGCODIGO) AS ENDERECO FROM TBPESSOA SUB-SELECT X JOIN Como apresentado anteriormente existe a possibilidade de se utilizar sub-select como origem de dados de consulta e também para buscar informações sobre uma única coluna. Essas situações também são possíveis através do uso do comandoJOIN. ® IPM Informática Pública Municipal Programa Jovens Talentos 26 Qual opção é a melhor ? Tudo depende da quantidade de colunas que se deseja retornar de outra tabela relacionada. Quanto mais colunas forem necessárias melhor é com a utilização de JOIN. Exemplos: SELECT PESNOME, PESTIPO, (SELECT LOGDESCRICAO FROM TBLOGRADOURO WHERE TBLOGRADOURO.LOGCODIGO = TBPESSOA.LOGCODIGO) AS LOGRADOURO FROM TBPESSOA Neste caso a utilização de uma sub-consulta pode ser mais eficiente do que o uso de JOIN, pois trata-se do retorno de apenas uma coluna (LOGDESCRICAO) e utilizando-se a chave primária da tabela TBLOGRADOURO como critério de pesquisa. SELECT PESNOME, PESTIPO, (SELECT LOGDESCRICAO FROM TBLOGRADOURO WHERE TBLOGRADOURO.LOGCODIGO = TBPESSOA.LOGCODIGO) AS LOGRADOURO_NOME, (SELECT LOGTIPO FROM TBLOGRADOURO WHERE TBLOGRADOURO.LOGCODIGO = TBPESSOA.LOGCODIGO) AS LOGRADOURO_TIPO FROM TBPESSOA No primeiro caso executando-se a explicação da consulta obtêm-se os seguintes resultados: SEQ SCAN ON TBPESSOA (COST=100000000.00..100593070.65 ROWS=147965 WIDTH=38) (ACTUAL TIME=6.937..92.395 ROWS=10000 LOOPS=1) SUBPLAN -> INDEX SCAN USING TBLOGRADOURO_PKEY ON TBLOGRADOURO (COST=0.00..3.99 ROWS=1 WIDTH=32) (ACTUAL TIME=0.004..0.005 ROWS=1 LOOPS=10000) INDEX COND: ((LOGCODIGO)::INTEGER = ($0)::INTEGER) TOTAL RUNTIME: 97.761 MS No segundo caso obtêm-se os seguintes resultados: SEQ SCAN ON TBPESSOA (COST=100000000.00..101183446.65 ROWS=147965 WIDTH=38) (ACTUAL TIME=6.894..163.446 ROWS=10000 LOOPS=1) SUBPLAN -> INDEX SCAN USING TBLOGRADOURO_PKEY ON TBLOGRADOURO (COST=0.00..3.99 ROWS=1 WIDTH=14) (ACTUAL TIME=0.004..0.005 ROWS=1 LOOPS=10000) INDEX COND: ((LOGCODIGO)::INTEGER = ($0)::INTEGER) -> INDEX SCAN USING TBLOGRADOURO_PKEY ON TBLOGRADOURO (COST=0.00..3.99 ROWS=1 WIDTH=32) (ACTUAL TIME=0.004..0.005 ROWS=1 LOOPS=10000) INDEX COND: ((LOGCODIGO)::INTEGER = ($0)::INTEGER) TOTAL RUNTIME: 168.968 MS Utilizando-se Join: SELECT PESNOME, PESTIPO, LOGDESCRICAO, LOGTIPO ® IPM Informática Pública Municipal Programa Jovens Talentos 27 FROM TBPESSOA NATURAL LEFT JOIN TBLOGRADOURO Com join obtêm-se os seguintes resultados: HASH LEFT JOIN (COST=100000154.00..100005438.04 ROWS=147965 WIDTH=80) (ACTUAL TIME=9.456..41.341 ROWS=10000 LOOPS=1) HASH COND: (("OUTER".LOGCODIGO)::INTEGER = ("INNER".LOGCODIGO)::INTEGER) -> SEQ SCAN ON TBPESSOA (COST=100000000.00..100002694.65 ROWS=147965 WIDTH=38) (ACTUAL TIME=6.856..15.894 ROWS=10000 LOOPS=1) -> HASH (COST=143.81..143.81 ROWS=4074 WIDTH=50) (ACTUAL TIME=2.577..2.577 ROWS=0 LOOPS=1) -> INDEX SCAN USING TBLOGRADOURO_PKEY ON TBLOGRADOURO (COST=0.00..143.81 ROWS=4074 WIDTH=50) (ACTUAL TIME=0.018..1.845 ROWS=1000 LOOPS=1) TOTAL RUNTIME: 46.485 MS Verifica-se com os resultados obtidos que a sub-select é uma opção viavel quando se trata de retorno de no máximo uma coluna por tabela relacionada, quando trata-se de dois ou mais campos a melhor solução é o uso de JOIN. O uso de JOIN mostrou-se (neste caso) mais eficiente em qualquer situação, porém cada caso é um caso e deve-se utilizar a explicação da consulta para verificar os melhores caminhos. OPERADORES DE AGREGAÇÃO Uma expressão de agregação representa a aplicação de uma função de agregação nas linhas selecionadas pela consulta. Uma função de agregação reduz vários valores de entrada a um único valor de saída, tal como a soma ou a média dos valores entrados. A sintaxe da expressão de agregação é uma das seguintes: NOME_DA_AGREGAÇÃO (EXPRESSÃO) NOME_DA_AGREGAÇÃO (ALL EXPRESSÃO) NOME_DA_AGREGAÇÃO (DISTINCT EXPRESSÃO) NOME_DA_AGREGAÇÃO ( * ) onde nome_da_agregação é uma agregação definida anteriormente (possivelmente qualificado pelo nome do esquema), e expressão é qualquer expressão de valor que não contenha uma expressão de agregação. Por exemplo, count(*) retorna o número total de linhas de entrada; count(f1) retorna o número de linhas de entrada onde f1 não é nulo; count(distinct f1) retorna o número de valores distintos não nulos de f1. Uma expressão de agregação pode aparecer apenas na lista de resultados ou na cláusula HAVING do comando SELECT. Seu uso é proibido nas outras cláusulas, tal como WHERE, porque estas cláusulas são avaliadas logicamente antes dos resultados das agregações estarem formados. A Tabela abaixo mostra as funções de agregação internas. Função Tipo do argumento Tipo retornado Descrição avg(expressão) smallint, integer, bigint, real, double precision, numeric ou interval numeric para qualquer argumento de tipo inteiro, double precision para argumento de tipo ponto flutuante, caso contrário o mesmo tipo de dado do argumento a média (média aritmética) de todos os valores de entrada count(*) Bigint número de valores de entrada count (expressão) any Bigint número de valores de entrada para os quais o valor da expressão não é ® IPM Informática Pública Municipal Programa Jovens Talentos 28 nulo max(expressão) qualquer tipo de dado matriz, numérico, cadeia de caracteres, data ou hora o mesmo tipo de dado do argumento valor máximo da expressão entre todos os valores de entrada min(expressão) qualquer tipo de dado matriz, numérico, cadeia de caracteres, data ou hora o mesmo tipo de dado do argumento valor mínimo da expressão entre todos os valores de entrada stddev (expressão) Smallint, integer, bigint, real, double precision ou numeric double precision para argumentos de ponto flutuante, caso contrário numeric desvio padrão da amostra dos valores de entrada sum(expressão) smallint, integer, bigint, real, double precision, numeric ou interval bigint para argumentos smallint ou integer, numeric para argumentos bigint, double precision para argumentos de ponto flutuante, caso contrário o mesmo tipo de dado do argumento somatório da expressão para todos os valores de entrada variance (expressão) smallint, integer, bigint, real, double precision ou numeric double precision para argumentos de ponto flutuante, caso contrário numeric. variância da amostra dos valores de entrada (quadrado do desvio padrão da amostr a) AGRUPAMENTO – GROUP BY A cláusula GROUP BY permite dividir a tabela em grupos de linhas que correspondem a um ou mais valores. SELECT LISTA_SELEÇÃO FROM ... [WHERE ...] GROUP BY REFERÊNCIA_COLUNA_AGRUPAMENTO A cláusula GROUP BY é utilizada para agrupar linhas de uma tabela que compartilham os mesmos valores em todas as colunas listadas. Em que ordem as colunas são listadas não faz diferença. A finalidade é reduzir cada grupo de linhas compartilhando valores comuns a uma única linha agrupada representando todas as linhas do grupo. Isto é feito para eliminar redundância na saída, e/ou para calcular agregações aplicáveis a estes grupos. Por exemplo: => SELECT * FROM TESTE1; X | Y ---+--- A | 3 C | 2 B | 5 A | 1 (4 ROWS) => SELECT X FROM TESTE1 GROUP BY X; X --- ® IPM Informática Pública Municipal Programa Jovens Talentos 29 A B C (3 ROWS) Na segunda consulta não poderia ser escrito SELECT * FROM teste1 GROUP BY x, porque não existe um único valor da coluna y que poderia ser associado com cada grupo. As colunas agrupadas podem ser referenciadas na lista de seleção, porque possuem um valor constante conhecido para cada grupo. HAVINGA cláusula HAVING permite selecionar somente os grupos de linhas que atendem a uma condição específica. Se uma tabela for agrupada utilizando a cláusula GROUP BY, mas há interesse em alguns grupos apenas, a cláusula HAVING pode ser utilizada, da mesma forma que a cláusula WHERE, para remover grupos da tabela agrupada. A sintaxe é: SELECT LISTA_SELEÇÃO FROM ... [WHERE ...] GROUP BY ... HAVING EXPRESSÃO_BOOLEANA As expressões na cláusula HAVING podem fazer referência tanto a expressões agrupadas quanto a expressões não agrupadas (as quais necessariamente envolvem uma função de agregação). Exemplo: => SELECT X, SUM(Y) FROM TESTE1 GROUP BY X HAVING SUM(Y) > 3; X | SUM ---+----- A | 4 B | 5 (2 ROWS) => SELECT X, SUM(Y) FROM TESTE1 GROUP BY X HAVING X < 'C'; X | SUM ---+----- A | 4 B | 5 (2 ROWS) Agora vamos fazer um exemplo mais próximo da realidade: SELECT CHAVE, COUNT(*) FROM SPTABELA HAVING COUNT(*) > 1 Neste exemplo irá retornar todos os registros de sptabela cuja chave seja igual e exista mais do que 1. ORDENAÇÃO - ORDER BY A cláusula ORDER BY faz com que as linhas retornadas sejam classificadas na ordem especificada. Se ORDER BY não for especificado, as linhas retornam na ordem que o sistema considera mais fácil de gerar. ® IPM Informática Pública Municipal Programa Jovens Talentos 30 Após a consulta ter produzido uma tabela de saída (após a lista de seleção ter sido processada) esta tabela pode, opcionalmente, ser ordenada. Se nenhuma ordenação for especificada, as linhas retornam em uma ordem aleatória. Na verdade, neste caso a ordem depende dos tipos de plano de varredura e de junção e da ordem no disco, mas não se deve confiar nisto. Uma determinada ordem de saída somente pode ser garantida se a etapa de ordenação for explicitamente especificada. A cláusula ORDER BY especifica a ordenação: SELECT LISTA_SELEÇÃO FROM EXPRESSÃO_TABELA ORDER BY COLUNA1 [ASC | DESC] [, COLUNA2 [ASC | DESC] ...] Onde: Coluna1, etc: fazem referência às colunas da lista de seleção. Pode ser tanto o nome de saída de uma coluna, quanto o número da coluna. Alguns exemplos: SELECT A, B FROM TABELA1 ORDER BY A; SELECT A + B AS SOMA, C FROM TABELA1 ORDER BY SOMA; SELECT A, SUM(B) FROM TABELA1 GROUP BY A ORDER BY 1; Como uma extensão do padrão SQL, o PostgreSQL também permite a ordenação por expressões arbitrárias: SELECT A, B FROM TABELA1 ORDER BY A + B; Também é permitido fazer referência a nomes de colunas da cláusula FROM que foram renomeados na lista de seleção: SELECT A AS B FROM TABELA1 ORDER BY A; ou SELECT A AS B FROM TABELA1 ORDER BY B; Mas estas extensões não funcionam nas consultas que envolvem UNION, INTERSECT ou EXCEPT, e não são portáveis para outros bancos de dados SQL. Cada coluna especificada pode ser seguida pela palavra opcional ASC ou DESC, para determinar a forma de ordenação como ascendente ou descendente. A forma ASC é o padrão. A ordenação ascendente coloca os valores menores na frente, sendo que "menor" é definido nos termos do operador <. De forma semelhante, a ordenação descendente é determinada pelo operador >. Se mais de uma coluna de ordenação for especificada, as últimas colunas são utilizadas para ordenar as linhas iguais na ordem imposta pelas primeiras colunas ordenadas. LIMIT E OFFSET A cláusula LIMIT permite que retorne para o usuário apenas um subconjunto das linhas produzidas pela consulta. LIMIT e OFFSET permitem trazer apenas uma parte das linhas geradas pela consulta: SELECT LISTA_SELEÇÃO FROM EXPRESSÃO_TABELA [LIMIT { NÚMERO | ALL }] [OFFSET NÚMERO] Se o limite for fornecido, não mais que esta quantidade de linhas será retornada (mas possivelmente menos, se a consulta produzir menos linhas). LIMIT ALL é o mesmo que omitir a cláusula LIMIT. OFFSET informa para saltar esta quantidade de linhas antes de começar a retornar as linhas para o cliente. OFFSET 0 é o mesmo que omitir a cláusula OFFSET. Se tanto OFFSET quando LIMIT forem especificados, então são saltadas OFFSET linhas antes de começar a contar as LIMIT linhas que serão retornadas. ® IPM Informática Pública Municipal Programa Jovens Talentos 31 É necessário possuir o privilégio SELECT na tabela para poder ler seus valores (Consulte os comandos GRANT e REVOKE). EXERCÍCIOS 1. Crie uma seleção de dados da tabela TBIMOVEIS fazendo uma contagem de registros, agrupando por LOGRADOURO, retornando uma coluna com a contagem dos registros e outra com o código do logradouro; 2. Crie uma seleção de dados da tabela TBLOGRADOURO retornando os campos LOGCODIGO, LOGTIPO e LOGDESCRICAO, ordenando a mesma por LOGTIPO, de forma ASCENDENTE; 3. Crie uma seleção de dados da tabela TBPESSOA buscando os campos PESNOME, PESCODIGO, PESSEXO, PESTIPO e LOGCODIGO. Para o nome das colunas selecionadas deverá retornar os seguintes nomes (respectivamente): "Nome ou Razão", "Código", "Sexo", "Tipo", "Cód. Logradouro"; 4. Crie uma seleção de dados da tabela TBPESSOA retornando os campos PESNOME, PESCODIGO, LOGCODIGO e o nome do LOGRADOURO relacionado, que deverá ser buscado da tabela TBLOGRADOURO; 5. Crie uma seleção de dados da tabela TBIMOVEL fazendo junção com a tabela TBPESSOA, retornando as seguintes colunas:TBIMOVEL.IMVCODIGO, TBIMOVEL.IMVLARGURA, TBIMOVEL.IMVCOMPRIMENTO e TBPESSOA.PESNOME, com os nomes originais para as colunas. 6. Crie uma seleção dos 10 (dez) maiores imóveis, considerando o M², retorne juntamente o nome dos proprietários dos imóveis exibidos; A CLÁUSULA WHERE A sintaxe da Cláusula WHERE é WHERE EXPRESSÃO_BOOLEANA A expressão_booleana pode ser qualquer expressão que retorna um valor booleano. Após o processamento da cláusula FROM ter sido feito, cada linha da tabela virtual derivada é verificada com relação à condição de pesquisa. Se o resultado da condição for verdade, a linha é mantida na tabela de saída, senão (ou seja, se o resultado for falso ou nulo) a linha é desprezada. Normalmente a condição de pesquisa faz referência a pelo menos uma coluna da tabela gerada pela cláusula FROM; embora isto não seja requerido, se não for assim a cláusula WHERE não terá utilidade. Em muitos casos esta expressão possui a forma: EXPRESSÃO OP_CONDIÇÃO EXPRESSÃO Ou OP_LOGICO EXPRESSÃO Nota: A condição de junção de uma junção interna pode ser escrita tanto na cláusula WHERE quanto na cláusula JOIN. Por exemplo, estas duas expressões de tabela são equivalentes: FROM A, B WHERE A.ID = B.ID AND B.VAL > 5 e FROM A INNER JOIN B ON (A.ID = B.ID) WHERE B.VAL > 5 Qual destas formas deve ser utilizada é principalmente uma questão de estilo. A sintaxe do JOIN na cláusula FROM provavelmente não é muito portável para outros sistemas gerenciadores de banco de dados SQL. Para as junções externas não existe escolha em nenhum caso: devem ser feitas na cláusula FROM. A cláusula ON/USING da junção externa não é equivalente à condição WHERE, porque determina a adição de linhas (para as linhas de entrada sem correspondência) assim como a remoção de linhas do resultado final. Abaixo estão mostrados alguns exemplos de cláusulas WHERE: SELECT ... FROM FDT WHERE C1 > 5 ® IPM Informática Pública Municipal Programa Jovens Talentos 32 SELECT ... FROM FDT WHERE C1 IN (1, 2, 3) SELECT ... FROM FDT WHERE C1 IN (SELECT C1 FROM T2) SELECT ... FROM FDT WHERE C1 IN (SELECT C3 FROM T2 WHERE C2 = FDT.C1 + 10) SELECT ... FROM FDT WHERE C1 BETWEEN (SELECT C3 FROM T2 WHERE C2 = FDT.C1 + 10) AND 100 SELECT ... FROM FDT WHERE EXISTS (SELECT C1 FROM T2 WHERE C2 > FDT.C1) Sendo que FDT é a tabela derivada da cláusula FROM. As linhas que não aderem à condição de pesquisa da cláusula WHERE são eliminadas de fdt. Deve ser observada a utilização de subconsultas escalares como expressões de valor. Assim como qualquer outra consulta, as subconsultaspodem utilizar expressões de tabela complexas. Deve ser observado, também, como FDT é referenciada nas subconsultas. A qualificação de c1 como fdt.c1 somente é necessária se c1 também for o nome de uma coluna na tabela de entrada derivada da subconsulta. Entretanto, a qualificação do nome da coluna torna mais clara a consulta, mesmo quando não é necessária. OPERADORES LÓGICOS Os operadores lógicos habituais que estão disponíveis são: AND, OR e NOT O SQL utiliza a lógica booleana de três valores, onde o valor nulo representa o "desconhecido". Observe as seguintes tabelas verdade: A b a AND b a OR b TRUE TRUE TRUE TRUE TRUE FALSE FALSE TRUE TRUE NULL NULL TRUE FALSE FALSE FALSE FALSE FALSE NULL FALSE NULL NULL NULL NULL NULL OPERADORES DE COMPARAÇÃO Os seguintes operadores de comparação estão disponíveis: Operador Descrição < Menor que > Maior que <= Menor que ou igual a >= Maior que ou igual a = igual <> ou != Diferente. O Operador !=, somente está disponível para PostgreSQL Between Entre <x> e <y>. Ex: ...(CODIGO BETWEEN 1 AND 2)... Neste exemplo retornará as linhas cujo código estiver entre 1 e 2 Like Nome que contenha o conjunto de caracteres. Podem ser utilizados os caracteres ‘%’ procedendo ao 2º parâmetro de comparação e também terminando. Ex: ...(NOME LIKE ‘%JOÃO%’)... Neste caso ira pesquisar na coluna NOME todas as linhas que contém JOÃO. Existe ainda o operador ILIKE, que faz o mesmo serviço do like, porém é CASE INSENSITIVE (não importa maiúsculas e minúsculas). a NOT a TRUE FALSE FALSE TRUE NULL NULL ® IPM Informática Pública Municipal Programa Jovens Talentos 33 Os operadores de comparação estão disponíveis em todos os tipos de dado onde fazem sentidos. Todos os operadores de comparação são operadores binários que retornam valores do tipo boolean; expressões como 1 < 2 < 3 não são válidas (porque não existe o operador < para comparar um valor booleano com 3). OPERADOR IN Sintaxe Básica: EXPRESSÃO IN (VALOR[, ...]) O lado direito é uma lista de expressões escalares entre parênteses. O resultado é “verdade” se o resultado da expressão à esquerda for igual a qualquer uma das expressões à direita. Esta é uma notação abreviada de: EXPRESSÃO = VALOR1 OR EXPRESSÃO = VALOR2 OR ... Deve ser observado que se o resultado da expressão do lado esquerdo for nulo, ou se não houver valor igual do lado direito e pelo menos uma expressão do lado direito tiver resultado nulo, o resultado da construção IN será nulo, e não falso. Isto está de acordo com as regras normais do SQL para combinações booleanas de valores nulos. Pode-se utilizar também em conjunto com o operador IN uma subconsulta que retorna várias linhas e apenas uma coluna, por exemplo: SELECT * FROM TBPESSOA WHERE PESCODIGO IN (SELECT PESCODIGO FROM TBIMOVEL) Neste caso irá retornar todas as pessoas que possuem imóveis. Existe uma outra forma de se utilizar o operador IN com subconsulta que retorna várias colunas e várias linhas: SELECT * FROM TBTAXA WHERE (PESCODIGO, IMVCODIGO) IN (SELECT PESCODIGO, IMVCODIGO FROM TBIMOVEL WHERE PESCODIGO = 1) Além do IN pode-se realizar a sua negação através do NOT IN. Ex: EXPRESSÃO NOT IN (VALOR[, ...]) OPERADOR EXISTS O argumento do EXISTS é uma declaração SELECT arbitrária, ou uma subconsulta. A subconsulta é processada para determinar se retorna alguma linha. Se retornar pelo menos uma linha, o resultado de EXISTS é “verdade”; se a subconsulta não retornar nenhuma linha, o resultado de EXISTS é “falso”. Este comando é uma boa alternativa ao comando IN. A subconsulta pode referenciar variáveis da consulta que a envolve, que atuam como constantes durante a execução da subconsulta. A subconsulta geralmente só é processada até ser determinado se retorna pelo menos uma linha, e não até o fim. Não é aconselhável escrever uma subconsulta que tenha chamadas a funções externas (tal como chamar uma função de sequência); pode ser difícil prever se a subconsulta será processada rapidamente ou não. Como o resultado depende apenas de uma linha ser retornada, e não do conteúdo da linha, normalmente não há interesse na saída da subconsulta. Uma convenção de codificação habitual é escrever todos os testes de EXISTS na forma: EXISTS(SELECT 1 WHERE ...). Entretanto, existem exceções para esta regra, como as subconsultas que utilizam INTERSECT. ® IPM Informática Pública Municipal Programa Jovens Talentos 34 Este exemplo simples é como uma junção interna em PESCODIGO, mas produz no máximo uma linha de saída para cada linha de TBPESSOA, mesmo havendo várias linhas correspondentes em TBIMOVEL: SELECT PESNOME FROM TBPESSOA WHERE EXISTS(SELECT 1 FROM TBIMOVEL WHERE TBIMOVEL.PESCODIGO = TBPESSOA.PESCODIGO) EXPRESSÃO CONDICIONAL – CASE A expressão CASE do SQL é uma expressão condicional genérica, semelhante às declarações if/else de outras linguagens. A cláusula CASE pode ser empregada sempre que a utilização de uma expressão for válida. A condição é uma expressão que retorna um resultado booleano. Se a condição for verdade, então o valor da expressão CASE é o resultado. Se a condição for falsa, todas as cláusulas WHEN seguintes são percorridas da mesma maneira. Se nenhuma condição WHEN for verdade, então o valor da expressão CASE é o valor do resultado na cláusula ELSE. Se a cláusula ELSE for omitida, e nenhuma condição for satisfeita, o resultado será nulo. CASE WHEN CONDIÇÃO THEN RESULTADO [WHEN ...] [ELSE RESULTADO] END Um exemplo: => SELECT * FROM TESTE; Resultado: A --- 1 2 3 => SELECT A, CASE WHEN A=1 THEN 'UM' WHEN A=2 THEN 'DOIS' ELSE 'OUTRO' END FROM TESTE; Resultado: A | CASE ---+------- 1 | UM 2 | DOIS 3 | OUTRO Os tipos de dado de todas as expressões para resultado devem poder ser convertidos no mesmo tipo de dado de saída. CASE EXPRESSÃO WHEN VALOR THEN RESULTADO [WHEN ...] [ELSE RESULTADO] END ® IPM Informática Pública Municipal Programa Jovens Talentos 35 A expressão é computada e comparada com todas as especificações de valor nas cláusulas WHEN, até encontrar um que seja igual. Se não for encontrado nenhum valor igual, é retornado o resultado na cláusula ELSE (ou o valor nulo). Podemos utilizar junto com a cláusula CASE o IN (visto anteriormente), conforme exemplo abaixo: SELECT PESNOME, CASE WHEN PESCODIGO IN (SELECT PESCODIGO FROM TBIMOVEL) THEN 'SIM' ELSE 'NÃO' END AS TEM_IMOVEL FROM TBPESSOA; A expressão CASE não processa nenhuma subexpressão que não seja necessária para determinar o resultado. Por exemplo, esta é uma forma possível de evitar o erro gerado pela divisão por zero: SELECT ... WHERE CASE WHEN X <> 0 THEN Y/X > 1.5 ELSE FALSE END Outra forma de se utilizar o CASE é em expressões de comparação, na cláusula WHERE. (Obs: disponível em alguns casos apenas no PostgreSQL): SELECT ... FROM TBPESSOA WHERE (CASE WHEN LOGCODIGO IS NOT NULL THEN 1 ELSE 0) <> 0 EXPRESSÃO CONDICIONAL – COALESCE Sintaxe básica: COALESCE(VALOR [, ...]) A função COALESCE retorna o primeiro de seus argumentos que não for nulo. Geralmente é útil para substituir o valor padrão dos valores nulos quando os dados são usados para exibição. Por exemplo: SELECT COALESCE(DESCRICAO, DESCRICAO_CURTA, '(NENHUMA)')... Como a expressão CASE, a função COALESCE não processa os argumentos que não são necessários para determinar o resultado, ou seja, os argumentos à direita do primeiro argumento que não forem nulo não são avaliados. EXERCÍCIOS 1. Considere o seguinte código SQL: SELECT TBPESSOA.PESCODIGO, TBPESSOA.PESNOME, TBPESSOA.PESSEXO, TBPESSOA.PESTIPO, TBPESSOA.LOGCODIGO, TBLOGRADOURO.LOGDESCRICAO FROM TBPESSOA LEFT JOIN TBLOGRADOURO ON TBLOGRADOURO.LOGCODIGO= TBPESSOA.LOGCODIGO Insira as seguintes condições de filtro: a. Quando o código da pessoa (PESCODIGO) for maior que 500; b. Quando o tipo do logradouro (LOGTIPO) for igual a 'Rua'; c. Quando o tipo de pessoa não for outros; d. Quando o nome da pessoa conter "20". e. Quando existirem os caracteres "C" e "7" no nome da pessoa. ® IPM Informática Pública Municipal Programa Jovens Talentos 36 2. Construa um código SQL que retorne os dados de pessoa, quando o código da pessoa for entre 20 e 5000, desconsiderando pessoas que residam nos logradouros de 20 a 50. 3. Construa um código SQL que retorne os dados de pessoas, sendo que para os campos PESTIPO e PESSEXO devem ser exibidos os conteúdos (Física, Jurídica, Outros) e (Masculino, Feminino, Não Informado) respectivamente. CONVERSÃO DE TIPOS Uma conversão de tipo (type cast) especifica a conversão de um tipo de dado em outro. O PostgreSQL aceita duas sintaxes equivalentes para conversão de tipo: CAST ( EXPRESSÃO AS TIPO ) EXPRESSÃO::TIPO Ex: Retorna a coluna "Metro Quadrado" no formato VARCHAR. SELECT CAST((IMVLARGURA*IMVCOMPRIMENTO) AS VARCHAR(20)) AS "METRO QUADRADO" FROM TBIMOVEL WHERE PESCODIGO = 1 Quando a conversão é aplicada a uma expressão de valor de tipo conhecido, representa uma conversão em tempo de execução. A conversão será bem-sucedida apenas se estiver disponível uma operação de conversão de tipo adequada. Esta forma de utilização é diferente de aplicar a conversão de tipos em uma constante. Neste caso a constante 'cadeia de caracteres' deve ter o seu valor padronizado com o tipo a ser convertido, caso contrário gerará erro de conversão. CAST ( 'CADEIA DE CARACTERES' AS TIPO ) Ex: Converte 20,50 (Fator) para o formato VARCHAR. CAST(20.50 AS VARCHAR(20)) AS "FATOR" O texto da constante cadeia de caracteres é passado para a rotina de conversão da entrada para o tipo chamado tipo. O resultado é uma constante do tipo indicado. A conversão explícita de tipo pode ser omitida caso não haja ambigüidade com relação ao tipo que a constante deva ter (por exemplo, quando é atribuída diretamente para uma coluna de uma tabela), neste caso é convertida automaticamente. Também é possível especificar uma conversão de tipo utilizando a sintaxe na forma de função: NOME_DO_TIPO ( EXPRESSÃO ) Entretanto, somente funciona para os tipos cujos nomes também são válidos como nome de função. Por exemplo, double precision não pode ser utilizado desta maneira, mas a forma equivalente float8 pode. Também, os nomes interval, time e timestamp somente podem ser utilizados desta maneira se estiverem entre aspas, devido a conflitos sintáticos. OPERADORES DE FORMAÇÃO DE DADOS As funções de formatação fornecem um poderoso conjunto de ferramentas para converter vários tipos de dado (date/time, integer, floating point, numeric) em cadeias de caracteres formatadas, e para converter cadeias de caracteres formatadas em tipos de dado específicos. A Tabela a seguir mostra estas funções, que seguem uma convenção de chamada comum: o primeiro argumento é o valor a ser formatado, e o segundo argumento é o modelo que define o formato da entrada ou da saída. Função Retorna Descrição Exemplo to_char(timestamp, text) text converte carimbo de tempo (time stamp) em cadeia de caracteres to_char(timestamp 'now','HH12:MI:SS') to_char(interval, text) text converte intervalo em cadeia de caracteres to_char(interval '15h 2m 12s','HH24:MI:SS') ® IPM Informática Pública Municipal Programa Jovens Talentos 37 Função Retorna Descrição Exemplo to_char(int, text) text converte inteiro em cadeia de caracteres to_char(125, '999') to_char(double precision, text) text converte real e precisão dupla em cadeia de caracteres to_char(125.8, '999D9') to_char(numeric, text) text converte numérico em cadeia de caracteres to_char(numeric '-125.8', '999D99S') to_date(text, text) date converte cadeia de caracteres em data to_date('05 Dec 2000', 'DD Mon YYYY') to_timestamp(text, text) timestamp converte cadeia de caracteres em carimbo de tempo to_timestamp('05 Dec 2000', 'DD Mon YYYY') to_number(text, text) numeric converte cadeia de caracteres em numérico to_number('12,454.8-', '99G999D9S') Ex: SELECT TAXDATA, TO_CHAR(TAXDATA, 'DD/MM/YYYY') AS "DATA FORMATADA" FROM TBTAXA WHERE PESCODIGO = 1 Como saída teremos: 2009-03-31 para o campo TAXDATA e 31/03/2009 para o campo "Data Formatada" OPERAÇÕES COM CONJUNTOS - UNION, INTERSECT E EXCEPT As consultas SELECT podem ser combinadas usando os operadores UNION, INTERSECT e EXCEPT. Use parênteses, se for necessário, para determinar a ordem destes operadores. O operador UNION computa a coleção das linhas retornadas pelas consultas envolvidas. As linhas duplicadas são eliminadas, a não ser que ALL seja especificado. CONSULTA1 UNION [ALL] CONSULTA2 CONSULTA1 UNION CONSULTA2 UNION CONSULTA3 significa, na verdade, (CONSULTA1 UNION CONSULTA2) UNION CONSULTA3 O operador INTERSECT computa as linhas que são comuns às duas consultas (interseção). As linhas duplicadas são eliminadas, a não ser que ALL seja especificado. CONSULTA1 INTERSECT [ALL] CONSULTA2 O operador EXCEPT computa as linhas que são retornadas pela primeira consulta, mas que não são retornadas pela segunda consulta. As linhas duplicadas são eliminadas, a não ser que ALL seja especificado. CONSULTA1 EXCEPT [ALL] CONSULTA2 Para ser possível calcular a união, a interseção, ou a diferença entre duas consultas, estas duas consultas precisam ser “compatíveis para união”, significando que as duas devem retornar o mesmo número de colunas, e que as colunas correspondentes devem possuir tipos de dado compatíveis. Nota: Dados dois conjuntos A e B: chama-se diferença ente A e B o conjunto formado pelos elementos de A que não pertencem a B; chama-se interseção de A com B o conjunto formado pelos elementos comuns ao conjunto A e ao conjunto B; chama-se união de A com B o conjunto formado pelos elementos que pertencem a A ou B. EXERCÍCIOS 1. Crie uma seleção de dados da tabela TBPESSOA, convertendo os campos INTEGER e SMALLINT para VARCHAR(7); 2. Crie uma seleção de dados da tabela TBIMOVEL, dos imóveis de PESSOAS FÍSICAS, convertendo os campos IMVLARGURA e IMVCOMPRIMENTO para VARCHAR(15), com o seguinte formato: 0.000,00; ® IPM Informática Pública Municipal Programa Jovens Talentos 38 3. Crie uma seleção de dados da tabela TBTAXA, das taxas com valor maior que R$ 10.000,00, convertendo o a data de lançamento da taxa para VARCHAR(15), com o seguinte formato: DD/MM/AAAA. 4. Crie uma seleção dos dados de pessoas físicas (incluindo informações sobre o endereço) unindo com dados de pessoas jurídicas 5. Considere o seguinte código SQL: SELECT TBPESSOA.PESCODIGO, TBPESSOA.PESNOME, TBPESSOA.PESSEXO, TBPESSOA.PESTIPO, TBPESSOA.LOGCODIGO FROM TBPESSOA com base na instrução acima, construa uma nova instrução SQL, unindo esta instrução com outra similar porém, inserindo as seguintes condições de filtro respectivamente: a) Quando o tipo da pessoa for Física ou Jurídica; b) Quando o tipo da pessoa for Outros. Insira em cada condição um campo descrevendo o tipo: Ex: SELECT "Física" AS TIPO, ...... INSERÇÃO DE INFORMAÇÕES – INSERT Ao ser criada a tabela não contém nenhum dado. A primeira coisa a ser feita para o banco de dados ser útil é colocar dados. Conceitualmente, os dados são inseridos uma linha por vez. É claro que pode ser inserida mais de uma linha, mas não existe modo de inserir menos de uma linha de cada vez. Mesmo conhecendo apenas o valor de algumas colunas, uma linha inteira deve ser criada. Para criar uma linha deve ser utilizado o comando INSERT. Este comando requer o nome da tabela, e um valor para cada coluna da tabela. Por exemplo, considere a seguinte estrutura: CREATE TABLE TBPRODUTO ( PROCODIGO INTEGER, PRONOME TEXT,PROPRECO NUMERIC ); Um comando mostrando a inclusão de uma linha pode ser: INSERT INTO TBPRODUTO VALUES (1, 'QUEIJO', 9.99); Os valores dos dados são colocados na mesma ordem que as colunas aparecem na tabela, separados por vírgula. Geralmente os valores dos dados são literais (constantes), mas expressões escalares também são permitidas. A sintaxe mostrada acima tem como desvantagem necessitar o conhecimento da ordem das colunas da tabela. Para evitar isto, as colunas podem ser declaradas explicitamente. Por exemplo, os dois comandos mostrados abaixo possuem o mesmo efeito do comando mostrado acima: INSERT INTO TBPRODUTO (PROCODIGO, PRONOME, PROPRECO) VALUES (1, 'QUEIJO', 9.99); INSERT INTO TBPRODUTO (PRONOME, PROPRECO, PROCODIGO) VALUES ('QUEIJO', 9.99, 1); A melhor prática para o comando insert é escrever sempre os nomes das colunas. Se não forem conhecidos os valores de todas as colunas, as colunas com valor desconhecido podem ser omitidas. Neste caso, o valor padrão de cada coluna será atribuído à coluna. Por exemplo: INSERT INTO TBPRODUTO (PROCODIGO, PRONOME) VALUES (1, 'QUEIJO'); INSERT INTO TBPRODUTO VALUES (1, 'QUEIJO'); ® IPM Informática Pública Municipal Programa Jovens Talentos 39 A segunda forma é uma extensão do PostgreSQL, que preenche as colunas a partir da esquerda com quantos valores forem fornecidos, e as demais com o valor padrão. Para ficar mais claro, o valor padrão pode ser requisitado explicitamente para cada coluna, ou para toda a linha: INSERT INTO TBPRODUTO (PROCODIGO, PRONOME, PROPRECO) VALUES (1, 'QUEIJO', DEFAULT); INSERT INTO TBPRODUTO DEFAULT VALUES; EXERCÍCIOS Considerando a estrutura criada nas tabelas TBPESSOA, TBLOGRADOURO, TBPESSOACONTATO e TBIMOVEL insira os dados (via código SQL) conforme tabelas abaixo: Obs: Antes de iniciar a inserção dos dados abaixo, apague os dados já existentes na base de dados, utilizando o comando truncate. TABELA: TBPESSOA PESNOME PESSEXO PESTIPO LOGCODIGO Marcos 1 1 2 Pedro 1 1 5 José S/A 1 2 1 Maria 2 1 3 Marta 2 1 4 Papel & CIA 1 2 5 Roberto 1 1 3 Tais 2 1 2 Mônica Presentes 1 2 4 Rivaldo 1 1 5 TABELA: TBLOGRADOURO LOGTIPO LOGDESCRICAO Rua XV de Novembro Avenida Carlos Gomes Travessa Pinheiros BR 470, km 242 Rua São Paulo Estrada Fundo Canoas TABELA: TBPESSOACONTATO PESCODIGO CTPNUMERO CTPDESCRICAO CTPRAMAL 1 4432-5526 Telefone Residencial 1 8822-5560 Telefone Celular 1 3351-2115 Telefone Comercial 2115 2 1123-5526 Telefone Residencial ® IPM Informática Pública Municipal Programa Jovens Talentos 40 3 1124-5527 Telefonista 15 4 9925-2265 Telefone Celular 5 6652-2445 Telefone Residencial 6 9952-2265 Telefone Celular 10 6658-2265 Telefone Residencial 10 9925-2256 Telefone Celular 10 3321-2265 Telefone Comercial 2265 TABELA: TBIMOVEL PESCODIGO IMVDESCRICAO IMVLAR- GURA IMVCOM- PRIMENTO LOGCODIGO 1 Imóvel de Alvenaria 25 52 1 2 Terreno Comercial 20 30 2 5 Sítio 200 1000 5 4 Sala Comercial 5 10 3 8 Apartamento – Cobertura 50 60 4 10 Imóvel de Madeira 20 15 3 ALTERAÇÃO DE INFORMAÇÕES – UPDATE A modificação dos dados armazenados no banco de dados é referida como atualização. Pode ser atualizado uma linha da tabela, todas as linhas da tabela, ou um subconjunto das linhas. Cada coluna pode ser atualizada individualmente; as outras colunas não são afetadas. Para efetuar uma atualização são necessárias três informações: 1. O nome da tabela e da coluna; 2. O novo valor para a coluna; 3. Quais linhas serão atualizadas. O SQL, por si só, não fornece um identificador único para as linhas. Portanto, não é sempre possível poder especificar diretamente a linha que será atualizada. Em vez disso, devem ser especificadas as condições que a linha deve atender para ser atualizada. Somente havendo uma chave primária na tabela (não importando se foi declarada ou não) é possível endereçar uma linha específica, escolhendo uma condição correspondente à chave primária. Ferramentas gráficas de acesso a banco de dados dependem disto para poder atualizar as linhas individualmente. Por exemplo, o comando mostrado abaixo atualiza todos os produtos com preço igual a 5, mudando estes preços para 10: UPDATE TBPRODUTO SET PROPRECO = 10 WHERE PROPRECO = 5; Este comando faz nenhuma, uma, ou muitas linhas serem atualizadas. Não é errado tentar fazer uma atualização sem nenhuma linha correspondente. Vejamos este comando em detalhe: Primeiro aparece a palavra-chave UPDATE seguida pelo nome da tabela. Como usual, o nome da tabela pode ser qualificado pelo esquema, senão é procurado no caminho. Depois aparece a palavra-chave SET, seguida pelo nome da coluna, por um sinal de igual, e do novo valor da coluna. O novo valor da coluna pode ser qualquer ® IPM Informática Pública Municipal Programa Jovens Talentos 41 expressão escalar, e não apenas uma constante. Por exemplo, sendo desejado aumentar o preço de todos os produtos em 10% pode ser usado: UPDATE TBPRODUTO SET PROPRECO = PROPRECO * 1.10; Como pode ser visto, a expressão para obter o novo valor também pode referenciar o valor antigo. Também foi deixada de fora a cláusula WHERE. Quando a cláusula WHERE é omitida significa que todas as linhas da tabela serão atualizadas. Quando está presente apenas a linha atendendo a condição escrita após o WHERE serão atualizadas. Observe que o sinal de igual na cláusula SET é uma atribuição, enquanto o sinal de igual na cláusula WHERE é uma comparação, mas isto não causa ambigüidade. Obviamente, esta condição não precisa ser um teste de igualdade. Também pode ser atualizada mais de uma coluna pelo comando UPDATE, colocando mais de uma atribuição na cláusula SET. Por exemplo: UPDATE MINHA_TABELA SET A = 5, B = 3, C = 1 WHERE A > 0; EXERCÍCIOS Considerando os dados inseridos anteriormente na tabela realizaremos as seguintes manutenções: 1. A pessoa cadastrada com o código 1 deverá ter seu salário alterado para R$ 2.000,00; 2. A Rua 1 teve seu nome alterado para Rua 7766, você deverá alterar o cadastro das pessoas que moram neste endereço para o novo nome da rua; 3. A pessoa 4 Maria, teve sua data de nascimento cadastrada de forma incorreta, você deverá alterar para 15/03/1990.END 4. Para a execução dos exercícios abaixo, considere que você já esteja conectado no servidor de banco de dados utilizando a ferramenta de administração pgAdminIII. Para estes exercícios utilizaremos a base de dados TREINA que já se encontra no servidor. 5. Considerando os dados inseridos anteriormente nas tabelas realizaremos as seguintes manutenções: 6. O Logradouro CARLOS GOMES acaba de se tornar uma RUA, sendo assim deve ser alterado seu tipo de AVENIDA para RUA; 7. Todos os telefones residenciais devem possuir o DDD relacionado, no caso (47); 8. Por descuido do funcionário que cadastra pessoas, ele indicou que pessoas JURÍDICAS eram do sexo MASCULINO, deve-se alterar essas pessoas para sexo NÃO INFORMADO; EXCLUSÃO DE DADOS – DELETE / TRUNCATE Assim como só é possível adicionar dados para toda uma linha, também uma linha só pode ser removida por completo de uma tabela. Na seção Inclusão de Dados foi visto que o SQL não oferece funcionalidade para endereçar diretamente linhas específicas. Portanto, a remoção de linhas só pode ser feita por meio da especificação das condições que as linhas a serem removidas devem atender. Havendo uma chave primária na tabela, então é possível especificar exatamente a linha. Mas também pode ser removido um grupo de linhas atendendo a uma determinada condição, ou podem ser removidas todas as linhas da tabela de uma só vez. É utilizado o comando DELETE para excluir linhas; a sintaxe deste comando é muito semelhante à do comando UPDATE. Por exemplo, para excluir todas as linhas da tabela produtos possuindo preço igual a 10, usa-se: DELETE FROM TBPRODUTOWHERE PROPRECO = 10; Se for escrito simplesmente DELETE FROM TBPRODUTO; ...então todas as linhas da tabela serão excluídas. ® IPM Informática Pública Municipal Programa Jovens Talentos 42 Mas a exclusão de registros por meio do DELETE (no caso de deleção de todos os registros da tabela) não é eficiente, pois os registros não são excluídos fisicamente, ou seja, o espaço não é liberado executando-se este tipo de comando, o mais correto para esta operação é a utilização do comando TRUNCATE, conforme descrito abaixo. TRUNCATE <NOME DA TABELA> EXERCÍCIOS Considerando os dados inseridos anteriormente na tabela realizaremos as seguintes exclusões: 1. Por determinação universal todas as pessoas com nome Marta devem ser eliminadas do planeta, para tanto você deverá excluir essas pessoas da tabela; 2. As pessoas com salário inferior a R$ 1.000,00 não fazem mais parte dos planos da empresa, por tanto devem ser excluídas. 3. A Rua São Paulo acaba de ser explodida, por tanto ela deve ser excluída da base de dados. As pessoas que residiam nesta rua foram transferidas para a Travessa Pinheiros, o cadastro delas deve ser atualizado. Outras tabelas que fazem relacionamento com a tabela de Logradouro devem ser atualizadas também. 4. Pedro acaba de vender seu Telefone Celular, a tabela de contatos da pessoa deve ser alterada, excluindo esta informação. SQL – DDL ORGANIZAÇÃO DE OBJETOS NO POSTGRESQL O PostgreSQL é um sistema de gerenciamento de banco de dados relacional (SGBDR). Isto significa que é um sistema para gerenciar dados armazenados em relações. Uma relação é essencialmente um termo matemático para tabela. A noção de armazenar dados em tabelas é um lugar tão comum hoje em dia que pode parecer totalmente óbvio, mas existem várias outras maneiras de se organizar bancos de dados. Arquivos e diretórios em sistemas operacionais tipo Unix são um exemplo de banco de dados hierárquico. Um desenvolvimento mais moderno é o banco de dados orientado a objeto. Cada tabela é uma coleção nomeada de linhas. Cada linha de uma determinada tabela possui o mesmo conjunto de colunas nomeadas, e cada coluna são de um tipo de dado específico. Enquanto as colunas possuem uma ordem fixa em cada linha, é importante lembrar que o SQL não garante a ordem das linhas dentro de uma tabela (embora as linhas possam ser explicitamente ordenadas para a exibição). As tabelas são agrupadas em bancos de dados, e uma coleção de bancos de dados gerenciada por uma única instância do servidor PostgreSQL constitui um agrupamento de bancos de dados. Todos os objetos do banco de dados (tabelas, campos, índices, constraints, views, functions, etc), devem ser criados (de acordo com padrão definido pela IPM) com seus nomes sem espaço, sem acentuação, preferencialmente em MAIUSCULO. Uma instância do banco de dados pode possuir vários databases e também usuários. ® IPM Informática Pública Municipal Programa Jovens Talentos 43 USUÁRIOS A sintaxe básica para a criação de um usuário de banco de dados é: CREATE ROLE TREINA LOGIN WITH PASSWORD '123456' NOSUPERUSER NOCREATEDB NOCREATEROLE; Para se excluir um usuário é necessário para isto estar acessando o PostgreSQL como superusuário (ex: Postgres) e o mesmo deve estar desconectado do Postgre. O comando é o seguinte: DROP ROLE <NOME DO USUÁRIO> Para que a definição de um usuário possa ser alterada deve-se executar o seguinte comando: ALTER ROLE <NOME DO USUÁRIO> RENAME TO <NOVO NOME> ou ALTER ROLE <NOME DO USUÁRIO> SET <PARÂMETRO> { TO | = } { VALUE | DEFAULT } ou ALTER ROLE NAME RESET <PARÂMETRO> DATABASE Para que possam ser utilizados os recursos do Postgre, após instalado deverá ser criado o banco de dados que servirá como agrupamento das tabelas de todo o sistema. Para tanto deve-se utilizar a seguinte sintaxe: CREATE DATABASE NOME [ WITH [ LOCATION = 'CAMINHO' ] [ TEMPLATE = GABARITO ] [ ENCODING = CODIFICAÇÃO ] ] Entradas: Nome: O nome do banco de dados a ser criado; Caminho (Opcional): Um local alternativo no sistema de arquivos onde será armazenado o banco de dados, especificado como uma cadeia de caracteres; ou DEFAULT para utilizar o local padrão; Gabarito (Opcional): Nome do banco de dados a ser usado como gabarito para a criação do novo banco de dados, ou DEFAULT para utilizar o banco de dados de gabarito padrão (template1); Codificação (Opcional): Método de codificação multibyte a ser utilizado no novo banco de dados. Especifique o nome como uma cadeia de caracteres (por exemplo, 'LATIN1'), ou o número inteiro da codificação, ou DEFAULT para utilizar a codificação padrão. ® IPM Informática Pública Municipal Programa Jovens Talentos 44 Para que um banco de dados seja excluído, é necessário que todos os usuários não estejam utilizando o mesmo (acessando dados contidos nas tabelas ou efetuando operações nas mesmas) e que ele esteja desconectado. È necessário também que o usuário que realizará esta operação seja um superusuário. A sintaxe está representada abaixo: DROP DATABASE <NOME DO BANCO DE DADOS> Existe ainda a possibilidade de alteração da definição atual do banco de dados, os comandos disponíveis são os seguintes: ALTER DATABASE NAME SET <PARÂMETRO> { TO | = } { VALUE | DEFAULT } ou ALTER DATABASE NAME RESET <PARÂMETRO> ou ALTER DATABASE NAME RENAME TO <NOVO NOME> ou ALTER DATABASE NAME OWNER TO <NOVO DONO> SCHEMA Para que um schema possa ser criado/alterado/excluído primeiramente a seção deverá estar apontando para o usuário que será o dono do schema. Para isto basta executar a instrução abaixo: SET SESSION AUTHORIZATION <NOME DO USUÁRIO> Para saber qual usuário está setado no momento basta utilizar a seguinte instrução SQL: SELECT SESSION_USER, CURRENT_USER Os schemas servem como depósitos de tabelas onde cada módulo é representado por um schema, sendo que para cada schema criado deverá existir um usuário que seja o dono do mesmo. Para que um schema possa ser criado basta executar o seguinte comando SQL: CREATE SCHEMA <NOME DO SCHEMA> OWNER TO <NOME DO USUÁRIO> Para que se possa excluir um schema é necessário que o usuário que está acessando o PostgreSQL seja um superusuário. O comando é o seguinte: DROP SCHEMA <NOME DO SCHEMA> Um schema também pode ser alterado utilizando-se um dos seguintes comandos: ALTER SCHEMA <NOME DO SCHEMA> RENAME TO <NOVO NOME DO SCHEMA> ALTER SCHEMA <NOME DO SCHEMA> OWNER TO <NOME DO USUÁRIO> O SCHEMA PUBLICO (PUBLIC) Sempre que uma tabela é criada sem que um nome de esquema seja definido, ou que a seção não esteja apontando para um usuário (SET SESSION...), por padrão, estas tabelas (e outros objetos) são colocadas automaticamente no esquema chamado “PUBLIC”. Todo banco de dados novo possui este esquema. Portanto, as duas formas abaixo são equivalentes: CREATE TABLE PRODUTOS ( ... ); e CREATE TABLE PUBLIC.PRODUTOS ( ... ); Este esquema serve justamente para que quando uma tabela (ou qualquer outro objeto) é criado no banco de dados sem a definição do schema, o PostgreSQL possa criar no schema PUBLIC sem que um erro seja retornado. ® IPM Informática Pública Municipal Programa Jovens Talentos 45 TABELA Uma tabela em um banco de dados relacional é muito semelhante a uma tabela no papel: ela é formada por linhas e colunas. O número e a ordem das colunas são fixos, e cada coluna possui um nome. O número de linhas é variável, refletindo a quantidade de dados armazenados em um determinado instante. O padrão SQL não dá nenhuma garantia sobre a ordem das linhas na tabela. Quando a tabela é lida, as linhas aparecem em uma ordem aleatória, a não ser que a classificação seja requisitada explicitamente. Além disso, o SQL por si só, não atribui identificadores únicos para as linhas e, portanto, é possível existirem váriaslinhas totalmente idênticas na tabela, caso uma chave primária não seja criada. Para que uma tabela possa ser criada primeiramente a seção deverá estar apontando para o usuário que será o dono da tabela. Para isto basta executar a instrução a seguir: SET SESSION AUTHORIZATION <NOME DO USUÁRIO> Para saber qual usuário está setado no momento basta utilizar a seguinte instrução SQL: SELECT SESSION_USER, CURRENT_USER Uma nova tabela pode ser criada especificando-se o seu nome juntamente com os nomes das colunas e seus tipos. CREATE TABLE TBCLIENTE ( CLICODIGO INTEGER NOT NULL, CLINOME VARCHAR(20) NOT NULL, CLIDATANASC DATE ); Existe a possibilidade de se excluir a tabela do banco de dados. Para isto a tabela não deve estar sendo acessada, a operação poderá ser realizada através do comando: DROP TABLE <NOME DA TABELA> Da mesma forma uma tabela pode ser alterada, bem como sua definição (Campos, índices, etc). Para isto basta a execução de um dos seguintes comandos SQL: ALTER TABLE <NOME DA TABELA> <AÇÃO> [, ... ] ALTER TABLE <NOME DA TABELA> RENAME <NOME DA COLUNA> TO <NOVO NOME DA COLUNA> ALTER TABLE <NOME DA TABELA> RENAME TO <NOVO NOME DA TABELA> Onde ação é um dos seguintes comandos: ADD <NOME DA COLUNA> TYPE [ DEFINIÇÃO DA COLUNA [ ... ] ] DROP <NOME DA COLUNA> [ RESTRICT | CASCADE ] ALTER <NOME DA COLUNA> TYPE TYPE [ USING EXPRESSÃO ] ALTER <NOME DA COLUNA> SET DEFAULT EXPRESSION ALTER <NOME DA COLUNA> DROP DEFAULT ALTER <NOME DA COLUNA> { SET | DROP } NOT NULL ALTER <NOME DA COLUNA> SET STATISTICS INTEGER ADD <DEFINIÇÃO> DROP CONSTRAINT <DEFINIÇÃO> [ RESTRICT | CASCADE ] OWNER TO <NOME DO NOVO USUÁRIO> SET TABLESPACE <NOME DA TABLESPACE> EXERCÍCIOS ® IPM Informática Pública Municipal Programa Jovens Talentos 46 1. Crie o usuário TREINAUSER (via código SQL) dando-lhe privilégios de superusuário; 2. Crie o banco de dados TREINANOVO (via código SQL), com o encoding LATIN1, baseando-se no template0; 3. Observe o DER a seguir e crie a estrutura de dados no database criado no exercício anterior. CHAVES PRIMÁRIAS (PK) Uma tabela poderá (ou deverá) ter uma chave primária apropriada para a mesma. É a chave primária que garantirá a atomicidade dos dados contidos na tabela, ela define quais são os campos que compõe um índice único. Tecnicamente a restrição de chave primária é simplesmente a combinação da restrição de unicidade com a restrição de não-nulo . Portanto, as duas definições de tabela abaixo aceitam os mesmos dados: CREATE TABLE TBCLIENTE ( CLICODIGO INTEGER PRIMARY KEY, CLINOME VARCHAR(20) NOT NULL, CLIDATANASC DATE ); ou CREATE TABLE TBCLIENTE ( CLICODIGO INTEGER UNIQUE NOT NULL, CLINOME VARCHAR(20) NOT NULL, CLIDATANASC DATE ); As chaves primárias também podem restringir mais de uma coluna; a sintaxe é semelhante à da restrição de unicidade: CREATE TABLE TBTELEFONE ( CLICODIGO INTEGER NOT NULL, TELNUMERO VARCHAR(20) NOT NULL, TELDESCRICAO CHAR(18) PRIMARY KEY (CLICODIGO, TELNUMERO) ); A chave primária indica que a coluna, ou grupo de colunas, pode ser utilizada como identificador único das linhas da tabela (Isto é uma consequência direta da definição da chave primária. Deve ser observado que a restrição de unicidade não fornece, por si só, um identificador único, porque não exclui os valores nulos). A chave primária é útil tanto para fins de documentação quanto para os aplicativos cliente. Por exemplo, um aplicativo contendo uma Interface de Usuário Gráfica (GUI), que permite modificar os valores das linhas, provavelmente necessita conhecer a chave primária da tabela para poder identificar as linhas de forma única. Uma tabela pode ter no máximo uma chave primária (embora possa ter muitas restrições de unicidade e de não-nulo). A teoria de banco de dados relacional dita que toda tabela deve ter uma chave primária. TBLogradouro LOGCodigo: INTEGER NULL LOGTipo: VARCHAR(10) NOT NULL LOGDescricao: VARCHAR(100) NULL TBPessoa PESCodigo: INTEGER NULL PESNome: VARCHAR(100) NOT NULL PESSexo: SMALLINT NOT NULL PESTipo: SMALLINT NOT NULL LOGCodigo: INTEGER NULL (FK) ® IPM Informática Pública Municipal Programa Jovens Talentos 47 CHAVE ESTRANGERIA (FK) A restrição de chave estrangeira especifica que o valor da coluna (ou grupo de colunas) deve corresponder a algum valor existente em uma linha de outra tabela. A chave estrangeira é responsável por manter a integridade referencial entre duas tabelas relacionadas. Reveja no diagrama abaixo o relacionamento entre as tabelas TBPESSOA e TBLOGRADOURO e Considere o seguinte problema: Desejamos ter certeza que não serão inseridas linhas na tabela TBPESSOA sem que haja um registro correspondente na tabela TBLOGRADOURO. Isto é chamado de manter a integridade referencial dos dados. Esta abordagem possui vários problemas, e é muito inconveniente, por isso o PostgreSQL pode realizar esta operação de forma automática. A declaração das tabelas ficaria assim: CREATE TABLE TBLOGRADOURO ( LOGCODIGO CODIGO DEFAULT NEXTVAL('CHAVELOGRADOURO') NULL, LOGTIPO VARCHAR(10) NOT NULL, LOGDESCRICAO NOME NULL, PRIMARY KEY (LOGCODIGO) ); CREATE TABLE TBPESSOA ( PESCODIGO CODIGO DEFAULT NEXTVAL('CHAPESSOA') NULL, PESNOME NOME NOT NULL, PESSEXO SMALLINT DEFAULT 1 NOT NULL CHECK (PESSEXO IN (1, 2, 3)), PESTIPO SMALLINT DEFAULT 1 NOT NULL CHECK (PESTIPO IN (1, 2, 3)), LOGCODIGO CODIGO NULL, PRIMARY KEY (PESCODIGO), FOREIGN KEY (LOGCODIGO) REFERENCES TBLOGRADOURO ON UPDATE CASCADE ON DELETE NO ACTION ); a declaração da tabela TBPessoa poderia também ser assim: CREATE TABLE TBPESSOA ( PESCODIGO CODIGO DEFAULT NEXTVAL('CHAPESSOA') NULL, PESNOME NOME NOT NULL, PESSEXO SMALLINT DEFAULT 1 NOT NULL CHECK (PESSEXO IN (1, 2, 3)), PESTIPO SMALLINT DEFAULT 1 NOT NULL CHECK (PESTIPO IN (1, 2, 3)), LOGCODIGO CODIGO NULL REFERENCES TBLOGRADOURO (LOGCODIGO), PRIMARY KEY (PESCODIGO), ); Agora, ao se tentar inserir uma linha inválida: INSERT INTO TBPESSOA VALUES (1, 'PESSOA', 1, 1, 17); ERROR: INSERT OR UPDATE ON TABLE "TBPESSOA" VIOLATES FOREIGN KEY CONSTRAINT "LOGRADOURO_PESSOA_FKEY" DETAIL: KEY (TBPESSOA)=(17) IS NOT PRESENT IN TABLE "TBLOGRADOURO". -- Tradução da mensagem: ® IPM Informática Pública Municipal Programa Jovens Talentos 48 ERRO: INSERÇÃO OU ATUALIZAÇÃO NA TABELA "TBPESSOA" VIOLA A RESTRIÇÃO DE CHAVE ESTRANGEIRA "LOGRADOURO_PESSOA_FKEY" DETALHE: CHAVE (TBPESSOA)=(17) NÃO ESTÁ PRESENTE NA TABELA "TBLOGRADOURO". O comportamento das chaves estrangeiras pode receber ajuste fino no aplicativo. Não iremos além deste exemplo simples nesta apostila, para mais informações consulte o material oficial do PostgreSQL. ÍNDICES Para que um índice possa ser criado/alterado/excluído primeiramente a seção deverá apontar para o usuário que é o dono da tabela na qual o(s) índice(s) pertence(m). Para isto basta executar a instrução abaixo: SET SESSION AUTHORIZATION <NOME DO USUÁRIO> Para saber qual usuário está setado no momento basta utilizar a seguinte instrução SQL: SELECT SESSION_USER, CURRENT_USER Cada tabela do banco de dados poderá ser constituída de um ou mais índices, e estes devem ser criados de acordo com a modelagem realizada pelo analista de software. Geralmente índices são adicionados para que determinadas consultas que são muito utilizadas sejam agilizadas. Para que índices possam ser criados basta utilizar o seguinte comando: CREATE [ UNIQUE ] INDEX NOME_DO_ÍNDICE ON TABELA [ USING MÉTODO_DE_ACESSO ] ( COLUNA [ NOME_DO_OPERADOR ] [, ...] )[ WHERE PREDICADO ] Exemplo: CREATE UNIQUE INDEX IDXCAMPO ON SCHEMA.TABELA (CODIGO); ou CREATE INDEX IDXCAMPO ON SCHEMA.TABELA (CODIGO, NOME) WHERE NOME IS NOT NULL; Entradas: UNIQUE: Faz com que o sistema procure por valores duplicados na tabela quando o índice é criado, se existirem dados na tabela, e sempre que novos dados forem adicionados. A tentativa de inserir ou de atualizar dados, que produza um valor duplicado, gera um erro. nome_do_índice: O nome do índice a ser criado. Tabela: O nome da tabela a ser indexada. método_de_acesso: O nome do método de acesso a ser utilizado pelo o índice. O método de acesso padrão IPM (e do próprio Postgre) é o BTREE. O PostgreSQL implementa quatro métodos de acesso para os índices: BTREE: uma implementação das "B-trees" de alta concorrência de Lehman-Yao. É o método de acesso padrão para índices utilizados pela IPM. RTREE: implementa "R-trees" padrão, utilizando o algoritmo de partição quadrática de Guttman. HASH: uma implementação das dispersões lineares de Litwin. GIST: Generalized Index Search Trees (Árvores de Procura de Índice Generalizadas). Coluna: O nome de uma coluna da tabela. nome_do_operador: Uma classe de operador associada. Veja abaixo para obter mais detalhes. nome_da_função: Uma função que retorna um valor que pode ser indexado. Predicado: Define a expressão da restrição (constraint) para o índice parcial. Um índice pode ser removido da tabela se a mesma não estiver sendo acessada e se o usuário que está acessando o banco no momento for o dono da tabela. O comando é o seguinte: ® IPM Informática Pública Municipal Programa Jovens Talentos 49 DROP INDEX <NOME DO ÍNDICE> [CASCADE | RESTRICT] Onde: Cascade: Exclui todos os objetos que estão vinculados ao índice Restrict: Irá abortar a exclusão dos objetos que estão vinculados aos índices; A Definição de um índice poderá ser alterada também de acordo com a necessidade: ALTER INDEX <NOME DO ÍNDICE> AÇÃO [, ... ] ALTER INDEX <NOME DO ÍNDICE> RENAME TO <NOVO NOME DO ÍNDICE> Onde ação é uma das seguintes: OWNER TO <NOVO DONO> SET TABLESPACE <TABLE SPACE DE ÍNDICES> EXERCÍCIOS 1. Defina as chaves primárias para as tabelas criadas anteriormente; 2. Defina os relacionamentos entre as tabelas do modelo criando as chaves estrangerias. Defina todas as chaves estrangeiras como CASCADE ao apagar registros; 3. Crie um índice na tabela TBPESSOA para o campo PESNOME, não único; VIEWS Fazer livre uso de visões é um aspecto chave de um bom projeto de banco de dados SQL. As visões permitem encapsular, atrás de interfaces que não mudam, os detalhes da estrutura das tabelas, que podem mudar na medida em que os aplicativos evoluem. As visões podem ser utilizadas em praticamente todos os lugares onde uma tabela real pode ser utilizada. Construir visões baseadas em visões não é raro. Para que uma view possa ser criada/alterada/excluída primeiramente a seção deverá apontar para o usuário que será o dono da view. Para isto basta executar a instrução abaixo: SET SESSION AUTHORIZATION <NOME DO USUÁRIO> Para saber qual usuário está setado no momento basta utilizar a seguinte instrução SQL: SELECT SESSION_USER, CURRENT_USER A criação de views serve para padronizar o acesso a determinadas consultas de forma a melhorar o desempenho ao acesso as mesmas e dar suporte a sistemas de terceiros para que esses acessem dados da base de dados do sistema ATENDE.NET. O Comando para criação da view é o seguinte: CREATE VIEW <NOME DA VISÃO> [ ( NOME DAS COLUNAS ) ] AS <SELECT> A view poderá ser excluída a qualquer momento, sem que os dados sejam afetados, para isto basta executar o comando: DROP VIEW <NOME DA VISÃO> A Select de view pode ser alterada sempre que for necessário. Os Campos que compõe a view somente podem ser alterados para trocar posição, não para adicionar ou excluir campos, o comando é o seguinte: CREATE OR REPLACE VIEW <NOME DA VISÃO> [ ( NOME DAS COLUNAS ) ] AS <SELECT> Exemplo de View: ® IPM Informática Pública Municipal Programa Jovens Talentos 50 CREATE OR REPLACE VIEW DADOS_PESSOA AS SELECT PESCODIGO AS "CÓDIGO PESSOA", PESNOME AS "NOME PESSOA", PESSEXO AS "SEXO", CASE WHEN PESSEXO = 1 THEN 'MASCULINO' WHEN PESSEXO = 2 THEN 'FEMININO' WHEN PESSEXO = 3 THEN 'NÃO INFORMADO' END AS "DESCR. SEXO", PESTIPO AS "TIPO", CASE WHEN PESTIPO = 1 THEN 'FÍSICA' WHEN PESTIPO = 2 THEN 'JURÍDICA' WHEN PESTIPO = 3 THEN 'OUTROS' END AS "DESCR. TIPO", CASE WHEN COALESCE(TBLOGRADOURO.LOGTIPO,'') <> '' THEN TBLOGRADOURO.LOGTIPO||' '||TBLOGRADOURO.LOGDESCRICAO ELSE TBLOGRADOURO.LOGDESCRICAO END AS "LOGRADOURO" FROM TBPESSOA LEFT JOIN TREINA.TBLOGRADOURO ON TBLOGRADOURO.LOGCODIGO = TBPESSOA.LOGCODIGO; O dono da view poderá ser alterado a partir da seguinte instrução: ALTER TABLE DADOS_PESSOA OWNER TO TREINA; É muito importante que para objetos como VIEW sejam informados comentários, conforme exemplo: COMMENT ON VIEW TREINA.DADOS_PESSOA IS 'RETORNA OS DADOS DE PESSOAS'; Obs: View não pode ser utilizada para alteração dos registros que ela retorna, ou seja, ela é somente leitura. Um cuidado especial deve ser tomado para que os nomes e os tipos das colunas da visão sejam atribuídos da maneira desejada. Por exemplo: CREATE VIEW VISTA AS SELECT 'HELLO WORLD'; Este comando é ruim por dois motivos: o nome padrão da coluna é ?column?, e o tipo de dado padrão da coluna é unknown. Se for desejado um literal cadeia de caracteres no resultado da visão deve ser utilizado algo como: CREATE VIEW VISTA AS SELECT TEXT 'HELLO WORLD' AS HELLO; FUNÇÕES E GATILHOS A linguagem PL/pgSQL pode ser utilizada para definir procedimentos de gatilho. O procedimento de gatilho é criado pelo comando CREATE FUNCTION, declarando o procedimento como uma função sem argumentos e que retorna o tipo trigger. Deve ser observado que a função deve ser declarada sem argumentos, mesmo que espere receber os argumentos especificados no comando CREATE TRIGGER — os argumentos do gatilho são passados através de TG_ARGV, conforme descrito abaixo. Quando uma função escrita em PL/pgSQL é chamada como um gatilho, diversas variáveis especiais são criadas automaticamente no bloco de nível mais alto. São estas: NEW: Tipo de dado RECORD; variável contendo a nova linha do banco de dados, para as operações de INSERT/UPDATE nos gatilhos no nível de linha. O valor desta variável é NULL nos gatilhos no nível de instrução. ® IPM Informática Pública Municipal Programa Jovens Talentos 51 OLD: Tipo de dado RECORD; variável contendo a antiga linha do banco de dados, para as operações de UPDATE/DELETE nos gatilhos no nível de linha. O valor desta variável é NULL nos gatilhos no nível de instrução. TG_NAME: Tipo de dado name; variável contendo o nome do gatilho disparado. TG_WHEN: Tipo de dado text; uma cadeia de caracteres contendo BEFORE ou AFTER, dependendo da definição do gatilho. TG_LEVEL: Tipo de dado text; uma cadeia de caracteres contendo ROW ou STATEMENT, dependendo da definição do gatilho. TG_OP: Tipo de dado text; uma cadeia de caracteres contendo INSERT, UPDATE, ou DELETE, informando para qual operação o gatilho foi disparado. TG_RELID: Tipo de dado oid; o ID de objeto da tabela que causou o disparo do gatilho. TG_RELNAME: Tipo de dado name; o nome da tabela que causou o disparo do gatilho. TG_NARGS: Tipo de dado integer; o número de argumentos fornecidos ao procedimento de gatilho na instrução CREATE TRIGGER. TG_ARGV[]: Tipo de dado matriz de text; os argumentos da instrução CREATE TRIGGER. O contador do índice começa por 0. Índices inválidos (menor que 0 ou maiorou igual a tg_nargs) resultam em um valor nulo. Uma função de gatilho deve retornar nulo, ou um valor registro/linha possuindo a mesma estrutura da tabela para a qual o gatilho foi disparado. Os gatilhos no nível de linhas disparadas BEFORE (antes) podem retornar nulo, para sinalizar ao gerenciador do gatilho para pular o restante da operação para esta linha (ou seja, os gatilhos posteriores não serão disparados, e não ocorrerá o INSERT/UPDATE/DELETE para esta linha. Se for retornado um valor diferente de nulo, então a operação prossegue com este valor de linha. Retornar um valor de linha diferente do valor original de NEW altera a linha que será inserida ou atualizada (mas não tem efeito direto no caso do DELETE). Para alterar a linha a ser armazenada, é possível substituir valores individuais diretamente em NEW e retornar o NEW modificado, ou construir um novo registro/linha completo a ser retornado. O valor retornado por um gatilho BEFORE ou AFTER no nível de instrução, ou por um gatilho AFTER no nível de linha, é sempre ignorado; pode muito bem ser nulo. Entretanto, qualquer um destes tipos de gatilho pode interromper toda a operação gerando um erro. Exemplo: CREATE OR REPLACE FUNCTION SET_VALOR_TAXA() RETURNS "TRIGGER" AS $BODY$ DECLARE FVALORFIM FLOAT; BEGIN FVALORFIM = (SELECT (TBIMOVEL.IMVLARGURA * TBIMOVEL.IMVCOMPRIMENTO) * 0.15 FROM TBIMOVEL WHERE TBIMOVEL.IMVCODIGO = NEW.IMVCODIGO); IF FVALORFIM > 0 THEN INSERT INTO TBTAXA (PESCODIGO, IMVCODIGO, TAXDATA, TAXVALOR) VALUES (NEW.PESCODIGO, NEW.IMVCODIGO, CURRENT_DATE, FVALORFIM); END IF; RETURN NEW; END; $BODY$ LANGUAGE 'PLPGSQL' VOLATILE; Comando para alterar o dono da função criada: ® IPM Informática Pública Municipal Programa Jovens Talentos 52 ALTER FUNCTION SET_VALOR_TAXA() OWNER TO TREINA; POSTGRESQL – ADMINISTRAÇÃO BÁSICA SERVER STATUS O pgAdmin fornece ferramenta para acompanhar o status atual do servidor de banco de dados, com esta ferramenta é possível monitorar em tempo real como está o servidor. Esta opção está disponível no menu Tools > Server Status, a tela abaixo será mostrada. Esta tela possui as seguintes ferramentas e características: 1. Opções para cancelar a instrução atual (primeiro botão) e finalizar a conexão do cliente (segundo botão); 2. Grid que exibe as conexões atuais no servidor, a primeira coluna é PID que é trata-se do número do processo criado no servidor para aquela conexão. A tela abaixo é uma parte do console do Linux mostrando os processos do postgres ativos, na primeira coluna (marcada) pode-se observar o número do PID exatamente como é exibido na tela do status do servidor; 3. Processo do servidor indicando um processo lento (quando uma query excedeu a 10 segundos de execução). As cores de exibição no status server podem ser alteradas na opção File > Options > Colours. A tela abaixo exibe as cores padrão; ® IPM Informática Pública Municipal Programa Jovens Talentos 53 4. Na coluna QUERY, quando estiver configurado nos parâmetros do servidor no arquivo de configuração postgresql.conf para fazer log de query, são exibidas as instruções que estão sendo executadas naquele instante pela conexão; 5. Identificação da aplicação cliente que está conectada no servidor, esta informação é opcionalmente passada pelo cliente para o servidor identificando seu nome. No caso do sistema Atende.NET Web as informações são as seguintes: a. Nome do software [Atende.Net]; b. Nome do usuário logado naquela seção; c. Código do usuário que está naquela seção; d. Código da rotina que está sendo acessada no momento; e. Código da ação que está sendo acessada no momento; f. Número do IP de conexão. É exibido o IP do localhost (127.0.0.1) quando o servidor apache estiver rodando na própria máquina do usuário. No caso do apache estar sendo executado em outro servidor de aplicação, então o IP que será exibido é o da estação de trabalho; 6. Processos em espera. São conexões ativas no servidor, porém não executando nenhuma instrução SQL. Podem ser, por exemplo, transações aguardando por processo; 7. Processos ativos. São conexões ativas no servidor que estão executando instruções naquele instante; 8. Esta coloração é exibida quando a linha está selecionada mas o foco não está na consulta. 9. Lista contendo os bloqueios que estão dependendo de alguma transação ativa. 10. Lista de transações preparadas, aguardando para serem confirmadas. Caso alguma transação fique ativa nesta guia, indica que uma transação ficou pendente e poderá ser cancelada. EXPLICANDO UMA CONSULTA - MODO GRÁFICO Observe a explicação de consulta abaixo: A explicação acima, foi obtida com a execução do seguinte comando SQL: SELECT * FROM SPUNICO.UNICO LEFT JOIN SPUNICO.LOGRADOU ON LOGRADOU.CODIGO = UNICO.LOGRADOURO WHERE UNICO.CODIGO BETWEEN 19 AND 200 Na explicação são exibidos os seguintes pontos: 1. Indica que a consulta foi executada segundo a chave primária da tabela unico (pk_unico), o que agiliza a execução da consulta. Verifique mais detalhes em Clausula From/Join; ® IPM Informática Pública Municipal Programa Jovens Talentos 54 2. Após o filtro executado na tabela unico o banco de dados executou um sort (ordenação) da consulta; 3. Para cada linha lida da tabela unico, fora executada uma consulta em logradou para retornar o logradouro do único, conforme mostrado no código sql a ligação foi realizada utilizando-se a chave primária da tabela, isto faz com que na execução do código o banco de dados utilize esta chave (o índice dela) o que faz com que a consulta fique mais rápida. 4. Por fim, o banco de dados fez uma junção dos resultados em um mesmo result set; COLUNAS DO SISTEMA Toda tabela possui diversas colunas do sistema, as quais são implicitamente definidas pelo sistema. Portanto, estes nomes não podem ser utilizados como nomes de colunas definidas pelo usuário (observe que esta restrição é diferente do nome ser uma palavra chave ou não; colocar o nome entre aspas não faz esta restrição deixar de ser aplicada). Não há necessidade de se preocupar com estas colunas, basta apenas saber que elas existem. Podemos fazer uso destas colunas retornando-as sempre que necessário. oid O identificador de objeto (object ID) de uma linha. É um número serial adicionado pelo PostgreSQL, automaticamente, a todas as linhas da tabela (a não ser que a tabela seja criada com WITHOUT OIDS e, neste caso, esta coluna não estará presente). O tipo desta coluna é oid (o mesmo nome da coluna). Nas versões mais recentes do PostgreSQL a tabela é criada por padrão com WITHOUT OIDS. tableoid O OID da tabela que contém esta linha. Este atributo é particularmente útil nas consultas fazendo seleção em hierarquias de herança, porque sem este atributo é difícil saber de que tabela se origina cada linha. Pode ser feita uma junção entre tableoid e a coluna oid de pg_class para obter o nome da tabela. xmin O identificador da transação de inserção (transaction ID) para esta versão da linha (Uma versão da linha é um estado individual da linha; cada atualização da linha cria uma nova versão de linha para a mesma linha lógica). cmin O identificador do comando, começando por zero, dentro da transação de inserção. xmax O identificador da transação de exclusão (transaction ID), ou zero para uma versão de linha não excluída. É possível que esta coluna seja diferente de zero em uma versão de linha visível: normalmente isto indica que a transação fazendo a exclusão ainda não foi efetivada (commit), ou que uma tentativa de exclusão foi desfeita (rollback). cmax O identificador do comando dentro da transação de exclusão, ou zero. ctid A posição física da versão da linha dentro da tabela. Deve ser observado que, embora seja possível usar ctid para localizar a versão da linha muito rapidamente, octid da linha muda cada vez que a linha é atualizada ou movida pelo comando VACUUM FULL. Portanto, o ctid não serve como identificador de linha duradouro. O OID ou, melhor ainda, um número serial definido pelo usuário deve ser utilizado para identificar logicamente a linha. Ex: SELECT OID, TABLEOID, XMIN, XMAX, CMAX, CTID, PESCODIGO, PESNOME FROM TBPESSOA WHERE PESCODIGO = 1 Resultado: ® IPM Informática Pública Municipal Programa Jovens Talentos 55 OID TABLEOID XMIN XMAX CMAX CTID PESCODIGO PESNOME 18117787 18061007 95733848 0 0 (1106,13) 1 Cliente 1 Selecionando o registro pelo seu OID: SELECT PESCODIGO, PESNOME FROM TBPESSOA WHERE OID = 18117787 Resultado: PESCODIGO PESNOME 1 Cliente 1 OBS: As colunas informadas aqui são exclusivamente de uso do PostgreSQL. O ORACLE também possui colunas do sistema, para saber quais são e como utilizá-las consulte o guia do ORACLE. CONTROLE DE TRANSAÇÕES Transação é um conceito fundamental de todo sistema de banco de dados. O ponto essencial da transação é englobar vários passos em uma única operação de tudo ou nada. Os estados intermediários entre os passos não são vistos pelas demais transações simultâneas e, se ocorrer alguma falha que impeça a transação chegar até o fim, então nenhum dos passos intermediários irá afetar o banco de dados de forma alguma. Por padrão, o PostgreSQL executa as transações em modo não encadeado (também conhecido por "autocommit" [auto-efetivação] em outros sistemas de banco de dados). Em outras palavras, cada comando é executado em sua própria transação e uma efetivação é implicitamente realizada ao final do comando (se a execução terminar com sucesso, senão um "rollback" é realizado). O comando BEGIN inicia uma transação no modo encadeado, ou seja, todas as declarações após o comando BEGIN são executadas como sendo uma única transação, até que seja encontrado um comando explícito commit ou rollback, ou a execução ser abortada. Os comandos são executados mais rápido no modo encadeado, porque cada início/efetivação de transação requer uma atividade significativa de CPU e de disco. A execução de vários comandos em uma única transação também é requerida por motivo de consistência, quando várias tabelas relacionadas são modificadas. No PostgreSQL o comando que inicia um bloco de transação é o BEGIN WORK. Exemplo: BEGIN WORK; UPDATE TBPESSOA SET LOGCODIGO = 10 WHERE PESCODIGO = 1; UPDATE TBPESSOACONTATO SET CTPRAMAL = 1506 WHERE PESCODIGO = 1 AND CTPNUMERO = '3531-1506'; INSERT INTO TBPESSOACONTATO (PESCODIGO, CTPNUMERO, CTPDESCRICAO, CTPRAMAL) VALUES (1, '3531-1500', 'COMERCIAL', 0); O nível de isolamento padrão da transação no PostgreSQL é READ COMMITTED, onde os comandos dentro de uma transação enxergam apenas as mudanças efetivadas antes da execução do comando. Se a transação for efetivada, o PostgreSQL garante que todas as atualizações são realizadas ou, então, que nenhuma delas é realizada. As transações possuem a propriedade ACID (atomicidade, consistência, isolamento e durabilidade) padrão. ® IPM Informática Pública Municipal Programa Jovens Talentos 56 É necessário garantir que, caso aconteça algo errado no meio da operação, nenhum dos passos executados até o ponto produza efeito. Agrupar as atualizações em uma transação dá esta garantia. Uma transação é dita como sendo atômica (característica de atomicidade) do ponto de vista das outras transações, ou a transação acontece completamente ou nada acontece. O controle de transação evita alguns tipos de inconsistências, permitindo a execução de um conjunto de comandos de forma única, possibilitando uma confirmação ou cancelamento de todo o bloco de comando. Também é possível controlar o acesso e a visibilidade dos dados entre as sessões. Para que isso seja possível contamos com os comandos COMMIT, ROLLBACK e SAVEPOINT. Exemplo: No bloco de transação iniciado acima, precisamos concluí-lo. Caso a conexão com o banco de dados seja perdida antes disso o SGBD automaticamente gera um ROLLBACK de todo o bloco. COMMIT; (para concluir o bloco de transação efetivando a gravação de todas as informações) ROLLBACK; (para concluir o bloco de transação cancelando a gravação de todas as informações) O PostgreSQL utiliza o modelo MVCC (Multiversion Concurrency Control), para gerenciar transações em ambiente multi-usuário, mantendo uma imagem dos dados no estado inicial da transação. BACKUP O Processo de backup pode ser realizado também pelo pgAdmin, em nível de objeto (tabela), schema ou database (o banco de dados inteiro). Para executar o backup basta clicar com o botão direito do mouse sobre o objeto desejado, e escolher a opção "Cópia de Segurança", a seguinte tela será exibida: 1. Informe neste campo o nome do arquivo, com caminho completo. A Extensão será colocada automáticamente (.backup) caso nenhuma seja especificada; 2. Indique qual o formato do backup a ser realizado. COMPRESS, indica um formato compactado, o que diminui bastante o tamanho do backup, esta compactação é feita no próprio servidor de banco de dados. TAR, também ® IPM Informática Pública Municipal Programa Jovens Talentos 57 compactará o backup, porém utilizando o formato TAR. PLAIN serve para realizar backup em nível de texto, com os comandos SQL para recriação do objeto no destino; 3. Pode-se selecionar na lista a codificação de saída necessária para o backup. Isto somente deve ser alterado caso deseja-se explicitamente que o backup seja feito em outro encoding diferente do definido no database. RESTORE O processo de restore pode ser realizado a partir de um arquivo de backup realizado utilizando a ferramenta pgAdmin ou um arquivo de backup gerado diretamente pelo comando pg_dump. Na primeira tela você deve informar o nome do arquivo para restaurar o backup, deve ser informado o caminho completo, com nome e extensão; 1. Informe nestas opções o que deve ser restaurado, somente dados, somente esquema, caso uma das opções seja marcada, deverá clicar na aba abaixo chamada "Objects" e em seguida clicar em Visualizar, para que o conteúdo do arquivo seja mostrado, após isto deve-se selecionar o objeto (ou informação) a ser restaurado e clicar em OK; 2. Opções de privilégio, se Nenhum dono é selecionado então não restaura owner, a opção desabilitar gatilho serve para que no momento do restore do banco ao inserir registros nas tabelas as triggers (gatilhos) não sejam ativadas. Da mesma forma para privilégios e tablespace; 3. Caso seja necessário criar o database antes de iniciar o restore marque esta opção; 4. Marque esta opção caso seja necessário realizar uma limpeza dos dados antes de iniciar a restauração; 5. Caso seja necessário pode-se optar por uma única transação para todo o procedimento marcando esta opção;