Vous êtes sur la page 1sur 176

Versão 4 .

Manual Básico
exibir: condição;

direito autoral
Este documento é protegido por Copyright © 2013 por seus colaboradores, conforme listado abaixo. Você
pode distribuí-lo e / ou modificá-lo sob os termos da Licença Pública Geral GNU (
http://www.gnu.org/licenses/gpl.html ), versão 3 ou posterior, ou da Licença de Atribuição Creative
Commons ( http : //creativecommons.org/licenses/by/3.0/ ), versão 3.0 ou posterior.
Todas as marcas registradas deste guia pertencem a seus legítimos proprietários.

Colaboradores
Jochen Schiffers Robert Großkopf Jost Lange
Avelã Russman Martin Fox Andrew Pitonyak
Dan Lewis Jean Hollis Weber

Agradecimentos
Este livro é baseado em um documento alemão original, que foi traduzido por Hazel Russman e Martin Fox.

Comentários
Por favor, envie quaisquer comentários ou sugestões sobre este documento para:
documentation@global.libreoffice.org

Data de publicação e versão do software


Publicado em 3 de julho de 2013 . Baseado no LibreOffice 4.0.

Conteúdo
direito autoral
Colaboradores
Comentários
Agradecimentos
Data de publicação e versão do software
Prefácio
Para quem é este livro?
O que há neste livro?
Onde obter mais ajuda
Sistema de ajuda
Suporte on-line gratuito
Suporte pago e treinamento
O que você vê pode ser diferente
Ilustrações
Ícones
Usando o LibreOffice em um Mac
Quais são todas essas coisas chamadas?
Quem escreveu este livro?
Perguntas frequentes
Capítulo 1 Introdução à Base
Introdução
Base - um contêiner para o conteúdo do banco de dados
Entrada de dados usando formulários
Entrada de dados diretamente em uma tabela
Consultas - obtendo informações sobre dados em tabelas
Relatórios - apresentação de dados
Capítulo 2 Criando um banco de dados
Notas gerais sobre a criação de uma base de dados
Novo banco de dados usando o mecanismo interno do HSQL
Acessando bancos de dados externos
Bancos de dados MySQL
bancos de dados dBase
Planilhas
Livro de endereços do Thunderbird
Capítulo 3 Tabelas
Informações gerais sobre tabelas
Relacionamentos entre tabelas
Relacionamentos para tabelas em bancos de dados
Tabelas e relacionamentos para o banco de dados de exemplo
Criando Tabelas
Criação usando a interface gráfica do usuário
Entrada direta de comandos SQL
Ligando Tabelas
Inserindo dados em tabelas
Entrada usando a GUI Base
Entrada direta usando SQL
Problemas com esses métodos de entrada de dados
Capítulo 4 Formulários
Formulários facilitam a entrada de dados
Criando formulários
Uma forma simples
Barras de ferramentas para design de formulário
Propriedades do formulário
Propriedades dos controles
Um formulário simples concluído
Principais formas e subformulários
Uma visão - muitas formas
Capítulo 5 Consultas
Informações gerais sobre consultas
Inserindo consultas
Criando consultas usando o diálogo Design da Consulta
Aprimoramento de consulta usando o modo SQL
Usando um alias em uma consulta
Consultas para a criação de campos da caixa de listagem
Consultas como base para informações adicionais em formulários
Possibilidades de entrada de dados em consultas
Uso de parâmetros em consultas
Subqueries
Subconsultas Correlacionadas
Consultas como tabelas de origem para consultas
Resumindo dados com consultas
Acesso mais rápido a consultas usando visualizações de tabela
Capítulo 6 Relatórios
Criando relatórios usando o Report Builder
A interface do usuário do Report Builder
Propriedades gerais dos campos
Propriedades de dados dos campos
Funções no Report Builder
Inserir fórmulas
Funções definidas pelo usuário
Entrada de fórmula para um campo
Impressão condicional
Formatação condicional
Capítulo 7 Vinculando aos Bancos de Dados
Notas gerais sobre ligação de banco de dados
Registro de bancos de dados
Navegador da fonte de dados
Dados para texto
Dados para campos
Mala direta
Fonte de dados do documento atual
Explorer on / off
Criando documentos de mala direta
Impressão de etiquetas
Criação direta de mala direta e documentos de etiqueta
Mala direta usando o mouse
Criando cartas formulário selecionando campos
Formulários externos
Uso do banco de dados no Calc
Inserindo dados no Calc
Exportando dados do Calc para um banco de dados
Convertendo dados de um banco de dados para outro
Capítulo 8 Tarefas do banco de dados
Comentários gerais sobre tarefas de banco de dados
Filtragem de dados
Procurando por dados
Partes de codigo
Obtendo a idade atual de alguém
Obtendo um saldo em execução por categorias
Numeração de linhas
Obtendo uma quebra de linha através de uma consulta
Agrupando e resumindo
Capítulo 9 Macros
Comentários gerais sobre macros
Melhorando a usabilidade
Atualização automática de formulários
Registros de Filtragem
Pesquisando registros de dados
Comboboxes como listboxes com uma opção de entrada
Navegação de um formulário para outro
Removendo elementos de distração de formulários
Tarefas de banco de dados expandidas usando macros
Fazendo uma conexão com um banco de dados
Protegendo seu banco de dados
Compactação de banco de dados
Diminuindo o índice da tabela para campos de autovalor
Diálogos
Capítulo 10 Manutenção do banco de dados
Comentários gerais sobre manutenção de bancos de dados
Compactando um banco de dados
Repor autovalores
Consultando as propriedades do banco de dados
Tabelas de teste para entradas desnecessárias
Testando entradas usando a definição de relacionamento
Edição de entradas usando formulários e subformulários
Consultas para encontrar entradas órfãs
Velocidade de pesquisa de banco de dados
Efeito de consultas
Efeito de listboxes e comboboxes
Apêndice
Códigos de barra
Tipos de dados para o editor de tabelas
Inteiros
Números de ponto flutuante
Texto
Tempo
De outros
Funções integradas e procedimentos armazenados
Numérico
Texto
Data hora
Conexão de banco de dados
Sistema
Tabelas de informação para HSQLDB
Reparo de banco de dados para arquivos * .odb
Conectando um banco de dados a um HSQLDB externo
Alterando a conexão do banco de dados para o HSQLDB externo
Alterando a conexão do banco de dados para acesso multiusuário
Valores de incremento automático com HSQLDB externo
Prefácio

Para quem é este livro?


Qualquer pessoa que queira se familiarizar rapidamente com o LibreOffice Base achará esse livro valioso.
Você pode querer ler primeiro o Capítulo 8, Introdução à Base, no Guia de Introdução .

O que há neste livro?


Este livro apresenta o Base, o componente de banco de dados do LibreOffice. Base usa o mecanismo de
banco de dados HSQLDB para criar documentos de banco de dados. Ele pode acessar bancos de dados
criados por muitos programas de bancos de dados, incluindo o Microsoft Access, MySQL, Oracle e
PostgreSQL. Base inclui funcionalidade adicional que permite criar aplicativos completos orientados a
dados.
Este livro apresenta os recursos e funções do Base, usando dois bancos de dados de exemplo.
•.Criando um banco de dados
•.Acessando bancos de dados externos
•.Criando e usando tabelas em bancos de dados relacionais
•.Criando e usando formulários para entrada de dados
•.Usando consultas para reunir dados de diferentes tabelas, calcular resultados quando necessário e filtrar
rapidamente um registro específico de uma massa de dados
•.Criando relatórios usando o Report Builder
•.Vinculando bancos de dados a outros documentos e formulários externos, incluindo o uso na mala direta
•.Filtrando e pesquisando dados
•.Usando macros para evitar erros de entrada, simplificar tarefas e melhorar a usabilidade de formulários
•.Manutenção de bancos de dados

Onde obter mais ajuda


Este livro, os outros guias do usuário do LibreOffice , o sistema de Ajuda integrado e os sistemas de
suporte ao usuário presumem que você esteja familiarizado com seu computador e funções básicas, como
iniciar um programa, abrir e salvar arquivos.

Sistema de ajuda
O LibreOffice vem com um extenso sistema de ajuda. Esta é sua primeira linha de suporte ao uso do
LibreOffice . Para exibir o sistema de Ajuda completo, pressione F1 ou selecione Ajuda do LibreOffice no
menu Ajuda. Além disso, você pode escolher se quer ativar Tips, estendida T ips, eo Agente de Ajuda
(utilizando Ferramentas > Opções > LibreOffice > Geral ).
Se as Dicas estiverem ativadas, coloque o ponteiro do mouse sobre qualquer um dos ícones para ver uma
pequena caixa (“tooltip”) com uma breve explicação da função do ícone. Para uma explicação mais
detalhada, selecione Ajuda > O que é isto? e segure o ponteiro sobre o ícone.

Suporte on-line gratuito


A comunidade do LibreOffice não apenas desenvolve software, mas também fornece suporte gratuito
baseado em voluntários. Veja a Tabela 1 e esta página da web: http://www.libreoffice.org/get-help/
Você pode obter suporte on-line abrangente da comunidade por meio de listas de e- mail e do site do Ask
LibreOffice . Outros sites executados por usuários também oferecem dicas e tutoriais gratuitos. Este fórum
fornece suporte da comunidade para o LibreOffice: http://en.libreofficeforum.org/
Este site fornece suporte para o LibreOffice, entre outros programas:
http://forum.openoffice.org/en/forum/
Tabela 1: Suporte gratuito para usuários do LibreOffice
Suporte gratuito ao LibreOffice
Pergunte ao Perguntas e respostas da comunidade do LibreOffice
LibreOffice http://ask.libreoffice.org/en/questions/
Guias do usuário, instruções e outras documentações.
Documentação http://www.libreoffice.org/get-help/documentation/
https://wiki.documentfoundation.org/Documentation/Publications
Respostas às perguntas mais frequentes
FAQs
http://wiki.documentfoundation.org/Faq
O suporte gratuito à comunidade é fornecido por uma rede de usuários
Listas de discussão experientes
http://www.libreoffice.org/get-help/mailing-lists/
O site do LibreOffice no seu idioma.
http://www.libreoffice.org/international-sites/
Apoio internacional
Listas de discussão internacionais
http://wiki.documentfoundation.org/Local_Mailing_Lists
Opções de Informações sobre as opções de acessibilidade disponíveis.
acessibilidade http://www.libreoffice.org/get-help/accessibility/

Suporte pago e treinamento


Como alternativa, você pode pagar pelos serviços de suporte . Contratos de serviço podem ser adquiridos
de um fornecedor ou empresa de consultoria especializada em LibreOffice .

O que você vê pode ser diferente

Ilustrações
O LibreOffice é executado nos sistemas operacionais Windows, Linux e Mac OS X, cada um dos quais
possui várias versões e pode ser personalizado pelos usuários (fontes, cores, temas, gerenciadores de
janela). As ilustrações neste guia foram tiradas de uma variedade de computadores e sistemas
operacionais. Portanto, algumas ilustrações não se parecerão exatamente com o que você vê na tela do
seu computador.
Além disso, algumas das caixas de diálogo podem ser diferentes devido às configurações selecionadas no
LibreOffice. Você pode usar diálogos do sistema do seu computador (padrão) ou diálogos fornecidos pelo
LibreOffice. Para mudar para o uso das caixas de diálogo do LibreOffice:
1)Nos sistemas operacionais Linux e Windows, vá para Ferramentas> Opções> LibreOffice> Geral na
barra de menu principal para abrir a caixa de diálogo das opções gerais.
2)Em um sistema operacional Mac, vá para LibreOffice> Preferências> Geral na barra de menu principal
para abrir a caixa de diálogo para opções gerais.
3)Selecione Usar caixas de diálogo do LibreOffice nas caixas de diálogo Abrir / Salvar e, apenas nos
sistemas operacionais Linux e Mac OS X, Imprimir caixas de diálogo para exibir as caixas de diálogo do
LibreOffice na tela do seu computador.
4)Clique em OK para salvar suas configurações e fechar a caixa de diálogo.

Ícones
Os ícones usados para ilustrar algumas das muitas ferramentas disponíveis no LibreOffice podem diferir
dos usados neste guia. Os ícones neste guia foram retirados de uma instalação do LibreOffice que foi
configurada para exibir o conjunto de ícones do Galaxy.
Se desejar, você pode alterar seu pacote de software do LibreOffice para exibir os ícones do Galaxy da
seguinte maneira:
1)Nos sistemas operacionais Linux e Windows, vá para Ferramentas> Opções> LibreOffice> Exibir na
barra de menus principal para abrir a caixa de diálogo das opções de exibição.
2)Em um sistema operacional Mac, acesse LibreOffice> Preferências> Exibir na barra de menu principal
para abrir a caixa de diálogo das opções de visualização.
3)Em Interface do usuário> Tamanho e estilo do ícone, selecione Galaxy nas opções disponíveis na lista
dro- p- down.
4)Clique em OK para salvar suas configurações e fechar a caixa de diálogo.

Alguns sistemas operacionais Linux, por exemplo Ubuntu, incluem LibreOffice


como parte da instalação e não podem incluir o Galaxy conjunto de ícone s . Você
Nota
deve ser capaz de baixar o conjunto de ícones do Galaxy do repositório de
software para o seu sistema operacional Linux.

Usando o LibreOffice em um Mac


Alguns keystrokes e itens de menu são diferentes em um Mac daqueles usados no Windows e no Linux. A
tabela abaixo fornece algumas substituições comuns para as instruções neste capítulo. Para uma lista
mais detalhada, consulte a Ajuda do aplicativo.

Windows ou Linux Equivalente em Mac Efeito


Ferramentas> LibreOffice> Preferências Acessar opções de configuração
Seleção do menu
Opções
Clique com o botão Controle + clique e / ou clique Abra um menu de contexto
direito com o botão direito
dependendo da configuração
do computador
Ctrl (controle) (comando) Usado com outras chaves
F5 Shift +  + F5 Abra o Navegador
F11 +t Abra a janela Estilos e formatação

Quais são todas essas coisas chamadas?


Os termos usados no LibreOffice para a maioria das partes da interface do usuário (as partes do programa
que você vê e usa, em contraste com o código por trás dos bastidores que realmente o fazem funcionar)
são as mesmas da maioria dos outros programas.
Uma caixa de diálogo é um tipo especial de janela. Sua finalidade é informá-lo sobre algo, solicitar
informações de você ou ambos. Ele fornece controles para você usar para especificar como executar uma
ação. Os nomes técnicos dos controles comuns são mostrados na Figura 1 . Na maioria dos casos, não
usamos os termos técnicos deste livro, mas é útil conhecê-los, porque a Ajuda e outras fontes de
informação costumam usá-los.

Figura 1: Diálogo mostrando controles comuns


1)página com guias (não estritamente falando um controle).
2)Botões de opção (apenas um pode ser selecionado por vez).
3)Caixa de seleção (mais de um pode ser selecionado por vez).
4)Caixa de rotação (clique nas setas para cima e para baixo para alterar o número mostrado na caixa de
texto ao lado ou digite a caixa de texto).
5)Miniatura ou pré-visualização.
6)Lista suspensa para selecionar um item.
7)Botões de pressão.
Na maioria dos casos, você pode interagir apenas com a caixa de diálogo (não com o documento em si),
desde que a caixa de diálogo permaneça aberta. Quando você fecha a caixa de diálogo após o uso
(geralmente, clicando em OK ou outro botão salva suas alterações e fecha a caixa de diálogo), você pode
trabalhar novamente com o documento.
Algumas caixas de diálogo podem ser deixadas abertas enquanto você trabalha, para que você possa
alternar entre a caixa de diálogo e o documento. Um exemplo desse tipo é a caixa de diálogo Localizar e
substituir.

Quem escreveu este livro?


Este livro foi escrito por voluntários da comunidade LibreOffice. Os lucros das vendas da edição impressa
serão usados para beneficiar a comunidade.

Perguntas frequentes
Como o LibreOffice é licenciado?
O LibreOffice é distribuído sob a Licença Pública Geral Menor (LGPL) aprovada pela Open Source
Initiative (OSI). A licença LGPL está disponível no site do LibreOffice:
http://www.libreoffice.org/download/license/
Posso distribuir o LibreOffice para alguém?
Sim.
Quantos computadores posso instalar?
Quantos você quiser.
Posso vendê-lo?
Sim.
Posso usar o LibreOffice no meu negócio?
Sim.
O LibreOffice está disponível no meu idioma?
O LibreOffice foi traduzido (localizado) para mais de 40 idiomas, então sua linguagem provavelmente é
suportada . Além disso, t aqui são mais de 70 s Pelling , hifenização e dicionário de sinónimos
dicionários disponíveis para idiomas e dialetos que não têm uma interface de programa localizado. Os
dicionários estão disponíveis no site do LibreOffice em: www.libreoffice.org .
Como você pode fazer isso de graça?
O LibreOffice é desenvolvido e mantido por voluntários e tem o apoio de várias organizações .
Eu estou escrevendo um aplicativo de software . Posso usar o código de programação do
LibreOffice no meu programa?
Você pode, dentro dos parâmetros definidos na LGPL. Leia a licença:
http://www.libreoffice.org/download/license/
Por que eu preciso do Java para executar o LibreOffice? Está escrito em Java?
O LibreOffice não está escrito em Java; está escrito na linguagem C ++ . Java é uma das várias
linguagens que podem ser usadas para estender o software. O Java JDK / JRE é necessário apenas
para alguns recursos; O mais notável é o mecanismo de banco de dados relacional HSQLDB.
Como posso contribuir com o LibreOffice?
Você pode ajudar com o desenvolvimento e suporte ao usuário do LibreOffice de várias maneiras, e
você não precisa ser um programador. Para começar, confira esta página:
http://www.documentfoundation.org/contribution/
Posso distribuir o PDF deste livro ou imprimir e vender cópias?
Sim, desde que você atenda aos requisitos de uma das licenças na declaração de direitos autorais no
início deste livro. Você não precisa solicitar permissão especial. Além disso, solicitamos que você
compartilhe com o projeto alguns dos lucros que você faz com a venda de livros, considerando todo o
trabalho que temos para produzi-los.
Capítulo 1
Introdução à Base
Introdução
Na operação diária do escritório, as planilhas são usadas regularmente para agregar conjuntos de dados e
realizar algum tipo de análise neles. Como os dados em uma planilha são dispostos em uma visualização
de tabela, claramente visíveis e capazes de serem editados ou adicionados, muitos usuários perguntam
por que devem usar um banco de dados em vez de uma planilha. Este manual explica s as diferenças
entre os dois, começando com uma pequena seção sobre o que pode ser feito com um banco de dados.
Este capítulo apresenta dois exemplos de banco de dados e todo o Manual é construído com base neles.
Um banco de dados é chamado Media_without_macros.odb ea outra, ampliada com a inclusão
de macros, é nam ed Media_with_macros.odb .

Base - uma c ontainer f o r d a conteúdo abase


Um arquivo Base é uma pasta compactada que contém informações para as diferentes áreas de trabalho
do Base. No uso diário, o Base inicialmente é aberto com a exibição a seguir.

O ambiente Base contém quatro áreas de trabalho: T Ables, Q ueries, F Orms e R ELATÓRIOS.
Dependendo da área de trabalho selecionado, várias tarefas- creat ing novo conteúdo ou chamar ing -se
elementos existentes -podem ser realizado.
Base começa com a visão F orm, porque os formulários são os elementos mais comumente usados
quando se trabalha com bancos de dados.

Entrada de dados usando formulários


Formulários simples mostram apenas uma tabela, como na parte superior do formulário Empréstimo .
O formulário de empréstimo foi ampliado para mostrar informações adicionais:
•O intervalo de pessoas mostrado pode ser filtrado no último nome para limitar os detalhes mostrados. Se
um usuário inserir a letra “G” no campo Filter (Last Name) à direita da tabela Loan, apenas as pessoas
cujo sobrenome começa com “G” serão mostradas.
•Novas informações do mutuário podem ser inseridas diretamente nos campos da tabela do formulário.
• Osdetalhes dos itens a serem emprestados são inseridos e mostrados na área no meio do formulário. Se
um item previamente emprestado está atrasado e deve ser devolvido th é área está bloqueada (sem
entrada possível ) eo título indicará “empréstimo temporário bloqueado!”.
•Os itens emprestados são mostrados na área inferior do formulário. A data para o retorno e um ch artigo
emprestado é comparado com a data atual e a duração do empréstimo restante mostrado .
•A data do empréstimo é definida como a data atual. No tração - campo para baixo à direita da Data de
empréstimo são os itens de mídia que podem ser emprestados. Os itens que já estão emprestados ao
mutuário selecionado não estão disponíveis para seleção.
•Os itens de mídia selecionados para empréstimo são adicionados aos detalhes do empréstimo atual
clicando no botão Atualizar .
•Na seção inferior do formulário (Retorno), não é possível excluir uma linha de dados. Somente os campos
Data de Devolução e Extensão podem ser editados. Se um tomador de empréstimo foi bloqueado
anteriormente e subseqüentemente retornou o item vencido, a área de empréstimo pode ser desbloqueada
clicando no botão Atualizar .
Todas essas funções podem ser executadas sem o uso de macros, quando o formulário é configurado e
preenchido da maneira descrita.

D entrada ata directamente numa mesa


A estrutura da tabela para tal formulário é relativamente básica e fácil de configurar. Na tabela mostrada
acima, os mesmos dados podem ser inseridos diretamente nas linhas e colunas da tabela, como quando
se usa o formulário.
•.O primeiro campo mostra uma chave primária ("ID") que é gerada automaticamente. Mais sobre este
tópico pode ser encontrado no capítulo sobre tabelas.
•.O segundo campo, MEDIA_ID, armazenar s a chave primária da mídia mesa, um número que se refere
aos meios. Na forma do id mídia, título e autor são mostrados na queda - menu de baixo.
•.O terceiro campo, Reader_ID, armazena a chave primária da tabela do Reader . Essa chave é um
número que se refere ao leitor. No formulário o sobrenome e o primeiro nome do leitor são mostrados.
•.O quarto campo armazena a data do empréstimo. Se esta data estiver presente e for posterior à data
atual, o conjunto de dados correspondente para o leitor será mostrado na tabela inferior do formulário, em
Retorno.
•.O campo marcado Extensão contém informações sobre extensões do empréstimo para um item. O
significado dos valores 1, 2 e assim por diante é explicado mais adiante. O banco de dados contém uma
tabela especial chamada Configurações para esse tipo de informação.
A entrada de th i dados s permite a gestão de uma biblioteca simples.

Consultas - obtendo informações sobre dados em tabelas

A consulta mostrada acima lista todas as mídias que estão atualmente sem empréstimo. Calcula para cada
item quanto tempo tem sido emprestado e o saldo do período do empréstimo.
•.Todas as mídias para as quais o campo Return_Date está vazio são listadas. Como uma visão geral
adicional, o nome do meio é incluído na consulta junto com o Media_ID.
•.A referência ao Reader é estabelecida com a chave primária da tabela do Reader .
•.O valor do campo LoanDays é calculado como a diferença entre o Loan_Date e a data atual.
•.O número de LoanDays é subtraído do Tempo do Empréstimo para fornecer o número restante de dias no
período do empréstimo. O tempo do empréstimo pode variar com diferentes tipos de mídia.
•.Na tabela Configurações, um valor de '1' para Extensão corresponde a uma extensão do período de
empréstimo de 7 dias. Nos dados definidos acima, a linha com Media_ID '2' mostra uma extensão de 7
dias.
Relatórios - p resentação de dados
Antes que um relatório real na forma de um aviso de recall possa ser impresso, as informações de recall
devem ser inseridas no formulário Recall. A tabela no formulário mostra todas as pessoas que
emprestaram itens com um tempo de empréstimo remanescente negativo.
Para cada item de mídia a ser rechamado, a data de rechamada e o número do aviso de rechamada são
inseridos. A data de rechamada é padronizada para a data atual. O número de rechamada é um número
inteiro incrementado em 1 com cada aviso de rechamada sucessivo para um determinado emprestador /
mídia.
Esse formulário, no exemplo atual do banco de dados sem macros, requer entrada do usuário para criar
avisos de recall. Na versão macro, a data é inserida automaticamente e o aviso de recall é impresso.

O aviso de recordação é gerado por meio de uma consulta dos dados de entrada anteriores . O usuário do
banco de dados só precisa escolher o relatório de Rechamada e uma carta de rechamada pode ser
impressa e enviada para todas as pessoas que tenham uma entrada de rechamada feita no formulário da
página anterior.
Nesse relatório, pode haver várias entradas (itens vencidos) para uma pessoa específica. Se a tabela que
contém os itens para essa pessoa exceder o espaço em uma página, ela será estendida para cobrir uma
página seguinte.
Tal relatório é mais abrangente do que uma carta de mala direta produzida com o Writer. Ele reúne
automaticamente os conjuntos de dados para impressão e organiza o texto acompanhante necessário.
Capítulo 2 Criando um banco de
dados
Como criar um novo banco de dados
Notas gerais sobre a criação de uma base de dados
Os fundamentos da criação de um banco de dados no LibreOffice são descritos no Capítulo 8 do Guia de
Introdução , Introdução à Base.
O componente de banco de dados do LibreOffice, chamado Base, fornece uma interface gráfica para
trabalhar com bancos de dados. Além disso, o LibreOffice contém uma versão do mecanismo de banco de
dados HSQL. Este banco de dados HSQLDB só pode ser usado por um único usuário. O conjunto de
dados inteiro é armazenado em um arquivo ODB que não possui mecanismo de bloqueio de arquivo
quando aberto por um usuário.

Novo banco de dados usando o mecanismo interno do HSQL


Se um banco de dados com vários usuários não for planejado ou o usuário desejar obter alguma
experiência inicial com um banco de dados, o mecanismo de banco de dados interno será suficiente. É
possível, em algum estágio posterior, transferir o banco de dados para um ambiente HSQLDB externo,
onde vários usuários podem ter acesso simultâneo ao banco de dados no servidor HSQLDB. Isso está
descrito no Apêndice deste Manual.
A criação de um novo banco de dados interno é descrita em detalhes em Introdução ao Base.
Um banco de dados registrado no LibreOffice pode ser acessado por outros componentes do programa
como uma fonte de dados (por exemplo, mala direta). Este processo de registro pode ser realizado em um
estágio posterior, se desejado.

Acessando bancos de dados externos


Um banco de dados externo deve existir antes de poder ser acessado. Supondo que o acesso a um banco
de dados seja desejado, o banco de dados deve ser configurado para permitir conexões de rede com um
nome de usuário e senha específicos para que programas externos possam se conectar a ele.
Quando esse banco de dados é configurado corretamente, um usuário pode, dependendo do software de
conexão disponível (o driver de banco de dados), criar tabelas, dados de entrada e dados de consulta.
Clique em Arquivo> Novo> Banco de Dados para abrir o Assistente de Banco de Dados e permitir que
uma conexão com um banco de dados existente seja feita. A lista de tipos de bancos de dados disponíveis
varia de acordo com o sistema operacional e a interface do usuário, mas os seguintes itens devem estar
sempre disponíveis:
•dBase
•JDBC
•MySQL
•ODBC
•Oracle JDBC
•PostgreSQL
•planilha
•texto
•bem como vários tipos de livros de endereços.
As opções de conexão variam de acordo com o tipo de banco de dados selecionado. Estes podem, em
qualquer caso, ser corrigidos posteriormente, após o arquivo * .odb ser criado.
Alguns tipos de bancos de dados (por exemplo, planilhas eletrônicas) não permitem a entrada de novos
dados. Estes são utilizados apenas para procurar ou reportar dados existentes.

Bancos de dados MySQL


Havia uma extensão para o MySQL, o MySQL Native Connector, que deveria permitir que o Base se
conectasse diretamente a um banco de dados MySQL. A extensão estava no centro de extensões do
LibreOffice na categoria base, mas não está sendo desenvolvida no momento.
O acesso geral ao MySQL para versões do LibreOffice a partir do 3.5 onwads é via JDBC ou ODBC. Para
poder usar o JDBC, é necessário instalar o mysql-connector-java.jar. Esse arquivo de arquivamento Java
deve ser copiado na mesma pasta em que a versão atual do java usada no LibreOffice está localizada. É
provável que seja uma subpasta como ... javapath ... / lib / ext para uma instalação do
Linux.
Alternativamente, a pasta apropriada contendo o arquivo Java pode ser definida através de Ferramentas>
Opções> Java> Caminho de Classe .
O método de acesso a um banco de dados MySQL existente é mostrado nas etapas a seguir.
A criação de um novo banco de dados só é possível no formato HSQLDB interno. A conexão com um
banco de dados externo só é possível quando o banco de dados já existe.
Selecione a opção Conectar a um banco de dados existente . Uma lista de formatos de banco de dados
está contida no menu suspenso. Selecione o MySQL.

A conexão com o MySQL pode ser via ODBC ou JDBC, a menos que um conector MySQL nativo tenha
sido instalado. Neste caso, uma conexão direta com o MySQL é possível.
Neste exemplo, selecione o conector Java JDBC.

O nome do banco de dados deve ser conhecido e inserido.


Se o servidor MySQL estiver no mesmo computador que o LibreOffice, então o nome do servidor pode ser
definido como localhost. Caso contrário, o endereço IP do servidor ou seu nome de host na rede ou na
Internet deve ser inserido. Também é possível acessar um banco de dados com o Base, no qual o banco
de dados está localizado no site de um provedor de serviços de Internet.
O número da porta padrão geralmente estará correto.
Digite a classe do driver JDBC e clique no botão Testar classe . Um diálogo deve aparecer confirmando
que o conector está carregado e acessível usando Java. O arquivo mysql-connector-java.jar deve estar no
mesmo caminho que a versão do Java em uso no LibreOffice ou diretamente vinculada ao LibreOffice.

O banco de dados na rede deve ser protegido com um nome de usuário e senha. Novamente, um teste de
conexão pode ser realizado.

Se uma conexão direta foi selecionada, este teste gerará mensagens de erro.
Nota Sem testes, o Base irá, no final do Assistente, abrir a janela do banco de dados
e conectar-se ao MySQL.
O teste de conexão inicia o processo de autenticação usando o nome do usuário inserido anteriormente.
Depois que a senha correta é entrada, um diálogo anuncia o resultado do teste. Se o MySQL não está
rodando neste momento, uma mensagem de erro é mostrada.

A etapa final é registrar o banco de dados. O banco de dados pode, se necessário, ser registrado
posteriormente para permitir seu uso com o Writer ou o Calc.
O Assistente finaliza o processo de conexão com o armazenamento do banco de dados ODB. O banco de
dados ODB contém todas as informações de conexão necessárias para permitir que as tabelas no banco
de dados sejam acessadas sempre que o banco de dados for aberto.
Nesta fase, escolha um nome para o arquivo de banco de dados ODB e salve-o. A próxima imagem é uma
visão da interface Base.

As tabelas no banco de dados estão contidas na árvore sob o nome do banco de dados.

A visão da árvore de tabelas pode ser fechada clicando no nome do banco de dados. Para uma única
conexão de banco de dados, isso não faz muito sentido, mas fornece uma indicação visível da conexão
direta.
Em vez de apenas a entrada do banco de dados na Etapa 3 do Assistente (consulte a barra de status
inferior), o LibreOffice abre todos os bancos de dados disponíveis no MySQL para o usuário “robby”.
As consultas devem incluir na sintaxe do MySQL não apenas o nome da tabela, mas também o banco de
dados que contém, por exemplo, o seguinte código :
… De "myphplib". "ASB" AS "ASB", "myphplib". "Kategorien" AS "Kategorien"
Também é possível, em cada caso, especificar um alias, criado a partir dos nomes de bancos de dados e
tabelas. Mais detalhes são fornecidos no capítulo sobre consultas.
Tabelas podem ser criadas e deletadas em um banco de dados. Campos com valores automáticos podem
ser criados ao configurar a estrutura das tabelas. No MySQL, o valor inicial de tais campos é padronizado
como 1.

bancos de dados dBase


Os bancos de dados do dBase têm um formato em que todos os dados estão contidos em tabelas
previamente inicializadas separadas. Links entre as tabelas devem ser feitos no código do programa.
Relações não são suportadas.

A conexão é feita para uma pasta específica. Todos os arquivos DBF nesta pasta serão incluídos e
mostrados no banco de dados ODB e podem ser vinculados usando consultas.
Tabelas no dBase não têm chave primária. Eles podem, em princípio, ser descritos como correspondentes
às planilhas no Calc.
Tabelas podem ser criadas e, em seguida, serão copiadas como novos arquivos na pasta selecionada
anteriormente.
O número de tipos de campo diferentes para uma nova tabela do dBase é claramente menor do que
quando o formato HSQLDB interno é usado. Na figura a seguir ainda existem alguns tipos de campos com
o mesmo nome de tipo.

O formato dBase é especialmente adequado para a troca e edição extensiva de dados. Além disso, os
cálculos da planilha podem acessar diretamente as tabelas do dBase. Pode ser melhor manipular os dados
no Base porque o Calc requer a entrada do tipo de codificação de caracteres, enquanto o Base
simplesmente usa a codificação apropriada fornecida pelo sistema operacional. Arquivos antigos do dBase
podem exibir pequenos erros de decodificação nos quais caracteres especiais foram usados.

Planilhas
As planilhas do Calc ou do Excel também podem ser usadas como a origem da tabela para bancos de
dados. Se, no entanto, uma planilha do Calc for usada, nenhuma edição dos dados da tabela será possível.
Se o documento do Calc ainda estiver aberto, ele será protegido contra gravação.
As únicas perguntas a serem respondidas são a localização do arquivo de planilha e se ele está ou não
protegido por senha. Base abre a planilha e inclui todas as planilhas no documento. A primeira linha é usada
para os nomes dos campos e os nomes das planilhas se tornam os nomes das tabelas.
Relacionamentos entre planilhas não podem ser configurados no Base, já que o Calc não é adequado para
uso como banco de dados relacional.

Livro de endereços do Thunderbird


O Assistente procurará automaticamente uma conexão com um catálogo de endereços, por exemplo,
conforme usado no Thunderbird. O assistente solicitará a localização do arquivo ODB que será produzido.

Todas as tabelas são mostradas. Como no Calc, as tabelas não são editáveis. Base usa os dados da
tabela apenas para consultas e aplicativos de mala direta.

Capítulo 3
Tabelas
Informações gerais sobre tabelas
Bancos de dados armazenam dados em tabelas. A principal diferença das tabelas em uma planilha simples
é que os campos nos quais os dados são gravados devem ser definidos claramente de antemão. Por
exemplo, um banco de dados não permite que um campo de texto contenha números para uso em
cálculos. Esses números são exibidos, mas apenas como seqüências de caracteres, cujo valor numérico
real é zero. Da mesma forma, as imagens não podem ser incluídas em todos os tipos de campos.
Detalhes sobre quais tipos de dados estão disponíveis podem ser obtidos na janela Design de Tabelas na
Base. Eles são mostrados no Apêndice deste manual.
Bancos de dados simples são baseados em apenas uma tabela. Todos os elementos de dados são
inseridos independentemente, o que pode levar à entrada múltipla dos mesmos dados. Um catálogo de
endereços simples para uso privado pode ser criado dessa maneira. No entanto, o catálogo de endereços
de uma escola ou de uma associação esportiva pode conter tanta repetição de códigos postais e locais que
esses campos são melhor colocados em uma ou até duas tabelas separadas.
Armazenar dados em tabelas separadas ajuda:
•Reduzir a entrada repetida do mesmo conteúdo
•Evitar erros de ortografia devido a entrada repetida
•Melhorar a filtragem de dados nas tabelas exibidas
Ao criar uma tabela, você deve sempre considerar se várias repetições, especialmente de texto ou
imagens (que consomem muito armazenamento), podem ocorrer na tabela. Nesse caso, você precisa
exportá-los para outra tabela. Como fazer isso, em princípio, é descrito no Capítulo 8, Introdução ao Base,
no manual Introdução ao LibreOffice .

Relacionamentos entre tabelas


Este capítulo explica muitas dessas etapas em detalhes, usando um banco de dados de exemplo para uma
biblioteca: media_without_macros . Construir as tabelas para esse banco de dados é um trabalho
extenso, pois abrange não apenas a adição de itens em uma biblioteca de mídia, mas também o
empréstimo subseqüente deles.

Relacionamentos para tabelas em bancos de dados


Quanto mais relacionamentos houver entre as tabelas, mais complexa será a tarefa de design. A Figura 2
mostra a estrutura geral da tabela deste banco de dados de exemplo como uma visão geral, dimensionada
para caber no tamanho da página deste documento. Para ler o conteúdo, amplie a página para 200%.

Figura 2: Diagrama de relacionamento para o banco de dados de exemplo media_without_macros

Relações um-para-muitos
O banco de dados media_without_macros lista os títulos da mídia em uma tabela. Como os títulos podem
ter várias legendas ou, às vezes, nenhuma, as legendas são armazenadas em uma tabela separada.
Esse relacionamento é conhecido como um-para-muitos (1: n). Muitas legendas podem ser atribuídas a um
meio, por exemplo, os vários títulos de faixa para um CD de música. A chave primária da tabela Media é
armazenada como uma chave estrangeira na tabela Subtitle . A maioria dos relacionamentos entre tabelas
em um banco de dados são relacionamentos um-para-muitos.
Figura 3: Exemplo 1: n relacionamento; relação n: m

Muitos-para-muitos relacionamentos
Um banco de dados para uma biblioteca pode conter uma tabela para nomes de autores e uma tabela para
a mídia. A conexão entre um autor e, por exemplo, livros que o autor escreveu, é óbvia. A biblioteca pode
conter mais de um livro por um autor. Também pode conter livros com vários autores. Esse relacionamento
é conhecido como muitos-para-muitos (n: m). Essas relações exigem uma tabela que atua como
intermediária entre as duas tabelas em questão. Isso é representado na Figura 3 pela tabela
rel_Media_Author .
Assim, na prática, a relação n: m é resolvida tratando-a como duas relações 1: n. Na tabela intermediária, o
Media_ID pode ocorrer mais de uma vez, assim como o Author_ID . Mas ao usá-los como um par, não há
duplicação: não há dois pares idênticos. Portanto, esse par atende aos requisitos da chave primária da
tabela intermediária.

Para um determinado valor de Media_ID, existe apenas um título da mídia e


Nota um ISBN. Para um determinado valor para Author_ID, há apenas um nome e
sobrenome de um autor. Assim, para um determinado par desses valores, há
apenas um ISBN e apenas um Autor. Isso torna o par único.

Relações um-para-um

Figura 4: Exemplo 1: 1 relacionamento


O banco de dados da biblioteca descrito acima requer uma tabela para os leitores. Nesta tabela, apenas os
campos diretamente necessários foram planejados antecipadamente. Mas para um banco de dados
escolar, a turma da escola também é necessária. Nos registros da classe escolar, você pode encontrar os
endereços dos devedores, quando necessário. Portanto, não é necessário incluir esses endereços no
banco de dados. O relacionamento dos alunos na escola é separado da tabela do leitor, porque o
mapeamento para as aulas não é apropriado em todas as áreas. Daí surge uma relação de 1: 1 entre o
leitor e a atribuição individual da turma escolar.
Em um banco de dados para uma biblioteca pública, os endereços dos leitores são obrigatórios. Para cada
leitor existe um único endereço. Se houver vários leitores no mesmo endereço, essa estrutura exigiria que
o endereço fosse inserido novamente, já que a chave primária da tabela do Reader é inserida diretamente
como a chave primária na tabela de endereços . A chave primária e a chave estrangeira são uma e a
mesma na tabela de endereços . Este é, portanto, um relacionamento 1: 1.
Um relacionamento 1: 1 não significa que, para cada registro em uma tabela, haverá um registro
correspondente em outra tabela. Mas no máximo haverá apenas um registro correspondente. Um
relacionamento 1: 1, portanto, leva a campos sendo exportados, que serão preenchidos com conteúdo para
apenas alguns dos registros.

Tabelas e relacionamentos para o banco de dados de exemplo


O banco de dados de exemplo (media_without_macros) deve atender a três requisitos: adições e
remoções de mídia, empréstimos e administração de usuários.

Tabela de adição de mídia


Primeiro, a mídia deve ser adicionada ao banco de dados para que uma biblioteca possa trabalhar com
eles. No entanto, para um simples resumo de uma coleção de mídia em casa, você poderia criar bancos
de dados mais fáceis com o assistente; isso pode ser suficiente para uso doméstico.
A tabela central para adição de mídia é a tabela Mídia (veja a Figura 5 ) .
Figura 5: Adição de mídia

Nesta tabela, todos os campos inseridos diretamente assumem que não estão sendo usados também para
outras mídias com o mesmo conteúdo. A duplicação deve, portanto, ser evitada.
Por esse motivo, os campos planejados na tabela incluem o título, o ISBN, uma imagem da capa e o ano
de publicação. A lista de campos pode ser estendida, se necessário. Assim, por exemplo, os bibliotecários
podem querer incluir campos para o tamanho (número de páginas), o título da série e assim por diante.
A tabela de legendas contém o conteúdo detalhado dos CDs. Como um CD pode conter várias partes de
música, um registro das peças individuais na tabela principal exigiria muitos campos adicionais (Legenda 1,
Legenda 2, etc.) ou o mesmo item teria que ser inserido várias vezes. A tabela de legendas, portanto, está
em um relacionamento n: 1 com a tabela Mídia .
Os campos da tabela de legendas são (além do próprio subtítulo) o número de sequência da legenda e a
duração da faixa. O campo Comprimento deve primeiro ser definido como um campo de hora. Desta
forma, a duração total do CD pode ser calculada e exibida em um resumo, se necessário.
Os autores têm uma relação com a mídia. Um item pode ter vários autores e um autor pode ter criado
vários itens. Esse relacionamento é controlado pela tabela rel_Media_Author . A chave primária dessa
tabela de vinculação é a chave estrangeira, formada pelas tabelas Autor e Mídia . A tabela
rel_Media_Author inclui uma classificação adicional (Author_Sort) dos autores, por exemplo, pela
sequência na qual eles são nomeados no livro. Além disso, um rótulo suplementar, como Produtor,
Fotógrafo e assim por diante, é adicionado ao autor quando necessário.
Categoria, Mediastyle, Town e Publisher têm um relacionamento de 1: n.
Para a categoria, uma pequena biblioteca pode usar algo como Arte ou Biologia. Para bibliotecas maiores,
sistemas gerais para bibliotecas estão disponíveis. Esses sistemas fornecem abreviações e descrições
completas. Portanto, ambos os campos aparecem em Categoria.
O Mediastyle está vinculado ao período de empréstimo do Loantime. Por exemplo, os DVDs de vídeo
podem, em princípio, ter um período de empréstimo de 7 dias, mas os livros podem ser emprestados por
21 dias. Se o período de empréstimo estiver vinculado a qualquer outro critério, haverá mudanças
correspondentes em sua metodologia.
A cidade t capaz não só serve para armazenar dados de localização dos meios de comunicação, mas
também para armazenar os locais utilizados nos endereços de usuários.
Como os editores também recorrem com frequência, uma tabela separada é fornecida para eles.
A tabela Media possui no total quatro chaves estrangeiras e uma chave primária, que é usada como uma
chave estrangeira em duas tabelas, conforme mostrado na Figura 5 .
Tabela de empréstimo
A tabela central é Empréstimo (veja a Figura 6 ). É o link entre as tabelas Mídia e Leitor. No caso de você
precisar descobrir retrospectivamente quem retirou um livro (por exemplo, se alguém notar durante o
processo de empréstimo que o livro está danificado, ou se você deseja fazer uma lista das mídias mais
populares), o Loan_Date no O registro de empréstimo não é simplesmente excluído durante o processo de
devolução. Em vez disso, um Return_Date é registrado.
Da mesma forma, os Lembretes são integrados ao procedimento de empréstimo. Cada lembrete é inserido
separadamente na tabela Recall para que o número total de lembretes possa ser determinado.
Assim como um período de extensão em semanas, há um campo extra no registro de empréstimo que
permite que a mídia seja emprestada usando um scanner de código de barras ( Media_ID_BC ). Os
códigos de barras contêm, além do Media_ID individual, um dígito de verificação que o scanner pode usar
para determinar se o valor digitalizado está correto. Este campo de código de barras está em c luded aqui
apenas para fins de teste. Seria melhor se a chave primária da mesa de mídia pudesse ser inserida
diretamente no formulário de código de barras ou se uma macro fosse usada para remover o dígito de
verificação do número do código de barras digitado antes do armazenamento.
Finalmente, precisamos conectar o Reader ao empréstimo. Na tabela real do leitor, apenas o nome, um
bloqueio opcional e uma chave estrangeira vinculada à tabela de Gênero são incluídos no plano.
Figura 6: Empréstimo

Tabela de administração de usuários


Para este design de tabela, dois cenários são previstos. A cadeia de tabelas mostrada na Figura 6 é
projetada para bibliotecas escolares. Aqui não há necessidade de endereços, pois os alunos podem ser
contatados através da escola. Lembretes não precisam ser enviados por correio, mas podem ser
distribuídos internamente.
A cadeia de endereços é necessária no caso de bibliotecas públicas. Aqui você precisa inserir dados que
serão necessários para a criação de cartas de lembrete. Veja a Figura 7 .

Figura 7: Leitores - uma cadeia de classes da escola e uma cadeia de endereços


A tabela de gênero garante que a saudação correta seja usada em lembretes. A gravação de lembretes
pode ser automatizada, tanto quanto possível. Além disso, alguns nomes podem ser igualmente
masculinos ou femininos. Portanto, a listagem separada de gênero é necessária mesmo quando os
lembretes são escritos à mão.
A tabela rel_Reader_Schoolclass , como a tabela A ddress , tem um relacionamento 1: 1 com a tabela do
Reader . Isso foi escolhido porque a turma da escola ou o endereço podem ser necessários. Caso
contrário, o Schoolclass_ID poderia ser colocado diretamente na mesa do aluno; o mesmo seria verdade
para o conteúdo completo da tabela de endereços em um sistema de biblioteca pública.
Uma classe de escola geralmente consiste em uma designação de ano e um sufixo de fluxo. Em uma
escola de 4 cursos, esse sufixo pode ser executado de a para d . O sufixo é inserido na tabela de classes .
O ano está em uma tabela de notas separada . Dessa forma, se os leitores subirem uma turma no final de
cada ano letivo, você pode simplesmente alterar a entrada do ano para todos.
O endereço também é dividido. A rua é armazenada separadamente porque os nomes das ruas dentro de
uma área são frequentemente repetidos. O código postal e a cidade são separados porque geralmente há
vários códigos postais para uma única área e, portanto, mais códigos postais que cidades. Assim, em
comparação com o Endereço t capaz, o Código Postal tabela contém significativamente menos registros
e da Cidade de mesa ainda menos.
A forma como esta estrutura de tabela é colocada em uso é explicada em mais detalhes no Capítulo 4,
Formulários, neste manual.

Criando Tabelas
A maioria dos usuários do LibreOffice geralmente usa a interface gráfica do usuário (GUI) exclusivamente
para criar tabelas. A entrada direta de comandos SQL torna-se necessária quando, por exemplo, um
campo deve ser subsequentemente inserido em uma determinada posição, ou um valor padrão deve ser
definido após a tabela ter sido salva.
Tabela de terminologia: A figura abaixo mostra a divisão padrão de tabelas em colunas e linhas.

Registros de dados são armazenados em uma única linha da tabela. Colunas individuais são amplamente
definidas pelo campo, pelo tipo e pelas regras que determinam se o campo pode estar vazio. De acordo
com o tipo, o tamanho do campo em caracteres também pode ser determinado. Além disso, um valor
padrão pode ser especificado para ser usado quando nada foi inserido no campo.
Na GUI base, os termos de uma coluna são descritos de forma um pouco diferente, conforme mostrado
abaixo.

O campo torna - se Nome do campo , o tipo torna - se Tipo de campo . Nome do campo e tipo de campo
são inseridos na área superior da janela Design da tabela. Na área inferior, você tem a oportunidade de
definir, nas propriedades do campo, as outras propriedades da coluna, na medida em que elas podem ser
definidas usando a GUI. Limitações incluem a configuração do valor padrão de um campo de data para a
data real de entrada. Isso é possível apenas usando o comando SQL apropriado (consulte “ Entrada direta
de comandos SQL ” na página 43 ).

Valores padrão: O termo "Valor padrão" na GUI não significa o que o usuário do
banco de dados geralmente entende como um valor padrão. A GUI exibe um
certo valor visivelmente, que é salvo com os dados.
Nota O valor padrão em um banco de dados é armazenado na definição da tabela.
Em seguida, ele é gravado no campo sempre que estiver vazio em um novo
registro de dados. Os valores padrão do SQL não aparecem ao editar as
propriedades da tabela.

Criação usando a interface gráfica do usuário


A criação de banco de dados usando a interface gráfica com o usuário é descrita em detalhes no Capítulo
8, Introdução à Base, no manual Introdução ao LibreOffice . Portanto, apenas as principais fontes de erro
são descritas aqui.
Quando um design de tabela é salvo, você pode ser perguntado se uma chave primária deve ser criada.
Isso significa que um campo necessário está faltando na tabela. Sem uma chave primária, o banco de
dados não pode acessar as tabelas. Normalmente, esse campo recebe o ID de abreviação e o tipo de
dados INTEGER e pode ser executado como um AutoValue. Você pode torná-lo a chave primária clicando
com o botão direito do mouse no campo correspondente.
Se as informações de outra tabela precisarem ser obtidas para essa (por exemplo, um banco de dados de
endereços com códigos e locais de postagem separados), você deverá incluir na tabela um campo do
mesmo tipo de dados que a chave primária da outra tabela. Se a tabela Postcode tiver como chave
primária o ID do campo , do tipo de dados Tiny Integer , a tabela Address deve ter um campo Postcode_ID
com o tipo de dados Tiny Integer . Em outras palavras, a tabela Endereço sempre conterá apenas o
número que serve como chave primária na tabela Código postal . Isso significa que o endereço tabela
agora tem uma chave estrangeira, além de sua própria chave primária.
Regras básicas para nomear campos na tabela: nenhum campo pode ter o mesmo nome. Portanto, você
não pode ter um segundo campo com o nome ID como uma chave estrangeira na tabela Address.
Existem limites para as alterações que você pode fazer no tipo de campo. Uma atualização (campo de
texto mais longo, intervalo numérico maior) não é problemática, pois todos os valores já inseridos caberão
no novo tipo. Um downgrade cria problemas e pode causar perda de dados.

Criando um índice
Às vezes, é útil indexar outros campos ou uma combinação de outros campos além da chave primária. Um
índice acelera a pesquisa e também pode ser usado para impedir entradas duplicadas.
Cada índice tem uma ordem de classificação definida. Se uma tabela for exibida sem ordenação, a ordem
de classificação será de acordo com o conteúdo dos campos especificados no índice.

Figura 8: Acesso ao Design do Índice

Abra a tabela para edição clicando com o botão direito do mouse e usando o menu de contexto. Então você
pode acessar a criação de índice com Ferramentas> Design de índice .
Figura 9: Criando
um novo índice

Na caixa de diálogo Índices (Figura 9 ), clique em Novo Índice para criar um índice além da chave
primária.
O novo índice recebe automaticamente o nome index1 . O campo Index especifica qual campo ou campos
devem ser usados para este índice. Ao mesmo tempo, você pode escolher a ordem de classificação.
Figura 10: O
índice é definido
como único.

Em princípio, um índice também pode ser criado a partir de campos de tabela que não contêm valores
exclusivos. No entanto, na Figura 10 , o detalhe do índice exclusivo foi verificado, para que o campo
LastName junto com o campo FirstName possa ter apenas entradas que ainda não ocorrem nessa
combinação. Assim, por exemplo, Robert Müller e Robert Maier são possíveis, e também Robert Müller e
Eva Müller.
Se um índice for criado apenas para um campo, a exclusividade será aplicada a esse campo. Esse índice
geralmente é a chave primária. Neste campo, cada valor pode ocorrer apenas uma vez. Além disso, no
caso de chaves primárias, o campo não pode ser NULL em nenhuma circunstância.
Uma circunstância excepcional para um índice exclusivo é quando não há entrada em um campo (o campo
é NULL). Como o NULL pode ter qualquer valor arbitrário, um índice usando dois campos sempre pode ter
a mesma entrada repetidamente em um dos campos, desde que não haja entrada no outro.

NULL é usado em bancos de dados para designar uma célula vazia, uma que
não contém nada. Nenhum cálculo é possível usando um campo NULL. Isso
Nota
contrasta com as planilhas, nas quais os campos vazios contêm
automaticamente o valor 0 (zero).
Exemplo: Em um banco de dados de mídia, o número da mídia e a data do empréstimo são inseridos
quando o item é emprestado. Quando o item é retornado, uma data de retorno é inserida. Em teoria, um
índice usando os campos Media_ID e ReturnDate poderia impedir facilmente que o mesmo item fosse
emprestado repetidamente sem que a data de retorno fosse anotada. Infelizmente isso não funcionará
porque a data de retorno inicialmente não tem valor. O índice impedirá que um item seja marcado como
retornado duas vezes com a mesma data, mas não fará mais nada.

Limitações do design de tabelas gráficas


A sequência de campos em uma tabela não pode ser alterada após o banco de dados ter sido salvo. Para
exibir uma sequência diferente, é necessária uma consulta.
Somente a entrada de comandos SQL diretos pode inserir um campo em uma posição específica na
tabela. No entanto, os campos já criados não podem ser movidos por esse método.
As propriedades das tabelas devem ser definidas no início: por exemplo, quais campos não devem ser
NULL e quais devem conter um valor padrão (Padrão). Essas propriedades não podem ser alteradas
posteriormente usando a GUI.
Os valores padrão definidos aqui não têm nada a ver com os valores padrão no próprio banco de dados.
Por exemplo, você não pode definir o padrão para um campo de data como sendo a data de entrada. Isso
só é possível com comandos SQL inseridos diretamente.

Entrada direta de comandos SQL


Para inserir comandos SQL diretamente, vá para Ferramentas> SQL .

Você pode então inserir comandos na área superior da janela (mostrada na Figura 11 ). A área inferior
mostra o resultado ou, se apropriado, o motivo pelo qual o comando falhou.
Consultas não podem ser criadas aqui. Para estes, a janela Design de consulta oferece uma possibilidade
extra de editar a consulta no modo SQL.
Figura 11: Diálogo para entrada direta de
comandos SQL

Um resumo dos comandos possíveis para o mecanismo HSQLDB integrado pode ser encontrado em
http://www.hsqldb.org/doc/1.8/guide/ch09.html . O conteúdo é descrito nas seções a seguir. Alguns
comandos só fazem sentido ao lidar com um banco de dados HSQLDB externo (especificar usuário, etc.).
Quando necessário, eles são tratados na seção “Trabalhando com o HSQLDB externo” no Apêndice deste
manual.

Nota O LibreOffice é baseado na versão 1.8.0 do HSQLDB. A versão do servidor


atualmente disponível é 2.2. As funções da nova versão são mais extensas.
Uma descrição mais detalhada é fornecida nos pacotes de instalação do
HSQLDB, que podem ser baixados em
http://sourceforge.net/projects/hsqldb/files/hsqldb/ .

Criação de tabelas
Um comando simples para criar uma tabela utilizável é:
CREATE TABLE "Teste" ("ID" INT PRIMARY KEY, "Texto" VARCHAR (50));
CREATE TABLE "Test" : Cria uma tabela com o nome "Test".
() : com os nomes de campos, tipos de campos e opções especificados.
"ID" INT PRIMARY KEY, "Texto" VARCHAR (50) : Nome do campo "ID" com o tipo numérico
inteiro como chave primária, nome do campo "Texto" com o tamanho do texto variável tamanho do texto e o
tamanho do texto limitado a 50 caracteres .
CRIAR [MEMORY | CACHED | [GLOBAL] TEMPORÁRIO | TEMP | TEXTO] TABELA "Nome
da tabela" (<Definição de campo> [, ...] [, <Definição de restrição> ...])
[ON COMMIT {DELETE | PRESERVE} ROWS];
[MEMORY | CACHED | [GLOBAL] TEMPORÁRIO | TEMP | TEXTO]:
A configuração padrão é MEMORY : HSQLDB cria todas as tabelas na memória principal. Essa
configuração também se aplica às tabelas gravadas no banco de dados interno pelo LibreOffice Base.
Outra possibilidade seria escrever as tabelas no disco rígido e usar a memória apenas para armazenar
em buffer o acesso ao disco rígido ( CACHED ). Tabelas no formato TEXT (como CSV) não
são graváveis em bancos de dados internos que são configurados puramente em MEMORY ,
enquanto o Base não pode acessar TEMPORARY ou TEMPtabelas. Os comandos SQL são
executados neste caso, mas as tabelas não são exibidas (e portanto não podem ser excluídas) usando
a GUI, e os dados inseridos via SQL também não são visíveis para o módulo de consulta da GUI, a
menos que a exclusão automática do conteúdo após o commit final ser evitado. Qualquer pedido neste
caso mostra uma tabela sem qualquer conteúdo.
Tabelas construídas diretamente com o SQL não são exibidas imediatamente. Você deve usar View>
Refresh Tables ou simplesmente fechar o banco de dados e reabri-lo.
<Definição de campo>:
"Nome do campo" Tipo de dados [(Número de caracteres [, Casas decimais])]
[{DEFAULT "Valor padrão" | GERADO PELO PADRÃO COMO IDENTIDADE (INICIAR COM
<n> [, INCREMENTO POR <m>])}] | [[NOT] NULL] [IDENTIDADE] [CHAVE PRIMÁRIA]
Permite que os valores padrão sejam incluídos na definição do campo.
Para campos de texto, você pode inserir texto entre aspas simples ou NULO . A única função SQL
permitida é CURRENT_USER . Isso só faz sentido se o HSQLDB estiver sendo usado como um
banco de dados externo do servidor com vários usuários.
Para campos de data e hora, uma data, um horário ou uma combinação dos dois pode ser inserida
entre aspas simples ou NULL . Você deve garantir que a data siga as convenções americanas (aaaa-
mm-dd), que a hora tenha o formato hh: mm: ss e que um valor combinado de data / hora tenha o
formato aaaa-mm-dd hh: mm: ss .
Funções SQL permitidas:
para a data atual CURRENT_DATE, TODAY, CURDATE ()
para a hora atual CURRENT_TIME, NOW, CURTIME ()
para o registro de data e hora de dados atuais CURRENT_TIMESTAMP, NOW .
Para campos booleanos (sim / não), as expressões FALSE, TRUE, NULL podem ser inseridas.
Estes devem ser inseridos sem aspas simples.
Para campos numéricos, qualquer número válido no intervalo ou NULL é possível. Aqui também, se
você digitar NULL , não use aspas. Ao digitar decimais, certifique-se de que o ponto decimal seja um
ponto (ponto) e não uma vírgula.
Para campos binários (imagens, etc.), qualquer cadeia hexadecimal válida entre aspas simples ou
NULL é possível. Uma string de exemplo hexadecimal é: '0004ff', que representa 3 bytes, primeiro
0, depois 4 e finalmente 255 (0xff). Como os campos binários na prática precisam ser inseridos apenas
para imagens, você precisa conhecer o código binário da imagem que deve servir como padrão.
NOT NULL: o valor do campo não pode ser NULL . Esta condição só pode ser dada na definição do
campo.

Sistema hexadecimal: Os números são baseados em 16. Um sistema misto


Nota que consiste nos números de 0 a 9 e as letras a a f fornece 16 dígitos
possíveis para cada coluna. Com duas colunas, você pode ter 16 * 16 = 256
valores possíveis. Isso corresponde a 1 byte (2 8 ).

<Definição de restrição>:
[CONSTRAINT "Nome"]
UNIQUE ("Field_name 1" [, "Field_name 2" ...]) |
PRIMARY KEY ("Field_name 1" [, "Field_name 2" ...]) |
CHAVE ESTRANGEIRA ("Field_name 1" [, "Field_name 2" ...])
REFERÊNCIAS "other_table_name" ("Field_name_1" [, "Field_name 2" ...])
[ON {DELETE | ATUALIZAR}
{CASCADE | SET DEFAULT | SET NULL}] |
CHECK (<Search_condition>)
As restrições definem condições que devem ser atendidas quando os dados são inseridos. Restrições
podem receber um nome.
UNIQUE ("Field_name"): o valor do campo deve ser exclusivo dentro desse campo
PRIMARY KEY ("Field_name"): o valor do campo deve ser exclusivo e não pode ser NULL
(chave primária)
FOREIGN KEY ("Field_name") REFERENCES <"other_table_name" >
("Field_name"): Os campos especificados desta tabela estão vinculados aos campos de outra
tabela. O valor do campo deve ser testado para integridade referencial como chaves estrangeiras; ou
seja, deve haver uma chave primária correspondente na outra tabela, se um valor for inserido aqui.
[ON {DELETE | ATUALIZAÇÃO} {CASCADE | SET DEFAULT | SET NULL}]:No caso de
uma chave estrangeira, isso especifica o que deve acontecer se, por exemplo, o registro externo for
excluído. Não faz sentido, em uma tabela de empréstimo para uma biblioteca, ter um número de
usuário para o qual o usuário não exista mais. O registro correspondente deve ser modificado para que
o relacionamento entre as tabelas permaneça válido. Normalmente, o registro é simplesmente excluído.
Isso acontece se você selecionar ON DELETE CASCADE .
CHECK (<Search_condition>): Formulado como uma condição WHERE , mas apenas para
o registro atual.
Você precisa de restrições quando o relacionamento entre tabelas ou o índice de determinados campos
deve ser definido.
[ON COMMIT {DELETE | PRESERVE} ROWS]:
O conteúdo de tabelas do tipo TEMPORARY ou TEMP é apagado por padrão quando você
terminar de trabalhar com um registro específico ( ON COMMIT DELETE ROWS ). Isso permite criar
registros temporários, que contêm informações para outras ações a serem executadas ao mesmo
tempo.
Se você quiser que uma tabela desse tipo contenha dados disponíveis para uma sessão inteira (de abrir
um banco de dados para fechá-lo), escolha ON COMMIT PRESERVE ROWS .

Modificação tabela
Às vezes você pode querer inserir um campo adicional em uma determinada posição na tabela. Suponha
que você tenha uma tabela chamada Endereços com ID de campos , Nome , Rua e assim por diante.
Você percebe que talvez seja sensato distinguir os primeiros nomes e sobrenomes.
ALTER TABLE "Addresses" ADICIONAR "First Name" VARCHAR (25) ANTES de
"Nome";
ALTER TABLE "Addresses" : Altere a tabela com o nome "Addresses".
ADD "First Name" VARCHAR (25) : insira o campo "FirstName" com um comprimento de 25
caracteres.
ANTES de "Nome" : antes do campo "Nome".
A possibilidade de especificar a posição dos campos adicionais após a criação da tabela não está
disponível na GUI.
ALTER TABLE "Table_name" ADD [COLUMN] <definição_de_campo> [BEFORE
"already_existing_field_name"];
A designação adicional COLUMN não é necessária nos casos em que não há opções alternativas
disponíveis.
ALTER TABLE "Table_name" DROP [COLUMN] "Field_name";
O campo "Nome do campo" é apagado da tabela Table_name . No entanto, isso não ocorre se o campo
estiver envolvido em uma exibição ou como uma chave estrangeira em outra tabela.
ALTER TABLE "Table_name" ALTER COLUMN "Field_name" RENAME PARA
"New_field_name"
Altera o nome de um campo.
ALTER TABLE "Table_name" ALTER COLUMN "Field_name" SET DEFAULT <valor
padrão>};
Define um valor padrão específico para o campo. NULL remove um valor padrão existente.
ALTER TABLE "Table_name" ALTER COLUMN "Field_name" SET [NOT] NULL
Define ou remove uma condição NOT NULL para um campo.
ALTER TABLE "Table_name" ALTER COLUMN <Definição de campo>;
A definição do campo corresponde à da criação da Tabela com as seguintes restrições:
•O campo já deve ser um campo de chave primária para aceitar a propriedade IDENTIDADE .
IDENTITY significa que o campo possui a propriedade AutoValue. Isso é possível apenas para os
campos INTEGER ou BIGINT . Para estas descrições de tipo de campo, consulte o Apêndice deste
manual.
•Se o campo já tiver a propriedade IDENTITY, mas ela não for repetida na definição do campo, a
propriedade IDENTITY existente será removida.
•O valor padrão será aquele especificado na nova definição de campo. Se a definição do valor padrão for
deixada em branco, qualquer padrão já definido será removido.
•A propriedade NOT NULL continua na nova definição, se não definido de outra forma. Isso está em
contraste com o valor padrão.
•Em alguns casos, dependendo do tipo de modificação, a tabela deve estar vazia para que a alteração
ocorra. Em todos os casos, a mudança terá efeito somente se for possível, em princípio (por exemplo,
uma mudança de NOT NULL para NULL ) e os valores existentes podem ser traduzidos (por
exemplo, uma mudança de TINYINT para INTEGER ).
ALTER TABLE "Table_name" ALTER COLUMN "Field_name" RESTART WITH
<New_field_value>
Este comando é usado exclusivamente para um campo IDENTITY . Ele determina o próximo valor
para um campo com o conjunto de funções Autovalue. Pode ser usado, por exemplo, quando um banco de
dados é inicialmente usado com dados de teste e, subsequentemente, fornecido com dados reais. Isso
requer que o conteúdo das tabelas seja excluído e um novo valor, como "1", seja definido para o campo.
ALTER TABLE "Table_name"
ADICIONAR [CONSTRAINT "Condition_name"] CHECK (<Search_condition>);
Isso adiciona uma condição de pesquisa introduzida pela palavra CHECK . Tal condição não será
aplicada retrospectivamente aos registros existentes, mas será aplicada a todas as alterações
subsequentes e registros recém-inseridos. Se um nome de restrição não for definido, um será atribuído
automaticamente.
Exemplo:
ALTER TABLE "Empréstimo" ADD CHECK (IFNULL ("Devolução_Data",
"Empréstimo_Data")> = "Empréstimo_Data")
A tabela Empréstimo precisa ser protegida contra erros de entrada. Por exemplo, você deve evitar
que uma data de retorno seja anterior à data do empréstimo. Agora, se esse erro ocorrer durante o
processo de retorno, você receberá uma mensagem de erro Verificar violação de
restrição…
ALTER TABLE "Table_name"
ADD [CONSTRAINT "Constraint_name"] UNIQUE ("Field_name1", "Field_name2"
...);
Aqui é adicionada uma condição que força os campos nomeados a terem valores diferentes em cada
registro. Se vários campos são nomeados, essa condição se aplica à combinação em vez dos campos
individuais. NULL não conta aqui. Um campo pode, portanto, ter o mesmo valor repetidamente sem
causar problemas, se o outro campo em cada um dos registros for NULL .
Este comando não funcionará se já houver uma condição UNIQUE para a mesma combinação de
campos.
ALTER TABLE "Table_name"
ADD [CONSTRAINT "Constraint_name"] PRIMARY KEY ("Field_name1",
"Field_name2" ...);
Adiciona uma chave primária, opcionalmente com uma restrição, a uma tabela. A sintaxe da restrição é a
mesma de quando uma tabela é criada.
ALTER TABLE "Table_name"
ADD [CONSTRAINT "Constraint_name"] CHAVE ESTRANGEIRA ("Field_name1",
"Field_name2" ...)
REFERÊNCIAS "Table_name_of_another_table" ("Field_name1_other_table",
"Field_name2_other_table" ...)
[ON {DELETE | ATUALIZAÇÃO} {CASCADE | SET DEFAULT | SET NULL}];
Isso adiciona uma chave estrangeira ( FOREIGN KEY ) à tabela. A sintaxe é a mesma de quando uma
tabela é criada.
A operação terminará com uma mensagem de erro, se algum valor na tabela não tiver um valor
correspondente na tabela que contém essa chave primária.
Exemplo: as tabelas Nome e Endereço devem ser vinculadas. A tabela Nome contém um campo com o
nome Address_ID . O valor disso deve estar vinculado ao ID do campo na tabela Address . Se o valor "1"
for encontrado em Address_ID, mas não no campo ID da tabela Address , o link não funcionará. Ele não
funcionará se os dois campos forem de tipos diferentes.
ALTER TABLE "Table_name" DROP CONSTRAINT "Constraint_name";
Este comando remove a restrição nomeada ( UNIQUE , CHECK , FOREIGN KEY ) de uma
tabela.
ALTER TABLE "Table_name" RENAME TO "new_table_name";
Finalmente, este comando altera apenas o nome de uma tabela.

Excluindo tabelas
DROP TABLE " Nome da tabela " [IF EXISTS] [RESTRICT | CASCATA];
Exclui a tabela "Nome da tabela".
IF EXISTS impede que um erro ocorra se esta tabela não existir.
RESTRICT é o arranjo padrão e não precisa ser explicitamente escolhido; isso significa que a exclusão
não ocorre se a tabela estiver vinculada a outra tabela pelo uso de uma chave estrangeira ou se houver
uma exibição ativa dessa tabela. As consultas não são afetadas, pois não são armazenadas no HSQLDB.
Se, em vez disso, você escolher CASCADE , todos os links para a tabela "Table_name" serão excluídos.
Nas tabelas vinculadas, todas as chaves estrangeiras são definidas como NULL. Todas as visualizações
referentes à tabela nomeada também são completamente excluídas.

Ligando Tabelas
Em princípio, você pode ter um banco de dados sem links entre tabelas. O usuário deve então assegurar,
durante a entrada de dados, que os relacionamentos entre as tabelas permanecem corretos. Isso
geralmente ocorre através do uso de formulários de entrada adequados que gerenciam isso.
A exclusão de registros em tabelas vinculadas não é uma tarefa simples. Suponha que você deseje excluir
uma determinada rua da tabela Street na Figura 7 , onde esse campo está vinculado à tabela Address
como uma chave estrangeira nessa tabela. As referências na tabela de endereços desapareceriam. O
banco de dados não permite isso, uma vez que o relacionamento tenha sido criado. Para excluir a Street , a
pré-condição deve ser preenchida, não sendo mais referenciada na tabela Address .
Links básicos são feitos usando Ferramentas> Relacionamentos . Isso cria uma linha de conexão da
chave primária em uma tabela para a chave estrangeira definida na outra.
Você pode receber a seguinte mensagem de erro ao criar um link:
Esta mensagem mostra algum texto em inglês e o comando SQL interno que causou o erro.
Os tipos de colunas não correspondem na instrução - como o comando SQL também é exibido, a
referência é claramente para as colunas Address.str_ID e Street.ID . Para fins de teste, um desses
campos foi definido como Integer e o outro como Tiny Integer. Portanto, nenhum link pode ser criado, pois o
campo não pode ter o mesmo valor que o outro.

Nesse caso, os tipos de coluna correspondem. A instrução SQL é a mesma do primeiro exemplo. Mas,
novamente, há um erro:
Violação de restrição de integridade - nenhum pai 1, tabela: Endereço ... - A integridade do
relacionamento não é garantida. No campo da tabela Endereço, Address.str_ID , há um número 1, que não
está presente no Street.ID . A tabela pai aqui é Street , já que sua chave primária é aquela que deve existir.
Esse erro é muito comum, quando duas tabelas devem ser vinculadas e alguns campos na tabela com a
chave estrangeira prospectiva já contêm dados. Se o campo de chave estrangeira contiver uma entrada
que não esteja presente na tabela pai (a tabela que contém a chave primária), esta é uma entrada inválida.

Se a vinculação for realizada com êxito e, posteriormente, houver uma tentativa de inserir um registro
inválido semelhante na tabela, você receberá a seguinte mensagem de erro:

Novamente, isso é uma violação de integridade. Base de se recusa a aceitar o valor 1 para o campo str_ID
após o link foi feita porque a rua tabela não contém tal v alor no campo ID.

Figura 12: Links podem ser editados com um clique com o botão direito

As propriedades de um link podem ser editadas para que a exclusão de um registro da tabela Street seja
definida simultaneamente como NULL para as entradas correspondentes na tabela Ad dress .
As propriedades mostradas na Figura 12 sempre se relacionam a uma ação vinculada à alteração em um
registro da tabela que contém a chave primária correspondente. No nosso caso, esta é a mesa de rua . Se
a chave primária de um registro nesta tabela for alterada (Atualização) , as ações a seguir poderão
ocorrer.
Nenhuma ação
Alterar a chave primária Street.ID não é permitido nesse caso, pois isso quebraria o relacionamento
entre as tabelas.
Atualizar cascata
Se a chave primária Street.ID for alterada, a chave estrangeira será alterada automaticamente para seu
novo valor. Isso garante que a ligação não seja danificada. Por exemplo, se um valor for alterado de 3
para 4, todos os registros da tabela Endereço que contiverem a chave estrangeira Address.Street_ID
com o valor 3, serão alterados para 4.

Figura 13: Editando as propriedades de um relacionamento

Definir nulo
Todos os registros que contêm essa chave primária específica agora não terão nenhuma entrada no
campo de chave estrangeira Address.Street_ID; o campo será NULL.
Conjunto padrão
Se a chave primária Street_ID for alterada, o valor de Address.Street_ID originalmente vinculado a ela
será definido como o valor padrão definido anteriormente. Para este propósito, precisamos de uma
definição inequívoca de um valor padrão. A GUI do LibreOffice Base até a versão 3.5 não parece
fornecer isso. Se o padrão for definido usando a instrução SQL:
ALTER TABLE "Endereço" ALTER COLUMN "Street_ID" SET DEFAULT 1;
a definição de link garante que o campo retornará a esse valor no caso de uma atualização. Portanto,
se a chave primária da tabela Street for alterada, a chave estrangeira correspondente na tabela Address
será definida como 1. Isso é útil quando um registro é necessário para ter um campo de rua, em outras
palavras, esse campo não pode ser NULL. Mas tenha cuidado! Se um não estiver em uso, você terá
criado um link para um não-existir e valor nt. Nesse caso, o HSQLDB parece ter sido projetado sem o
devido pensamento. Portanto, é possível destruir a integridade do relacionamento.

Atenção Se o valor padrão em um campo de chave estrangeira não estiver vinculado a


uma chave primária da tabela estrangeira, um link para um valor será criado,
isso não é possível. A integridade referencial do banco de dados seria
destruída.

Seria melhor não usar a possibilidade de definir o valor como padrão.


Se um registro for excluído da tabela Street , as seguintes opções estarão disponíveis.
Nenhuma ação
Nenhuma ação ocorre. Se a exclusão solicitada afetar um registro na tabela de endereços, a solicitação
será recusada.
Excluir em cascata
Se um registro for excluído da tabela Street e isso afetar um registro na tabela Address , esse registro
também será excluído.
Isso pode parecer estranho neste contexto, mas existem outras estruturas de tabelas nas quais faz
muito sentido. Suponha que você tenha uma tabela de CDs e uma tabela que armazena os títulos
nesses CDs. Agora, se um registro na tabela do CD for excluído, muitos títulos na outra tabela não
terão significado, pois não estão mais disponíveis para você. Em tais casos, uma exclusão em cascata
faz sentido. Isso significa que o usuário não precisa excluir todos esses títulos antes de excluir o CD do
banco de dados.
Definir como nulo
Isso é o mesmo que para a opção de atualização.
Definido como padrão
Este é o mesmo que para a opção de atualização e requer as mesmas precauções.

Para evitar mensagens de erro do banco de dados, tanto quanto possível, uma
Gorjeta vez que elas nem sempre são compreensíveis para o usuário, a opção
Nenhuma ação deve ser definitivamente evitada.

Inserindo dados em tabelas


Bancos de dados que consistem em apenas uma única tabela geralmente não requerem um formulário de
entrada, a menos que contenham um campo para imagens. No entanto, assim que uma tabela contiver
chaves estrangeiras de outras tabelas, os usuários devem lembrar quais números de chave devem ser
inseridos ou devem poder examinar as outras tabelas simultaneamente. Em tais casos, um formulário é
útil.

Entrada usando a GUI Base


Tabelas no contêiner de tabela são abertas clicando duas vezes nelas. Se a chave primária for um campo
de incremento automático, um dos campos visíveis conterá o texto AutoValue . Nenhuma entrada é
possível no campo AutoValue . Seu valor atribuído pode ser alterado, se necessário, mas somente após o
registro ter sido confirmado.

Figura 14: Entrada em tabelas - ocultando colunas

Colunas individuais na exibição de dados de tabela podem ser ocultas. Por exemplo, se o campo da chave
primária não precisar estar visível, isso pode ser especificado na tabela na visualização de entrada de
dados clicando com o botão direito do mouse no cabeçalho da coluna. Essa configuração é armazenada
com a GUI. A coluna continua a existir na tabela e sempre pode ser novamente visível.
A entrada na tabela geralmente ocorre da esquerda para a direita usando o teclado com as teclas Tab ou
Enter . Você também pode usar o mouse.
Quando você alcança o último campo de um registro, o cursor automaticamente salta para o próximo
registro. A entrada anterior está comprometida com o armazenamento. O armazenamento adicional
usando Arquivo> Salvar não é necessário e, na verdade, não é possível. Os dados já estão no banco de
dados.

Cuidado Para o HSQLDB, os dados estão na memória de trabalho. Ele só será


transferido para o disco rígido quando o Base for fechado (infelizmente do
ponto de vista de segurança de dados). Se a Base, por algum motivo, não
fechar de forma ordenada, isso pode levar à perda de dados.

Se nenhum dado for inserido em um campo que tenha sido definido anteriormente durante o design da
tabela como obrigatório ( NOT NULL ), a mensagem de erro apropriada será exibida:
Tentativa de inserir nulo em uma coluna não anulável…
A coluna correspondente, a tabela e o comando SQL (conforme traduzido pela GUI) também são exibidos.
É fácil alterar um registro: localize o campo, insira um valor diferente e saia da linha novamente.

Para excluir um registro, selecione a linha clicando em seu cabeçalho (a área cinza à esquerda), clique
com o botão direito do mouse e escolha Excluir linhas .
As funções Classificar, Pesquisar e Filtrar são muito úteis para recuperar registros específicos.

Tabelas de classificação
Figura 16: Classificação Rápida
A opção de ordenação rápida esconde atrás do A → Z e Z → A B uttons. Um campo é selecionado, um
clique no botão e os dados são classificados por essa coluna. A figura mostra uma classificação
decrescente pelo campo Título .
A classificação rápida classifica apenas por uma coluna. Para classificar por várias colunas
simultaneamente, uma função de classificação adicional é fornecida.
O nome do campo da coluna e a ordem de classificação atual são selecionados. Se uma classificação
rápida anterior tiver sido executada, a primeira linha já conterá o nome do campo e a ordem de
classificação correspondentes.
Figura 17:
Classificando
por mais de
uma coluna

Procurando tabelas

As funções para procurar registros são extensas e talvez não sejam a primeira escolha para localizar um
registro específico para usuários acostumados a mecanismos de pesquisa.

Antes de pesquisar, verifique se as colunas pesquisadas são grandes o


suficiente para mostrar corretamente os registros que você encontrará. A
Gorjeta janela de pesquisa permanece em primeiro plano e você não poderá corrigir as
configurações da largura da coluna na tabela subjacente. Para chegar à mesa,
você deve interromper a pesquisa.

A pesquisa assume os termos do campo do qual foi chamada.


Para tornar a pesquisa efetiva, a área de pesquisa deve ser limitada o máximo possível. Seria inútil
pesquisar o texto acima do campo Título no campo Autor . Em vez disso, o nome do campo Título já é
sugerido como o nome único do campo.
Configurações adicionais para a pesquisa podem facilitar as coisas através de combinações específicas.
Você pode usar os espaços reservados SQL normais ( "_" para um caractere variável, "%" para
um número arbitrário de caracteres variáveis, "\" como um caractere de escape, para permitir que
esses caracteres especiais sejam procurados).
Expressões regulares são descritas em detalhes na Ajuda do LibreOffice. Além disso, a Ajuda disponível
para este módulo é bastante esparsa.
Figura 18: Máscara de entrada para uma pesquisa de registro
Figura 19: Limitando a pesquisa de
similaridade

A função de pesquisa de similaridade é útil quando você precisa excluir erros de ortografia. Quanto mais
altos os valores que você definir, mais registros serão exibidos na lista final.
Este módulo de pesquisa é mais adequado para pessoas que sabem, de uso regular, exatamente como
alcançar um determinado resultado. A maioria dos usuários tem mais chances de obter registros usando
um filtro.
O Capítulo 4 deste manual descreve o uso de formulários para pesquisa e como o uso de SQL e macros
pode realizar uma pesquisa de palavras-chave.

Tabelas de filtragem

Você pode filtrar uma tabela rapidamente usando o AutoFiltro . Coloque o cursor em um campo e um
clique no ícone faz com que o filtro assuma o conteúdo desse campo. Apenas os registros são mostrados
para os quais o campo escolhido possui o mesmo conteúdo. A figura abaixo mostra a filtragem de acordo
com uma entrada na coluna Pub_Year .

O filtro está ativo, conforme mostrado pelo ícone de filtro com uma marca de seleção verde. O símbolo do
filtro é mostrado pressionado. Se o botão for clicado novamente, o filtro continuará existindo, mas todos os
registros serão exibidos agora. Então, se você quiser, você sempre pode retornar ao estado filtrado.
Clicar no ícone Remover filtro / ordenar na extrema direita faz com que todos os filtros e classificações
existentes sejam removidos. Os filtros ficam inativos e não podem mais ser recuperados com seus valores
antigos.
Você ainda pode inserir registros normalmente em uma tabela filtrada ou
Gorjeta restrita por uma pesquisa. Eles permanecem visíveis na exibição de tabela até
que a tabela seja atualizada pressionando o botão Atualizar .

O ícone Filtro Padrão abre uma caixa de diálogo na qual você pode filtrar usando vários critérios
simultâneos, semelhante a fazer uma classificação. Se o AutoFiltro estiver em uso, a primeira linha do Filtro
Padrão já mostrará esse critério de filtro existente.
Figura 20:
Filtragem
de Dados
Múltiplos
usando o
Filtro
Padrão

O filtro padrão fornece muitas das funções de filtragem de dados SQL. Os seguintes comandos SQL estão
disponíveis.
Condição da Descrição
GUI
= Igualdade exata; corresponde a like , mas sem nenhum placeholder
adicional
<> Desigual
< Menos que
<= Menor ou igual
> Melhor que
>= Maior que ou igual
gostar Para texto, escrito entre aspas ( '' ); "_" para um caractere
variável, "%" para um número arbitrário de caracteres variáveis

não parece Oposto de como , em SQL NOT LIKE

vazio Nenhuma entrada, nem mesmo um caractere de espaço. No SQL isso é


expresso pelo termo NULL

Não está vazio Oposto de vazio, em SQL NOT NULL

Antes que um critério de filtro possa ser combinado com outro, a seguinte linha deve ter pelo menos um
nome de campo selecionado. Na Figura 20 , a palavra - nenhum - é mostrada em vez de um nome de
campo, portanto a combinação não está ativa. Os operadores de combinação disponíveis são AND e
OR .
O nome do campo pode ser um novo nome de campo ou um nome previamente selecionado.
Mesmo para grandes coletas de dados, o número de registros recuperados pode ser reduzido a um
conjunto gerenciável com filtragem habilidosa usando essas três condições possíveis.
No caso de formulários de filtragem também, existem algumas outras possibilidades (descritas no capítulo
seguinte) que não são fornecidas pela GUI.

Entrada direta usando SQL


A entrada direta de dados usando SQL é útil para inserir, alterar ou remover vários registros com um
comando.

Entrando novos registros


INSERT INTO " Table_name " [( "Field_name" [, ...])]
{VALUES ( "valor do campo" [, ...]) | <Select-Formula>};
Se nenhum "Field_name" for especificado, todos os campos devem ser preenchidos e estar na ordem
correta (conforme estabelecido na tabela). Isso inclui o campo de chave primária incrementado
automaticamente, onde presente. Os valores inseridos também podem ser o resultado de uma consulta
(<Select-Formula>). Mais informações exatas são dadas abaixo.
INSERT INTO " Table_name " ( "Field_name" ) VALUES ('Test');
IDENTIDADE DE CHAMADA ();
Na tabela, na coluna "Field_name", o valor "Test" é inserido. O campo "ID" da chave primária incrementado
automaticamente não é tocado. O valor correspondente para o "ID" precisa ser criado separadamente
usando CALL IDENTITY (). Isso é importante quando você está usando macros, para que o valor desse
campo-chave possa ser usado mais tarde.
INSERT INTO " Table_name " ( "Field_name") SELECT "Other_fieldname" FROM
"Nome_do_outro_tabela" ;
Na primeira tabela, quantos novos registros são inseridos em "Field_name", como estão presentes na
coluna "Other_fieldname" na segunda tabela. Naturalmente, uma fórmula de seleção pode ser usada aqui
para limitar o número de entradas.

Editando registros existentes


UPDATE " Table_name " SET "Field_name" = <Expressão> [, ...] [WHERE
<Expressão> ];
Quando você está modificando vários registros de uma só vez, é muito importante verificar
cuidadosamente o comando SQL que você está digitando. Suponha que todos os alunos de uma turma
devam ser transferidos por um ano:
ATUALIZAÇÃO " Table_name " SET "Year" = "Year" +1
Nada poderia ser mais rápido: todos os registros de dados são alterados com um único comando. Mas é
claro que você deve agora determinar quais os alunos shoul € d não foram afetados por essa mudança.
Teria sido mais simples verificar um campo Sim / Não para a repetição de um ano e, em seguida, subir
apenas os alunos para os quais esse campo não foi verificado:
UPDATE " Table_name " SET "Ano" = "Ano" +1 ONDE "Repetição" = FALSO
Essas condições só funcionam quando o campo em questão só pode receber os valores FALSE e
TRUE ; pode não ser NULL . Seria mais seguro se a condição fosse formulada como WHERE
"Repetition" <> TRUE .
Outras etapas de cálculo também são possíveis com a atualização. Se, por exemplo, mercadorias que
custam mais de US $ 150,00 forem incluídas em uma oferta especial e o preço reduzido em 10%, isso
pode ser feito da seguinte maneira:
UPDATE " Table_name " SET "Preço" = "Preço" * 0,9 ONDE "Preço"> = 150

Excluindo registros existentes


DELETE FROM " Table_name " [WHERE <Expressão> ];
Sem a expressão condicional, o comando
DELETE FROM " Table_name "
exclui todo o conteúdo da tabela.
Por esse motivo, é preferível que o comando seja mais específico. Por exemplo, se o valor da chave
primária for dado, somente esse registro preciso será excluído.
DELETE FROM " Table_name " WHERE "ID" = 5 ;
Se, no caso de um empréstimo, o registro de mídia tiver que ser excluído quando o item for devolvido, isso
pode ser feito usando
DELETE FROM "Table_name" ONDE NÃO "Return_date" IS NULL;
ou alternativamente com
DELETE FROM "Table_name" WHERE "Return_date" NÃO É NULL;

Problemas com esses métodos de entrada de dados


A entrada usando uma tabela sozinha não leva em conta os links para outras tabelas. Isso fica claro a partir
de um exemplo de um empréstimo de mídia.

A tabela Empréstimo consiste em chaves estrangeiras para o item que está sendo emprestado ( Media_ID
) e o leitor correspondente ( Reader_ID ), bem como uma data de empréstimo ( Loan_Date ). Na tabela,
portanto, precisamos inserir no momento do empréstimo dois valores numéricos (número da mídia e
número do leitor) e uma data. A chave primária é inserida automaticamente no campo ID . Se o leitor
realmente corresponde ao número não é aparente a menos que uma segunda tabela para os leitores esteja
aberta ao mesmo tempo. Se o item foi emprestado com o número correto também não é aparente. Aqui, o
empréstimo deve basear-se no rótulo do item ou em outra mesa aberta.
Tudo isso é muito mais fácil de realizar usando formulários. Aqui, os usuários e a mídia podem ser
consultados usando controles de caixa de listagem. Nos formulários, os nomes de usuário e item são
visíveis e seus identificadores numéricos são ocultos. Além disso, um formulário pode ser criado de modo
que um usuário possa ser selecionado primeiro, depois uma data de empréstimo e cada conjunto de mídia
seja atribuído a essa data por número. Em outros lugares, esses números podem ser visíveis com as
descrições de mídia correspondentes exatamente.
A entrada direta em tabelas é útil apenas para bancos de dados com tabelas simples. Assim que você tiver
relações entre tabelas, uma forma especialmente projetada é melhor. Nos formulários, esses
relacionamentos podem ser melhor manipulados usando subformulários ou campos de lista.

Capítulo 4
Formulários
Formulários facilitam a entrada de dados
Os formulários são usados whe n entrada direta em uma tabela é inconveniente, para pegar erros de
entrada de dados imediatamente, ou quando são muitas mesas fazer a gestão directa de dados
impossíveis.

Um formulário na base é uma


estrutura invisível para o usuário
. Serve dentro do Base para
permitir o contato com o banco
de dados.
Nota O que é visível para o usuário é
o conjunto de controles , que
servem para a entrada ou
exibição de texto, números e
assim por diante. Esses
controles são divididos pela GUI
em vários tipos.

Creati ng de f ORMs
A maneira mais simples de criar um formulário é usar o Assistente de Formulário. O uso do Assistente
para criar um formulário é descrito no Capítulo 8, Introdução ao Base, no guia Introdução ao LibreOffice . Th
no capítulo também explica como você pode modificar ainda mais a forma depois de usar o Assistente.
Este manual descreve a criação de um formulário sem usar o Assistente. I t também descreve as
propriedades dos vários tipos de controlos em uma forma.

Um simples f orm
Começamos usando a tarefa Create F orm no Design View na área Forms da janela principal do Base.
Isso chama o Editor de Formulários e a janela Formulário Mostrado no Modo Design é exibida ( Figura 21 ).
A barra de ferramentas de controles de formulário está encaixada no lado esquerdo. A barra de ferramentas
Design Form (Figura 22 ) está encaixada na parte inferior. Se essas barras de ferramentas não aparecerem
automaticamente, use Exibir > Barras de ferramentas para exibi- las. Sem essas barras de ferramentas,
não é possível criar um formulário.
A área em branco mostra uma grade de pontos. Esta grade ajuda você a posicionar os controles com
precisão, especialmente em relação um ao outro. Os símbolos na extremidade direita da barra de
ferramentas Design de formulário mostram que a grade está visível e ativa.
Figura 21: Formulário s
hown no modo Design

Barras de ferramentas para f projeto ORM


Agora vamos criar um formulário na página vazia. Isso pode ser feito de duas maneiras:
•Eu invoco o Navegador de Formulários para configurar um formulário, ou
•Projete os controles de formulário e configure o formulário usando o menu de contexto.
Configurando um f orm com o Form Navigator
Para exibir t ele Forma Navigator, clique o Navigator Forma b utton ( mostrado na F igura 22 ) . Uma janela
aparece (Figura 23 ); ele mostra apenas uma pasta, rotuladas Forms . Este é o nível mais alto da área t h
na estamos editando. S formas everal pode ser acomodado aqui.
Figura 22: Disponíveis b uttons no Form Design t oolbar

Figura 23: Usando o Navegador de Formulários para criar um novo formulário

No Navegador de Formulários (Figura 23 ), clique com o botão direito em Formulários para abrir um menu
de contexto. Escolha Ne w> Form para criar um novo formulário. O o ther c SCOLHA s no menu de
contexto ( aberto no modo de estrutura e Focagem Automatic Control ) correspondem a b uttons na Fig
ure 22 ; Vamos discuti-los mais tarde.
O formulário carrega o nome padrão Form . Você pode alterar o nome dele imediatamente ou mais tarde.
Não tenho significado a menos que você precise acessar alguma parte do formulário usando macros. A
única coisa que você precisa garantir é que dois elementos com o mesmo nome não ocorram no mesmo
nível na árvore de pastas.
O menu de contexto do formulário (mostrado abaixo) fornece o caminho para criar propriedades de
formulário.

Criando um f orm usando um f orm f ield


A barra de ferramentas controles de formulário (Fig ure 24 ) torna disponíveis alguns campos para o
formulário. Os primeiros quatro elementos são idênticos aos da barra de ferramentas Form Design; eles
são seguidos pelos tipos de controle de formulários comumente usados (um controle consiste em um
campo mais um rótulo).
Figura 24: Disponível b uttons sobre o formulário Controla t oolbar
Figura 26: Menu de contexto para
formulário

Agora você pode criar o formulário clicando com o botão direito e usando o menu de contexto para o
controle (Figura26 ).
Selecione t ele Formar opção de menu (em destaque na ilustração) para definir as propriedades para o
formulário que acabou de criar. O formulário tem o nome padrão Form.

P ropriedades de formulário
Quando as propriedades do formulário são chamadas usando o menu de contexto no Navegador de
formulários ou no menu de contexto de um controle de formulário, uma janela Propriedades do formulário é
exibida. Tem três guias: Geral , Dados e Eventos.
Guia Geral
Aqui você pode alterar o nome do formulário. Além disso, existem possibilidades de design que não têm
significado dentro da Base. Eles mostram apenas as possibilidades mais gerais de design usando um
editor de formulários; quando você criar um formulário da Web, precisará usá-los.
URL : destino para os dados.
Quadro : Seção do site de destino a ser abordada, quando necessário.
Codificação de envio : além da codificação de caracteres normal para transmissão para o URL, você
pode especificar aqui codificação de texto e codificação de várias partes (por exemplo, para
transferência de dados ).
Tipo de submissão : GET (visível através do URL anexado ao nome do arquivo; você pode ver isso
muitas vezes na web, se você usar um motor de busca) ou POST (não visível; adequado para grandes
volumes de dados).
Guia Dados

Para criar formulários internos no Base, essa é a guia mais importante. Aqui você pode definir as
seguintes propriedades iniciais para o formulário:
Tipo de conteúdo : C entre os comandos Tabela , Consulta e SQL . Enquanto Tabela sempre pode ser
usado para entrada de dados em uma forma, isso nem sempre é o caso de consulta (para mais
informações, consulte o Capítulo 5, QUER s , neste livro) ou a entrada directa de um comando SQL.
Aqui estamos lidando com uma consulta que não é visível no contêiner de consulta do Base, mas tem,
em princípio, a mesma estrutura.
Conteúdo : De acordo com a escolha da Tabela ou Consulta acima, todas as tabelas e consultas
disponíveis são listadas. Se um comando SQL for criado, você poderá chamar o Editor de Consultas
usando o botão com os três pontos à direita do campo Conteúdo.
Analy z comando e SQL : Se a um nálise de comandos SQL não deve ser permitido (porque, por
exemplo, você está usando o código que a GUI não pode mostrar corretamente), você deve escolher
Não aqui. No entanto, isso impedirá a forma de acessar os dados subjacentes usando um filtro ou uma
classificação.
Filtro : aqui você pode definir um filtro. Para obter ajuda, clique no botão à direita do campo. Veja
também C apítulo 3, Tabelas, neste livro .
Ordenar : aqui você pode configurar uma classificação para seus dados. Para obter ajuda, clique no
botão à direita do campo. Veja também C apítulo 3, Tabelas.
Permitir adições : a entrada de novos dados deve ser permitida? Por padrão, isso é definido como Sim .
Permitir modificações : a edição dos dados deve ser permitida? Por padrão, também sim .
Permitir exclusões : a exclusão de dados também é permitida por padrão.
Adicionar apenas dados : se você escolher essa opção, um formulário vazio será sempre exibido. Não
haverá acesso a dados existentes, que não podem ser editados nem visualizados.
Barra de navegação : A aparência da barra de navegação na parte inferior da tela pode ser ativada ou
desativada. Também existe a possibilidade, quando você tem um subformulário, sempre mostrar a
Barra de Navegação para o formulário principal, para que a ativação desta barra de ferramentas afete
apenas o formulário principal. Essa configuração para a barra de navegação não é relevante para a
barra de ferramentas de navegação interna que pode ser adicionada como um controle de formulário,
se necessário.
Ciclo : A opção D efault para bancos de dados de base é que, após a entrada no último campo em um
formulário, a tecla T ab leva você ao primeiro campo do próximo registro - ou seja, um novo registro
será criado. Para bancos de dados, isso tem o mesmo efeito que Todos os registros . Por outro lado, se
você escolher Registro ativo , o cursor se moverá somente dentro do registro; quando chegar ao último
campo, ele retornará ao primeiro campo nesse registro. Página atual refere-se particularmente a
formulários HTML. O cursor salta do final de um formulário para o próximo formulário nessa página
mais abaixo.
Guia Eventos

Eventos podem acionar macros. Um clique no botão à direita (…) permite que as macros sejam
vinculadas ao evento.
Redefinir : o formulário é esvaziado de todas as novas entradas que ainda não foram salvas.
Antes de enviar : Antes dos dados do formulário serem enviados. Isso só é significativo para
formulários da Web.
Ao carregar : somente ao abrir o formulário. Não ao carregar um novo registro no formulário.
Recarregamento : ocorre quando o conteúdo do formulário é atualizado, por exemplo, usando um botão
na barra de navegação.
Descarga : T sua opção parece não funcionar. Seria esperado que se referisse ao fechamento do
formulário.
Gravar ação : Isso inclui, por exemplo, armazenamento usando um botão. Nos testes, essa ação
regularmente se duplica; as macros são executadas duas vezes em sucessão.
Mudança de registro : a abertura de um formulário conta como uma mudança de registro. Sempre que
um registro muda para outro dentro do formulário, essa ação também ocorre duas vezes. As macros
são, portanto, executadas duas vezes em sucessão.
Parâmetros de preenchimento: essa macro será executada se uma consulta de parâmetro precisar ser
chamada em um subformulário, mas, por algum motivo, o parâmetro não é transmitido corretamente do
formulário principal. Se este evento não for detectado, uma consulta de parâmetro seguirá o
carregamento do formulário.
Erro: Este evento não pôde ser reconstruído.

Propriedades de c ONTROLOS
Depois que um formulário é criado, ele pode ser preenchido com controles visíveis. Alguns controles
permitem que o conteúdo do banco de dados seja exibido ou que os dados sejam inseridos no banco de
dados. Outros controles são usados exclusivamente para navegação, pesquisa e execução de comandos
(interação). Alguns controles servem para retrabalho gráfico adicional do formulário.
Entrada de dados e exibição de dados
Ao controle Usar
Campo de texto Entrada de texto
Campo numérico Inserindo números
Campo de data Inserindo datas
Campo de tempo Entrando vezes
Campo de moeda Entrada numérica pré-formatada para moeda
Campo formatado Exibição e entrada com formatação adicional, por exemplo, usando
unidades de medida
Caixa de listagem Escolhendo entre várias possibilidades diferentes, também para
transferir para o banco de dados de valores diferentes daqueles
exibidos
Caixa combo Semelhante a um campo de lista, mas com apenas o valor exibido
transferido ou você pode inserir novos valores manualmente
Caixa de seleção Sim / Não Campo
Botão Opções Botão r adio; um llows que você escolha a partir de um pequeno
número de possibilidades
Controle de imagem Exibição de imagens de um banco de dados e entrada de imagens
em um banco de dados por meio de uma seleção de caminho
Campo padrão Entrada em uma máscara predefinida; limita as possibilidades de
entrada a combinações de caracteres específicas
Controle de mesa Módulo de entrada universal, que pode exibir uma tabela inteira.
Integrado neste controle estão muitos dos controles acima
desenhar
Ao controle Usar
Campo de etiqueta Indo para o formulário, descrição de outros controles
Caixa de grupo Um quadro ao redor, por exemplo, um conjunto de botões de opção
Interação
Ao controle Usar
Botão Botão com etiqueta
Botão de imagem Como um botão, mas com um gráfico adicional exibido nele
Barra de navegação Barra de ferramentas muito semelhante à da extremidade inferior da
tela
Seletor de arquivos Para selecionar arquivos, por exemplo, para fazer upload em um
formulário HTML - não mais descrito
Caixa de rotação Só pode ser usado com uma macro - não descrita posteriormente
Barra de rolagem Só pode ser usado com uma macro - não descrita posteriormente

Configurações padrão para muitos controles


Como nos formulários, as propriedades são agrupadas em três categorias: Geral, Dados e Eventos. Geral
compreende tudo o que é visível para o usuário. A categoria de dados especifica a ligação a um campo no
banco de dados. A categoria Eventos controla as ações, que podem ser vinculadas a alguma macro. Em
um banco de dados sem macros, essa categoria não desempenha nenhum papel.
Guia Geral

O nome de um controle deve


ser exclusivo dentro do
formulário - usado para acesso
usando macros.

O campo tem um rótulo? Isso


agrupa o campo e o rótulo
juntos.

Campos não habilitados não


podem ser usados e estão
esmaecidos. Útil para controlar
o uso de macros. (Exemplo: Se
o Campo 1 contiver um valor, o
Campo 2 não deverá conter um;
o Campo 2 será desativado.)

Normalmente Y es ; campos
invisíveis podem ser usados
como armazenamento
intermediário, por exemplo, na
criação de campos de
combinação com macros. Ver
C apítulo 9, macros.

Sim excluirá qualquer


modificação do valor. Isso é útil,
por exemplo, para uma chave
primária gerada
automaticamente.
Às vezes, é útil imprimir uma
página de um formulário em vez
de um relatório separado. Neste
caso, nem todos os campos
podem ser obrigados a
aparecer.

Dentro de um formulário, a tecla


Tab é normalmente usada para
navegação.
Um campo que é somente
leitura não precisa de uma
parada de tabulação; pode ser
pulado.

O campo tem uma parada de


tabulação? Aqui a seqüência de
ativação dentro do formulário é
especificada.

Ancoragem de gráficos dentro


de um campo de texto.

Posição do canto superior


esquerdo em relação ao lado
esquerdo do formulário.

Posição do canto superior


esquerdo em relação ao topo do
formulário.

Largura do campo

Altura do campo

Fonte, tamanho da fonte e


efeitos de fonte podem ser
definidos aqui.

Alinhamento. Aqui, a entrada de


texto é justificada à esquerda.

Alinhamento vertical: padrão |


Topo | Meio | Inferior.

Cor de fundo do campo de


texto.

Enquadramento: Sem moldura |


3D-Look | Plano.

Se houver um quadro, sua cor


pode ser definida aqui.

Texto realçado perde o


destaque quando o campo de
texto perde o foco.

Usado para informações a


serem lidas por macros. Ver C
apítulo 9, macros.

Aparece como uma dica de


ferramenta quando o mouse é
passado sobre o campo de
texto.

Aponta para um arquivo de


ajuda, útil principalmente para
HTML. Pode ser chamado
usando F1 quando o foco está
no campo.

Além disso, numéricos, campos de data, etc, possuem as seguintes propriedades.


Com o teste ativado, somente
números e pontos decimais
podem ser inseridos.

Nunca permite alterações


usando a roda do mouse;
Quando selecionado, permite
tais alterações quando o campo
é selecionado e o mouse está
sobre o campo; Alway s
significa sempre que o mouse
está sobre o campo.

Um símbolo de rotação é
incorporado no lado direito do
campo.

Se uma seta de rotação é


pressionada e mantida, isso
determina se a entrada na caixa
deve ser incrementada além do
próximo valor.

Determina o atraso mínimo


após o pressionamento de um
botão do mouse que aciona a
repetição.

Guia Dados

Campo de dados : aqui você cria a ligação com a tabela na qual o formulário é baseado.
A string vazia é NULL : se uma string vazia deve ser tratada como (NULL) ou o conteúdo simplesmente
excluído.
Entrada obrigatória : essa condição deve corresponder à da tabela. A GUI solicitará a entrada se o
usuário não tiver inserido um valor.
Filtrar proposta : quando os dados devem ser filtrados, o conteúdo desse campo é armazenado
temporariamente como uma sugestão. Cuidado - com grandes conteúdos, essa opção pode usar muito
armazenamento.
Guia Eventos

Alterado : este evento ocorre quando um controle é modificado e depois perde o foco.
Texto modificado : refere-se ao conteúdo, que pode, de fato, ser texto, numérico ou o que for. Ocorre
depois que cada caractere adicional é inserido.
Ao receber foco : O cursor entra no campo. Sob nenhuma circunstância a macro deve criar um diálogo
de mensagem na tela; clicando em tal diálogo faz com que o campo de formulário perca o foco e, em
seguida, recupere-o, acionando a macro novamente. Um loop é criado e só pode ser quebrado usando
o teclado.
Ao perder o foco : o cursor sai do campo. Isso pode levar ao mesmo tipo de interação quando o
tratamento do evento faz com que ele ocorra novamente.
Tecla : Refere-se ao teclado. Por exemplo, uma tecla é pressionada quando você percorre o formulário
usando a tecla Tab. Isso faz com que um campo receba o foco. Então a chave é liberada.
Mouse : autoexplicativo; Estes eventos só acontecem se o mouse estiver ou já estiver dentro do
campo ("outside" corresponde ao javascript onMouseOut).
Redefinir : o formulário é esvaziado de todos os dados. Isso acontece, por exemplo, ao iniciar um novo
registro. Quando um formulário é carregado pela primeira vez, os dois eventos Antes de redefinir e
Após a redefinição ocorrem em sucessão, antes que o formulário esteja disponível para entrada.
Atualização : Se o evento estiver vinculado a um controle de formulário, a atualização ocorre quando o
foco é perdido e pula para outro controle de formulário, depois de alterar o conteúdo do campo.
Alterações no formulário são aceitas e exibidas. Quando um formulário é fechado, os dois eventos
Antes da atualização e Após a atualização ocorrem em sucessão.

Campo de texto
Assim como as propriedades definidas na página 70 , os campos de texto podem ter as seguintes
propriedades adicionais:
Guia Geral

Quando esse valor é 0, a


entrada não é permitida.
Normalmente, o comprimento
do campo do banco de dados
ao qual o campo de texto
corresponde é usado aqui.

O texto padrão deve ser


colocado em um campo vazio?
Este texto deve ser excluído se
qualquer outra entrada tiver que
ser feita com sucesso.

Tipos possíveis: linha única |


Multi-linha | Multi-linha com
formatação (os dois últimos
diferem no comportamento de
tabulação e, além disso, um
campo de padrão não pode ser
vinculado a um banco de
dados). O alinhamento vertical
não está ativo para campos
com várias linhas.

Unix ou Windows? Isso afeta


principalmente os finais de
linha. Internamente, as linhas
do Windows terminam com
dois caracteres de controle (CR
e LF).

Apenas para campos com


várias linhas: Horizontal |
Vertical | Ambos.

Ativo apenas para campos de


linha única. Altera os caracteres
para ver apenas pontos.

Guia Dados
N ada de significância.
Guia Eventos
N ada de significância.

Numérico f ield
Além das propriedades já descritas, existem as seguintes propriedades:
Guia Geral

Valor mínimo para o campo.


Deve concordar com o valor
mínimo definido na tabela.

Valor máximo.

Incremento de rolagem ao usar


a roda do mouse ou dentro de
uma caixa de rotação.

Valor exibido quando um novo


registro está sendo criado.

Número de casas decimais,


definido como 0 para inteiros.
Separador para milhares,
geralmente uma vírgula .

Guia Dados
Não há verificação se um campo pode ser NULL. Se não houver entrada, o campo será NULL e não 0.
Nenhuma proposta de filtro é oferecida.
Guia Eventos
O evento "Changed" está ausente. As alterações devem ser tratadas usando o evento "Texto
modificado" (o texto da palavra não deve ser usado literalmente aqui).

Campo de data
Além das propriedades descritas na página 70 , deve-se observar o seguinte.
Guia Geral

Valor mínimo para o campo,


selecionável usando um
calendário suspenso.

Valor máximo.

Forma abreviada como


10.02.12 ou vários formulários
usando '/' em vez de '.'
ou '-' no estilo americano.

Aqui você pode inserir uma


data literal, mas infelizmente
não (ainda) a data atual (Hoje)
no momento em que o
formulário é aberto.

Um calendário mensal para


selecionar datas pode ser
incluído.

Guia Dados
Não há verificação se um campo pode ser NULL. Se não houver entrada, o campo será NULL e não 0.
Nenhuma proposta de filtro é oferecida.
Guia Eventos
O evento "Changed" está ausente. As alterações devem ser tratadas usando o evento "Texto
modificado" (o texto da palavra não deve ser usado literalmente aqui).

Campo de tempo
Além das propriedades listadas na página 70 , os seguintes recursos estão disponíveis.
Guia Geral

Valor mínimo para o campo,


por padrão, definido como 0.

Valor máximo, por padrão,


definido como 1 segundo antes
das 24:00.

Forma abreviada sem


segundos, formato longo com
segundos e também formatos
de 12 horas com AM e PM.

Você pode definir um horário


fixo, mas infelizmente não
(ainda) o tempo real de salvar o
formulário.

Guia Dados
Não há verificação se um campo pode ser NULL. Se não houver entrada, o campo será NULL e não 0.
Nenhuma proposta de filtro é oferecida.
Guia Eventos
O evento "Changed" está ausente. As alterações devem ser tratadas usando o evento "Texto
modificado" (o texto da palavra não deve ser usado literalmente aqui).

Campo de moeda
Além das propriedades já listadas na página 70 , os seguintes recursos estão disponíveis:
Guia Geral
Min. valor, máx. valor, Incremento, Valor padrão, Casas decimais e Milhares de separadores.
correspondem às propriedades gerais listadas na página 75 . Além destes, existe apenas:
O símbolo é exibido, mas não
armazenado na tabela
subjacente ao formulário.

O símbolo deve ser colocado


antes ou depois do número?

Guia Dados
Não há verificação se um campo pode ser NULL. Se não houver entrada, o campo será NULL e não 0.
Nenhuma proposta de filtro é oferecida.
Guia Eventos
O evento "Changed" está ausente. As alterações devem ser tratadas usando o evento "Texto
modificado" (o texto da palavra não deve ser usado literalmente aqui).

Formatado f ield
Além das propriedades listadas na página 70 , os seguintes recursos são oferecidos:
Guia Geral
Os valores mínimo e máximo e o valor padrão dependem da formatação. Atrás do botão de
Formatação i é um campo flexível t h a torna mais moeda e campos numéricos desnecessário. Ao
contrário de um campo de moeda simples, um campo de padrão pode mostrar somas negativas em
vermelho.
O botão à direita com os três
pontos fornece uma opção de
formatos numéricos, como
você costuma fazer no Calc.

Entre os formatos numéricos podem ser vistos, ao lado de Data, Hora, Moeda ou formato numérico
normal, possibilidades de usar campos com uma unidade de medida como kg (veja a Figura 27 ). Veja
também a Ajuda geral sobre códigos de formato numérico.
Guia Dados
Nada de especial para reportar.
Guia Eventos
O evento "Changed" está ausente. As alterações devem ser tratadas usando o evento "Texto
modificado" (o texto da palavra não deve ser usado literalmente aqui).

Figura 27: Formatado f ield com opções numéricas gerais

Lista b boi
Quando uma caixa de listagem é criada, o assistente L ist B ox aparece por padrão. Esta aparência
automático pode ser comutado o f f se necessário, utilizando o Assistentes S / N O FF ( mostrado na Fig
ure 24 ).
bruxo
O formulário já está definido. Está vinculado a uma tabela chamada Empréstimos . Uma caixa de
listagem mostra ao usuário dados diferentes do que é realmente transmitido para a tabela . Esses
dados geralmente vêm de outra tabela no banco de dados e não da tabela à qual o formulário está
vinculado.
A tabela Empréstimos i s suppos ed para mostrar quais Reader tem Borro casar w mídia hich. No
entanto, esta tabela não armazena o nome do leitor, mas a chave primária correspondente da tabela do
Reader . É, portanto, a tabela Leitor t chapéu fo rm s a base para a caixa de listagem.

O campo Sobrenome da tabela do Leitor deve ser visível na caixa de listagem. Isso serve como o
campo de exibição .

O campo Reader_ID o ccurs na tabela Empréstimo que serve de base ao formulário. Esta tabela é
descrita aqui como a tabela Value . O ID da chave primária da tabela do Reader deve estar vinculado a
este campo. A tabela do Reader é descriçada aqui como a tabela List .
A caixa de listagem agora foi criada completa com dados e configuração padrão e está totalmente
funcional.
Além das propriedades listadas na página 70 , os seguintes recursos estão disponíveis.
Guia Geral
As entradas da lista já foram
definidas usando o Assistente.
Aqui você pode adicionar mais
entradas que não são de
nenhuma tabela no banco de
dados. Listar entradas aqui
significa as entradas visíveis,
não aquelas que o formulário
transmitirá para a tabela.

Se o campo não estiver


especificado como suspenso,
as setas de rolagem aparecerão
no lado direito da caixa de
listagem quando o formulário for
carregado. O campo de lista
automaticamente se torna um
campo de várias linhas, no qual
o valor real selecionado é
destacado.

Se o campo for suspenso, essa


propriedade fornecerá o número
máximo visível de linhas. Se o
conteúdo se estender por mais
linhas, uma barra de rolagem
aparecerá quando a lista for
encerrada.

Mais de um valor pode ser


selecionado? No exemplo
acima, isso não é possível, pois
uma chave estrangeira está
sendo armazenada.
Normalmente, essa função não
é usada para bancos de dados,
pois cada campo deve conter
apenas um valor. Se
necessário, as macros podem
ajudar na interpretação de
várias entradas no campo de
lista.

Como o botão desativado deixa


claro, uma seleção padrão faz
pouco sentido no contexto de
uma ligação com uma tabela de
banco de dados, conforme
criado pelo Assistente de
campo de lista. Pode bem
acontecer que o registro
correspondente à seleção
padrão na tabela de exemplo
Readers não esteja mais
presente.

Guia Dados
Além das propriedades de dados usuais, Campo de dados e Entrada necessária , existem propriedades
significativas que afetam a ligação entre os dados exibidos e os dados a serem inseridos na tabela
subjacente ao formulário.
Tipo de conteúdo da lista : Valuelist | Tabela | Consulta | SQL | SQL [nativo] | Campos de mesa
Lista o conteúdo valueList : Se a lista ENTR s foram criados unde r geral , os valores correspondentes
a serem armazenados são inseridos aqui. O conteúdo da lista é carregado com itens individuais
separados por Shift - Enter . O campo Listar conteúdo mostra-os como " Valor1 "
; " Valor2 " ; " Valor3 " ... A propriedade Campo
Vinculado está inativa .

Listar o conteúdo Tabela : Aqui, uma das tabelas do banco de dados pode ser selecionada. No entanto,
isso raramente é possível, pois exige que o conteúdo da tabela seja estruturado de forma que o primeiro
campo da tabela contenha os valores a serem exibidos no campo de lista e um dos seguintes campos
contenha a chave primária que a tabela subjacente usa como uma chave estrangeira. A posição deste
campo dentro da tabela é especificada em Campo Limite , onde a numeração começa com 0 para o
primeiro campo da tabela do banco de dados . Mas este 0 é reservado para o valor exibido, no
exemplo acima o sobrenome , enquanto o 1 se refere ao campo ID .
Listar conteúdo Consulta : Aqui, uma consulta é criada primeiro e armazenada separadamente. A
criação dessas consultas é descrita no Capítulo 5, Consultas. Usando a consulta, é possível mover o
campo ID da primeira posição na tabela subjacente para a segunda posição, aqui representada pelo
campo acoplado 1.
Listar o conteúdo SQL : O Assistente de Caixa de Lista preenche este campo. A consulta construída
pelo Assistente se parece com isso:
A consulta é a mais simples possível. O campo
de sobrenome o ccurs na posição 0, o campo
de ID na posição 1. Ambos são lidos da tabela
do Reader. Como o campo acoplado é o Campo
1, essa fórmula SQL funciona. Aqui deve ser adicionado ORDER BY "LastName" ASC . Então
você não precisa percorrer a lista para encontrar alguém. A n um problema dicional pode ser, que
LastName poderia ser o mesmo para mais de um leitor. Portanto, FirstName deve ser adicionado na
exibição da caixa de listagem. W galinha existem leitor s com o mesmo sobrenome e o mesmo
NomePróprio , a chave principal ID também deve ser mostrado. Vejo C apítulo 5, Consultas, para obter
informações sobre como isso funciona.
Listar conteúdo SQL [Nativo] : A fórmula SQL é inserida diretamente, não usando o Assistente. Base
não avalia a consulta. Isso é adequado quando a consulta contém funções que talvez não sejam
compreendidas pela GUI Base. Nesse caso, a consulta não está marcada para erros. Mais
informações sobre o modo SQL direta pode ser encontrado em C apítulo 5, Consultas.
Listar os campos de tabela de conteúdo : Aqui os nomes de campo de uma tabela são listados, não seu
conteúdo. Para a tabela do Reader , o conteúdo da lista seria " ID", "Nome próprio", "Apelido",
"Bloqueio", "Gender_ID".
Guia Eventos
Além dos eventos padrão, os seguintes eventos estão disponíveis:
Executar ação : Se um valor for escolhido pelo teclado ou pelo mouse , a caixa de listagem executará
essa ação .
Status do item alterado : pode ser a alteração do conteúdo exibido de uma caixa de listagem por meio
do uso do botão suspenso. Também pode ser um clique no botão suspenso do campo.
Erro : infelizmente, este evento não pode ser reconstruído para caixas de listagem.

Caixa combo
Assim que uma caixa de combinação é criada, um Assistente aparece por padrão, assim como com uma
caixa de listagem. Este comportamento automático pode ser desactivada, se necessário, utilizando o
Assistentes S N / S ff botão ( ver Fig ure 24 ).
Caixas de combinação gravam o texto selecionado diretamente na tabela subjacente ao formulário.
Portanto, o exemplo a seguir mostra a tabela vinculada ao formulário e a selecionada para o controle como
a tabela do Reader.
bruxo

Novamente o formulário é predefinido, desta vez com a tabela do Reader. Como os dados a serem exibidos
na caixa de combinação também devem ser armazenados nesta tabela, a fonte selecionada para os dados da
lista é da mesma forma a tabela do Reader.
Na tabela do Reader, o campo FirstName ocorre. Isso deve ser exibido na caixa de combinação.

Em um banco de dados, parece haver pouco sentido em não armazenar o valor de uma caixa de
combinação dentro de um campo. Queremos ler os nomes fornecidos da tabela do Reader e também
disponibilizá-los para novos leitores, para que não seja necessário criar novos registros para um
determinado nome que já exista no banco de dados. A caixa de combinação mostra o primeiro nome e a
entrada de texto não é necessária.
Se um novo valor precisar ser inserido, isso pode ser feito facilmente em uma caixa de combinação, pois a
caixa mostra exatamente o que está entrando na tabela subjacente do formulário.
Além das propriedades mostradas na página 70 e descritas para caixas de listagem, os recursos a seguir
estão disponíveis.
Guia Geral
Durante a entrada de novos
valores, uma lista de valores
correspondentes (se houver) é
exibida para uma possível
seleção.

Guia Dados

Os campos de dados estão de acordo com as configurações padrão existentes e as configurações de


uma caixa de listagem. O comando SQL, no entanto, mostra um recurso especial:
SELECT DISTINCT "FirstName" FROM "Reader"
Adicionar a palavra-chave DISTINCT garante que nomes duplicados sejam mostrados apenas uma
vez. No entanto, a criação usando o Assistente mais uma vez torna impossível que o conteúdo seja
classificado.
Guia Eventos
Os eventos correspondem àqueles para uma caixa de listagem.

Caixa de seleção
A caixa de seleção aparece imediatamente como uma combinação de um campo de caixa de seleção e
um rótulo para a caixa.
Além das propriedades descritas na página 70 , os seguintes recursos estão disponíveis.
Guia geral

O rótulo dessa caixa é exibido


por padrão à direita da caixa.
Além disso, você pode vinculá-
lo a um campo de rótulo
separado.
Aqui, dependendo da opção no
campo Tri-state, até três
possibilidades estão
disponíveis: Não selecionado |
Selecionado | Não definido .
Não definido corresponde a
uma entrada NULL na tabela
subjacente ao formulário.

Por padrão, o rótulo não está


dividido. O rótulo será truncado
se o campo não for grande o
suficiente.

Aqui você pode especificar um


gráfico em vez de ou além do
rótulo. Você deve observar que
esses gráficos não estão
vinculados ao documento *
.odb por padrão. Para
pequenos gráficos, é útil
incorporar o gráfico e não
vinculá-lo.

Se você escolheu usar um


gráfico, seu alinhamento com o
rótulo pode ser definido aqui.

Por padrão, as caixas de


seleção têm apenas dois
estados: Selecionado (Valor: 1)
e Não selecionado (Valor: 0).
Com Tri-state, uma definição de
campo Vazio (NULL) é
adicionada.

Guia Dados

A caixa de seleção pode receber um valor de referência. No entanto, apenas os valores de 1 (para On)
ou 0 (para Off) podem ser transferidos para o campo de dados subjacente (as caixas de verificação
atuam como campos para a escolha de Yes e No ) .
Guia Eventos
Os campos "Alterado", "Texto modificado". "Antes de atualizar" e "Após a atualização" estão todos
ausentes.
Os campos adicionais para uma caixa de seleção são "Executar ação" (consulte Caixa de listagem) e
"Status do item alterado" (corresponde a "Alterado").

Botão de opção
O botão de opção é semelhante à da caixa de verificação descrita acima, com excepção das suas g
propriedades eral e a sua forma externa (redondo).
Quando vários botões de opção no formulário estão vinculados ao mesmo campo da tabela, somente uma
das opções pode ser selecionada.
Guia Geral
O botão de opção é projetado
para ser usado em grupos.
Uma das várias opções pode
ser selecionada. É por isso que
um nome de grupo aparece
aqui, sob o qual as opções
podem ser endereçadas.
Guia Dados
Veja abaixo da caixa de seleção. Aqui, no entanto, os valores de referência inseridos são realmente
transferidos para o campo de dados.
Guia Eventos
Veja abaixo da caixa de seleção.

Imagem c ontrole
Um controle de imagem lida com a entrada e exibição de material gráfico no banco de dados. O campo de
dados subjacente deve ser um campo binário.
A entrada em um controle de imagem ocorre por um clique duplo com o mouse para abrir uma caixa de
diálogo de seleção de arquivos ou por um clique com o botão direito do mouse para escolher se um gráfico
existente deve ser excluído ou substituído.
Um controle gráfico por padrão não possui uma parada Tab.
Além das propriedades descritas na página 70 , as seguintes características são beneficie um ble.
Guia geral

O gráfico selecionado aqui é


mostrado apenas dentro do
controle, enquanto o formulário
está sendo editado. Não tem
significado para entrada
posterior.

Não : a imagem não será


ajustada no campo. Se for
muito grande, o campo
mostrará uma janela para a
imagem. A imagem não está
distorcida.
Taxa de manutenção : a
imagem é ajustada ao controle,
mas não é distorcida (relação
de aspecto preservada).
Autom. Tamanho : A imagem é
ajustada ao controle e pode ser
mostrada de forma distorcida.

Guia Dados
Nada mais a relatar.
Guia Eventos
Os eventos "Alterado", "Texto modificado", "Antes de atualizar" e "Após a atualização" estão faltando.

Padrão f ield
Uma máscara de entrada é usada para controlar a entrada no campo. Os caracteres são pré-especificados
para posições específicas, determinando as propriedades dos caracteres inseridos. Os caracteres
predefinidos são armazenados junto com os inseridos.
Além das propriedades descritas na página 70 , os seguintes recursos estão disponíveis.
Guia Geral
Isso determina quais
caracteres podem ser
inseridos.

É isso que o usuário do


formulário vê.

O conteúdo a seguir foi obtido da Ajuda do LibreOffice:


O comprimento da máscara de edição determina quantos caracteres podem ser inseridos. Se a entrada
do usuário não corresponder à máscara, a entrada será rejeitada ao sair do controle. Os seguintes
caracteres estão disponíveis para definir a máscara de edição.
Personagem Significado
eu Uma constante de texto. Esta posição não pode ser editada. O caractere
real é exibido na posição correspondente na máscara literal.
uma Representa qualquer uma das letras az / AZ. Letras maiúsculas não são
convertidas em minúsculas.
UMA Representa qualquer uma das letras AZ. Se forem inseridas letras
minúsculas, elas serão convertidas automaticamente para maiúsculas.
c Representa qualquer um dos caracteres az / AZ mais os dígitos 0-9.
Letras maiúsculas não são convertidas em minúsculas.
C Representa qualquer uma das letras AZ mais os dígitos 0-9. Se forem
inseridas letras minúsculas, elas serão convertidas automaticamente para
maiúsculas.
N Apenas os dígitos 0-9 podem ser inseridos.
x Todos os caracteres imprimíveis são permitidos.
X Todos os caracteres imprimíveis são permitidos. Se forem inseridas letras
minúsculas, elas serão convertidas automaticamente para maiúsculas.
Assim, por exemplo, você pode definir a máscara literal como "__ / __ / 2012" e a máscara de edição
como "NNLNNLLLLL", para permitir que o usuário insira apenas quatro caracteres para uma data.
Guia Dados
Nada mais a relatar.
Guia Eventos
O evento "Changed" está ausente.

Controle de mesa
Este é o controle mais abrangente. Ele fornece uma tabela, que pode ser fornecida com controles para
colunas individuais. Isso não apenas permite que os dados reais sejam visualizados durante a entrada,
mas também os dados inseridos anteriormente, sem a necessidade de usar a barra de navegação para
percorrer os registros.
Nem todos os campos possíveis em um formulário podem ser selecionados para um campo de controle de
tabela. Botões de pressão, botões de imagem e botões de opção não estão disponíveis.
O Table Control Wizard monta em uma janela os campos que aparecerão depois na tabela.

No controle, a tabela Empréstimos está disponível para edição. Além do campo ID (chave primária) e do
campo Media_ID_BC (entrada de mídia usando um scanner de código de barras), todos os campos devem
ser usados no controle.
O controle de tabela criado anteriormente deve agora ser desenvolvido, para permitir a entrada na tabela
básica . Para campos como Reader_ID ou Media_ID , seria mais útil poder escolher o leitor ou a mídia
diretamente, em vez de um número que representa o leitor ou a mídia. Para esse propósito, controles como
caixas de listagem podem ser colocados dentro do controle de tabela. Isso é declarado mais tarde. A
formatação do campo Extensão com duas casas decimais certamente não foi planejada.
Figura 28: Saída do Assistente
de Controle de Tabela

Além das propriedades listadas na página 70 , os seguintes recursos estão disponíveis.


Guia geral
Altura de linhas individuais.
Sem valor aqui, a altura é
automaticamente ajustada ao
tamanho da fonte. Os campos
de texto de várias linhas são
exibidos como linhas simples a
serem roladas.

Como nas tabelas, a borda


inferior do controle mostra o
número do registro e os auxílios
à navegação.

Por padrão, há um marcador de


registro na borda esquerda do
controle. Indica o registro atual.
Você pode usar o marcador de
registro para acessar a função
de exclusão de todo o registro.
Guia Dados
Como esse é um campo que não contém dados, mas gerencia outros campos, não há propriedades de
dados.
Guia Eventos
Os eventos "Alterado" e "Texto modificado" estão faltando. O evento "Erro ocorrido" é adicionado.

Campo de etiqueta
Além das propriedades descritas na página 70 , os seguintes recursos estão disponíveis.
Guia Geral
Por padrão, um rótulo não é
empacotado. Se for muito longo
para o campo, ele será
truncado. Cuidado: quebra de
linha não reconhece espaços,
portanto, se o campo for muito
pequeno, pode ocorrer uma
quebra em uma palavra.
Guia Dados
Nenhum.
Guia Eventos
O campo de etiqueta reage apenas aos eventos que estão conectados com o mouse, uma chave ou o
foco.

Caixa de grupo
Uma caixa de grupo agrupa graficamente vários controles e fornece a eles um rótulo coletivo.
Se uma caixa de grupo for criada com os Assistentes ativos, o Assistente parte da suposição de que vários
botões de opção ocorrerão juntos nesse quadro.

Este formulário é baseado na tabela do Reader. Estamos lidando com a escolha do gênero. As entradas
são os rótulos dos botões de opção.

Aqui a opção padrão é "feminino". Se não houver nenhum campo padrão, a entrada padrão na tabela
subjacente será NULL.
O Assistente dá aos botões de opção valores separados por padrão, aqui 1 para fem a le e 2 para m ale.
Esses valores correspondem aos exemplos de campos de chave primária na tabela Gênero.
O valor selecionado ao clicar em um botão de opção é transferido para o campo Gender_ID dos leitores da
tabela abaixo do formulário . Desta forma, a tabela Readers é fornecida com a chave estrangeira
correspondente da tabela Gender usando o botão de opção.

O grupo de botões de opção recebe uma caixa de grupo (quadro) com o rótulo Gênero.

Se a fêmea for selecionada na forma ativa , o macho é desmarcado. Essa é uma característica dos botões
de opção vinculados ao mesmo campo na tabela subjacente. No exemplo mostrado acima, os botões de
opção substituem uma caixa de listagem de dois elementos.
Além das propriedades descritas na página 70 , os seguintes recursos estão disponíveis.
Guia Geral
O rótulo pode ser alterado de seu valor padrão. No momento, as propriedades do quadro (espessura da
linha, cor da linha) não podem ser alteradas, mas você pode alterar a formatação da fonte.
Guia Dados
Nenhum, pois esse controle serve apenas para agrupamento visual de campos.
Eventos rab
A caixa de grupo reage a eventos envolvendo o mouse, uma chave ou o foco.

Empurre b utton
Além das propriedades descritas na página 70 , os seguintes recursos estão disponíveis.
Guia geral
Etiqueta no botão.

O botão recebe o foco quando


é clicado.

Se Y es, o botão pode ser


pressionado mostrado em. O
estado do botão é mostrado
como para um interruptor.
Quando você pressiona uma
segunda vez, mostra um botão
não pressionado.
Ativo, quando a opção Alternar
estiver definida como Sim .
Selecionado corresponde ao
botão pressionado.

Quebra automática se o botão


for muito estreito.

Uma variedade de ações


semelhantes às da barra de
navegação estão disponíveis.

HTML: Arquivo a ser chamado


com este botão.

Apenas para formulários


HTML: o quadro de destino
(organização de quadros para
diferentes páginas HTML) no
qual o arquivo deve ser aberto.

O botão padrão é enquadrado


quando está definido como Sim
. Quando existem vários botões
alternativos em um formulário,
o mais usado deve ter essa
característica. É ativado
pressionando a tecla Enter,
quando nenhuma outra ação
precisa depender dessa chave.
Apenas um botão no formulário
pode ser o botão padrão.

Um gráfico deve aparecer no


botão?

Apenas ativo quando um


gráfico foi selecionado.
Especifica o alinhamento do
gráfico ao texto.

Guia Dados
Nenhum. Um botão só executa ações.
Guia Eventos
"Aprovar ação", "Executar ação" e "Status do item alterado".

Imagem b utton
Além das propriedades já descritas na página 70 , os seguintes recursos estão disponíveis.
Guia Geral
Semelhante a um botão normal. No entanto, este botão não tem texto e o botão em si não é visível.
Você vê apenas uma moldura ao redor do gráfico.
Por padrão, um botão de imagem não tem parada de tabulação.
Atenção: no momento da escrita, quase nenhuma ação funciona com este botão. É praticamente só
utilizável com macros.
Guia Dados
Nenhum; esse controle realiza apenas ações.
Guia Eventos
"Aprovar ação" e todos os eventos que envolvam o mouse, uma chave ou o foco.

Barra de navegação
Figura 29:
Navegação b
ar control

A barra de pesquisa padrão F orm N é inserida em formulários na borda inferior da tela. A inserção desta
barra de ferramentas pode causar um breve deslocamento para a direita do formulário à medida que ele se
acumula na tela. Isso pode ser uma distração nos casos em que a barra de navegação é desativada
novamente para algumas partes do formulário visível, por exemplo, quando há subformulários ou mais de
um formulário no formato visível .
Por outro lado, um controle de barra de navegação que faz parte do formulário, separado dos itens
correspondentes, deixa claro por quais itens você navega com a barra de ferramentas. O formulário para
Loan s , por exemplo, precisa procurar primeiro através dos leitores e, em seguida, mostrar a mídia
carregado para o leitor. A barra de navegação de controle está posicionado perto do leitor, de modo que o
aviso do usuário s de que a barra de navegação é utilizado para o leitor e não para os meios emprestados
para o leitor.
A barra de aviação padrão F orm N disponibiliza os botões mostrados na figura30 . O controle da barra de
navegação mostra o mesmo botão s excepto th ose para Encontrar ficha, Filtros formulário com base em
dados e s onte como Tabela.
Figura 30: Botões de
navegação
Além das propriedades listadas na página 70 , os recursos a seguir estão disponíveis para o controle da
barra de navegação .
Guia Geral
O tamanho do ícone é
ajustável. Além disso, você
pode escolher quais grupos
são exibidos. Estas são
mostradas na Fig ure 29 a
partir da esquerda para a
direita usando uma linha
vertical como um separador
de grupo: Posicionamento,
navegação, sob uma ficha, e
grupos de comandos para
filtragem e classificação.

Guia Dados
Nenhum, já que este controle apenas realiza ações.
Guia Eventos
Todos os eventos que envolvem o mouse, uma chave ou o foco.
Independente desse controle de formulário, a barra de navegação inserível naturalmente continua
existindo com os mesmos itens da figura acima.
Essa barra de navegação inserível fornece adicionalmente a pesquisa de registro geral , o filtro com base
em formulário e a exibição da fonte de dados subjacente do formulário na exibição de tabela acima do
formulário.
Se você estiver trabalhando não apenas com um formulário, mas com subformulários e formulários
auxiliares, deve ter cuidado para que essa barra de navegação inserível não desapareça quando você
alternar os formulários. Isso cria um efeito perturbador na tela.

Seleção múltipla
Se você usar o ícone Select (Fig ure 24 ) para selecionar uma região grande ou vários elementos de um
formulário, as seguintes modificações podem ser realizadas (ver Fig ure 31 ).
Figura 31: gerais p ROPRIEDADES de f orm f fields em um m últiplo s eleição
Você não deve alterar o nome. Isso faria com que todos os elementos selecionados de repente a um c
quire o mesmo nome. Isso tornaria difícil encontrar elementos individuais usando o navegador F orm N , e o
gerenciamento do formulário usando controles nomeados em macros impossíveis.
A seleção múltipla é mais útil para alterar a fonte, a altura ou a cor de fundo dos controles. Observe que
alterar a cor do plano de fundo também afeta os rótulos.
Se você quiser alterar apenas os rótulos, mantenha pressionada a C ontrole chave e clique esses controles
direta ou no N avigator, ou botão direito do mouse em um campo para chamar as propriedades de controle.
Agora, a escolha de propriedades que você pode alterar é maior, pois você está lidando apenas com
campos semelhantes. Você pode alterar qualquer coisa aqui que esteja disponível em um campo de rótulo.
As possibilidades de seleção múltipla dependem, portanto, da escolha de campos. Você pode alterar
simultaneamente controles do mesmo tipo que possuem todas as propriedades existentes para uma única
instância.

Um formulário simples concluído


Um formulário simples tem controles de formulário para escrever ou ler registros de uma única tabela ou
consulta. Sua construção é mostrada pelo exemplo a seguir.

O exemplo de um formulário simples para empréstimos de biblioteca é mostrado aqui usando várias
variantes. A maneira rápida para nos enviar um e o Assistente de formulário é descrito no Capítulo 8,
Introdução ao Base, na Introdução ao LibreOffice guia. H ere que descrevem a criação em D esign V iew.

O título do formulário foi criado usando um campo de rótulo. A fonte foi alterada. O campo de rótulo é
ancorado a um parágrafo no canto superior esquerdo do documento. Usando o menu de contexto do
campo de etiqueta, foi criado um formulário vinculado à tabela Empréstimos (consulte “ Propriedades do
formulário ” na página 66 ). A página também recebeu um fundo uniformemente colorido.

Adicionando g rupos de f fields


Uma variante rápida para a entrada direta de campos com rótulos é usar a função Adicionar campo .
Essa função, disponível na barra de ferramentas Design de Fórmulas (veja a Figura 22 ), permite que todos
os campos da tabela subjacente sejam selecionados.

D ouble - clique nos campos t o insira -os na forma como um grupo com etiquetas (infelizmente todos no
mesmo local). O grupo precisa ser separado para que o formulário se pareça com a ilustração a seguir.
Para uma melhor visualização, todas as barras de ferramentas desnecessárias foram removidas da janela,
que também foi compactada para que nem todos os elementos da barra de distribuição N sejam visíveis.
Todos os campos foram selecionados, exceto Media_ID_BC , que é projetado para ser usado somente
com um scanner de código de barras.
Figura 32: simples f
orm feita usando um
campo dd

Para cada campo da tabela, um controle de formulário apropriado foi selecionado automaticamente. Os
números estão em campos numéricos e são declarados como números inteiros sem casas decimais. Os
campos de data são representados corretamente como controles de data. Todos os campos receberam a
mesma largura. Se um controle gráfico tivesse sido incluído, seria dado um campo quadrado.

Ajustar f ield p roportions


Agora podemos fazer algumas coisas criativas, incluindo o ajuste do tamanho dos campos e as datas nos
campos suspensos. Mais importante ainda é para o MEDIA_ID e os Reader_ID campos para ser mais
user-friendly, a menos que cada usuário da biblioteca ha s uma biblioteca ID cartão e cada meio é fornecido
com um ID no momento da adesão. Isso não será assumido no que segue.
Para ajustar campos individuais, devemos editar o grupo. Isso pode ser feito com um direito - clique sobre
o grupo e, em seguida, seguindo o menu de contexto (Figura33 ) . Para o trabalho futuro, será mais claro se
usarmos o F orm N avigator.

Figura 33: Forma controla: e ditando o g rupo


O avigator Form N exibe todos os elementos do formulário com seus rótulos. Para controles, os nomes
são obtidos diretamente dos nomes dos campos na tabela subjacente. Os nomes dos rótulos têm o rótulo
de sufixo .
Um clique em Media_ID seleciona este campo (Figura34 ) . R ight - clique para substituir o campo
seleccionado com um tipo diferente de campo, usando o menu de contexto (Figura 35 ).
Figura 34: Selecção f orm c
ONTROLOS d irectly u cantar a F
orm N avigator

Figura 35: Substituindo o ne k ind de c ontrolo por um utro utilizando o Formulário Navigator
Esta substituição é realizado para os MEDIA_ID e Reader_ID controles.

A mudança é tornada visível no F orm N avigator pela alteração no ícone de acompanhamento.

A consulta SQL para o campo de lista agora pode ser criada por meio da interface gráfica do usuário,
clicando no botão à direita. Isso é executado automaticamente quando uma caixa de listagem é criada
diretamente, mas não quando é formada pela conversão de outro tipo de controle. Para o comando SQL,
consulte C apítulo 5, Consultas.
Como as caixas de listagem devem ser feitas suspensas, os seguintes defeitos podem ser corrigidos ao
mesmo tempo:
•Os rótulos das caixas de listagem devem ser Mídia em vez de Media_ID e Reader em vez de Reader _ ID
.
?O controlo de ID deve ser declarado como só de leitura.
•Quaisquer campos que não sejam absolutamente necessários para a emissão de empréstimos para uma
nova mídia não precisam de uma parada de tabulação. Sem isso, o formulário pode ser percorrido muito
mais rápido. Se necessário, a parada de tabulação também pode ser ajustada usando a seqüência de
ativação (consulte a página 70 ). Somente oscampos Mídia , Leitor e Data do Empréstimo devem estar
acessíveis em todos os casos, usando atecla T ab .
•Se o formulário for destinado à execução de empréstimos, é desnecessário e também confuso para a
mídia devolvida ser exibida. Mídia com data de retorno deve ser filtrada. Além disso, a ordem de exibição
pode ser classificada por R eader, de modo que a mídia emprestada à mesma pessoa seja exibida
sucessivamente. Consulte a observação em “ Propriedades do formulário ” na página 66 . No entanto, há
um problema aqui em que os leitores podem ser classificados somente por ID, não por ordem alfabética,
bec um u s e a tabela subjacente do formulário contém apenas o ID.
Adicionando s ingle f fields
A adição de campos únicos é um pouco mais complicada. Os campos devem ser selecionados,
arrastados para a superfície do formulário e o campo apropriado da tabela subjacente especificada. Além
disso, o tipo de campo deve ser escolhido corretamente; Por exemplo, os campos numéricos têm duas
casas decimais por padrão.
Somente ao criar caixas de listagem o Assistente entram em jogo, tornando mais fácil para um novato para
executar os passos para a criação correta Fields u p a um ponto. Além desse ponto, o assistente deixa de
atender aos requisitos bec um u s e :
•As entradas não são classificadas automaticamente.
• Acombinação de vários campos no conteúdo da caixa de listagem não é possível.
Aqui, novamente, precisamos fazer melhorias retrospectivas, para que o código SQL necessário possa ser
criado rapidamente usando o editor de consultas integrado.
Ao adicionar controles únicos, o campo e seu rótulo devem ser explicitamente associados (consulte “
Configurações padrão para muitos controles ” na página 70 ). Na prática, poderia ser melhor se você fizer n
ó campos de t associados com as etiquetas. Então você não deve escolher Editar Grupo antes chang ing
as propriedades de um campo.

Controle de mesa
O uso do Assistente de Tabelas para criar um controle de tabela já foi descrito na página 87 . No entanto,
existem alguns defeitos que precisam ser melhorados:
•Os MEDIA_ID e Reader_ID campos deve tornar-se caixas de listagem.
• Oscampos numéricos devem ser removidos de suas casas decimais, uma vez que o Assistente sempre
especifica duas casas decimais para números.

Alterar campos dentro do controle de tabela não é possível usando o mesmo método descrito para outros
controles. No N avigator, a descrição dos campos termina com o controle de tabela. O navegador N não
sabe nada sobre os controles que estão dentro do controle de tabela, referindo-se aos campos na tabela
subjacente. Isso se aplica igualmente mais tarde, quando são feitas tentativas de acessar os campos
usando macros. Eles não podem ser acessados pelo nome.

Os controles dentro do controle de tabela são chamados de colunas. Usando o menu de contexto, agora é
possível substituir um tipo de campo por outro. No entanto, toda a gama de tipos não está disponível. Não
há botões, caixas de opção ou controles gráficos.

As propriedades dos campos estão ocultas no menu de contexto por trás do conceito de colunas. Aqui, por
exemplo, o campo numérico Extensão pode ser alterado para que nenhuma casa decimal seja mostrada.
Além disso, o valor mínimo padrão de –1.000.000,00 dificilmente faz sentido para uma extensão de
empréstimo. O número deve permanecer sempre pequeno e positivo.
Assim que as propriedades de uma coluna forem chamadas, você poderá selecionar outra coluna sem
fechar a caixa de diálogo de propriedades. Desta forma, você pode trabalhar em todos os campos, um
após o outro, sem ter que economizar no meio.
E salvando todo o formulário e, finalmente, o próprio banco de dados.
As propriedades dos campos incorporados em um controle de tabela não são tão abrangentes quanto as
externas. A fonte, por exemplo, pode ser definida apenas para o controle de tabela inteiro. Além disso, você
não tem a opção de ignorar colunas individuais removendo suas paradas de tabulação.

Você pode percorrer um formulário usando o mouse ou a tecla T ab . Se você


tabular em um controle de tabela, o cursor moverá um campo para a direita
Gorjeta para cada tabulação adicional; no final da linha, ele retornará ao primeiro
campo do próximo registro no controle de tabela. Para sair do controle de
tabela, use Ctrl + Tab .

A ordem das colunas pode ser alterada arrastando o cabeçalho da coluna:

Se isso for feito no modo de design de formulário, ele será permanente. Uma alteração temporária na
ordem pode ser executada durante a entrada de dados usando o mesmo método.
Se apenas determinado campo s deve ser visível durante o uso, você pode usar vários controles diferentes
de mesa na forma, como o T ab é capturado por padrão por cada controle de tabela.
A forma mostrada na Figura 36 é para o empréstimo de mídia. Apenas os campos imediatamente
necessários são mostrados no controle da tabela superior. O inferior mostra todos os campos, de modo
que é aparente qual pessoa e meio o retorno é para.
Figura 36: A f orm com vários
controlos de mesa

Esta figura mostra uma falha estética t h às necessidades de atenção urgente. No controle da tabela
superior, o mesmo meio às vezes ocorre mais de uma vez. Isso acontece porque a tabela também mostra
as mídias que foram retornadas anteriormente. Portanto, os dados precisam ser filtrados para mostrar
apenas os empréstimos. Registros com data de retorno não devem aparecer.
Essa filtragem é possível por uma consulta ou usando diretamente as propriedades do formulário. Se isso
for feito usando as propriedades do formulário, o filtro pode ser temporariamente desligado durante a
entrada. Filtragem utilizando uma consulta é descrito em C apítulo 5, consultas. Aqui nós descrevemos
como fazer isso usando propriedades de formulário.

A filtragem é realizada usando o botão com os três pontos, que abre a caixa de diálogo mostrada abaixo.
Você também pode inserir o filtro diretamente no campo de texto Filtro , se souber a codificação SQL.
Usando a GUI , você pode agora selecionar o campo chamado Return_Date . Ele mostrará apenas os
registros para os quais o campo está vazio, onde “empty” significa a designação SQL NULL.
A forma limpa (mostrada na Figura37 ) agora parece bastante mais simples.
É claro que ainda há espaço para melhorias, mas em comparação com a forma anterior, a versão tem
uma vantagem nítida em que todas as mídias são visíveis de relance.
O processamento de dados usando controles de tabela é semelhante ao uso de uma tabela real. Um direito
- clique no cabeçalho de registro de um registro existente faz com que seja excluído, e uma entrada pode
ser cancelada ou salvo no caso de novos registros.
Quando você deixa uma linha, o registro é salvo automaticamente.

Figura 37: Formulário alterado


Ainda podemos melhorar o empréstimo da forma de mídia de várias maneiras.
•Seria bom se selecionar um leitor em uma parte do formulário fazia com que a mídia emprestada a este
leitor fosse exibida em outro.
•Na tabela mostrada acima, você pode ver um monte de discos que não são necessárias porque t media
stas já estão no empréstimo. A tabela foi criada para permitir empréstimos, portanto, seria melhor se
apenas uma página vazia aparecesse, o que poderia então ser preenchido com o novo empréstimo.
Tais soluções estão disponíveis usando outros formulários que são organizados hierarquicamente e
possibilitam visões separadas dos dados.

Principais formas e subformulários


Um subformulário está dentro de uma forma como um controle de formulário. Como um controle de
formulário, ele está vinculado aos dados do formulário principal. No entanto, sua fonte de dados pode ser
outra tabela ou consulta (ou um comando SQL). O importante para um subformulário é que sua origem de
dados está de alguma forma vinculada à fonte de dados do formulário principal.

Estruturas de tabelas típicas que podem ser usadas como subformulários são tabelas com um
relacionamento um-para-muitos (consulte o Capítulo 3, Tabelas). O formulário principal mostra uma tabela
com registros para os quais muitos registros dependentes no subformulário podem ser vinculados e
exibidos.
Primeiro, vamos utilizar a relação da tabela Leitor t oa mesa de empréstimo (ver Capítulo 3, Tabelas). A
tabela Leitor formará a base para o formulário principal e a tabela Empréstimo será reproduzida no sub-
formulário.

Aqui, o formulário principal está vinculado à tabela do Reader . Para acelerar a pesquisa de leitores, a tabela
é organizada em ordem alfabética. Faremos sem uma barra de navegação, pois o conteúdo do
subformulário ficará entre o formulário principal e a barra de navegação. Em vez disso, usaremos o
controle de formulário integrado ( Figura 29 ).

R ight clique sobre o formulário principal na F orm N avigator t o usar o menu de contexto para criar um
novo formulário. Mais uma vez este formulário tem o nome padrão do formulário, mas agora é um elemento
na subpasta do formulário principal.

As propriedades do subformulário agora devem ser configuradas para fornecer a fonte de dados correta, a
fim de reproduzir os dados para o leitor correto.
A tabela Empréstimos é escolhida para o subformulário. Para o filtro, especificamos que o campo Data de
retorno deve estar vazio (" Return_Date" IS NULL ). Isso impede que qualquer mídia que já tenha
sido retornada apareça. Os registros devem ser classificados por data de empréstimo. A classificação
crescente mostra o meio emprestado pelo período mais longo no topo.
Os campos mestre de link e escravo de link são usados para criar uma vinculação ao formulário principal,
no qual o subformulário se encontra. O botão com três pontos mostra mais uma vez que uma caixa de
diálogo útil está disponível para criá-los.

Em Empréstimos , os campos da tabela Empréstimos são mostrados, em Leitores, os da tabela Leitor. O


Reader_ID from Loans deve ser definido como equivalente ao ID da tabela R eader .
Embora essa ligação já tenha sido criada no banco de dados usando Ferramentas > Relacionamentos
(consulte C apítulo 3, Tabelas), a função que está por trás do botão Sugerir nessa caixa de diálogo não faz
referência a isso e sugere que a primeira chave estrangeira na tabela Empréstimo , ou seja , Media_ID ,
deve ser vinculado com o ID da tabela do Reader. O Form Creation Wizard resolve isso melhor lendo a
relação do relacionamento do banco de dados.

O link escolhido entre a tabela para o subformulário e a tabela para o formulário principal agora é
especificado em termos de campos das tabelas.
Para criar um controle de tabela para o formulário principal, agora temos de seleccionar o formulário
principal na F orm N avigator. Em seguida, se o Assistente para controle de tabela estiver ativado, ele
mostrará os campos disponíveis no formulário principal. Nós lidamos com o subformulário de maneira
semelhante.
Uma vez que os controles da tabela tenham sido configurados, precisamos realizar as modificações já
discutidas ao criar a forma mais simples:
•Substituindo o campo numérico Media_ID no subformulário por uma caixa de listagem.
•Renomeando o campo Media_ID Media .
•Modificando os campos numéricos para um formato sem casas decimais.
•Limitar os valores mínimo e máximo.
•Renomeando outros campos, para economizar espaço ou adicionar caracteres não-ASCII que não devem
ser usados em nomes de campos em tabelas de banco de dados.
As funções de classificação e filtro são complementadas para o formulário principal, adicionando uma barra
de navegação. Os outros campos da barra de navegação não são necessários, pois estão disponíveis
principalmente a partir do controle de tabela (exibição de registro, navegação de registro) ou então pela
movimentação através do controle de tabela (armazenamento de dados).
A forma final pode se parecer com a figura abaixo.
Figura 38: Forma que consiste em uma
forma principal (acima) e um subformulário
(abaixo).

Se um leitor for selecionado no formulário principal, o subformulário mostrará a mídia emprestada a esse
leitor. Quando um item n é retornado, ele continua aparecendo no formulário até que o próprio formulário
seja atualizado. Isso ocorre automaticamente quando outro registro é carregado no formulário principal. Se
o leitor original for selecionado novamente, a mídia retornada não será mais exibida.
Essa atualização atrasada é realmente desejável nesse caso, já que permite inspecionar a mídia que está
no momento no balcão da biblioteca e ver de imediato se elas foram registradas.
Essa estrutura de formulário é significativamente mais fácil de usar do que a anterior com apenas um único
formulário. No entanto, ainda há detalhes que podem ser melhorados:
• Asdatas de mídia e empréstimo podem ser alteradas quando a mídia for emprestada por mais tempo.
Alterar a data da mídia pode tornar impossível rastrear qual item ainda está disponível na biblioteca e
que está em empréstimo. Alterar a data do empréstimo pode levar a erros. Avisos de recall poderia n o t
ser verificada.
•Se um registro de leitor não for selecionado clicando no cabeçalho do registro à esquerda, somente a
pequena seta verde no cabeçalho mostrará qual registro está ativo no momento. É bem possível que o
registro ativo seja rolado para fora da janela de controle da tabela.
•Em vez do texto “ Mídia Emprestada do Leitor escolhido ”, seria melhor ter o nome do leitor.
•É possível emprestar o mesmo meio duas vezes sem que tenha sido devolvido.
•I t é possível excluir o registro para um item de n por empréstimo com bastante facilidade.
• Osdados podem ser alterados ou excluídos no formulário principal. Isso pode ser útil para pequenas
bibliotecas com pouco tráfego público. No entanto, quando as coisas ficam agitadas no balcão de
empréstimos, a edição dos dados do usuário não deve ocorrer ao mesmo tempo que a emissão de
empréstimos. Seria melhor se novos usuários pudessem ser registrados, mas os dados de usuário
existentes não fossem alterados. Para bibliotecas, isso se aplica igualmente a exclusões ou alterações
completas de nomes.
Primeiro, vamos melhorar a seleção de leitores. Isso deve nos proteger das mudanças nos registros de
empréstimos. Uma solução simples seria não permitir qualquer modificação, exceto a entrada de novos
registros. Isso ainda requer uma função de busca quando um leitor deseja emprestar um item n . Seria
melhor usar uma caixa de listagem para localizar o leitor e executar o problema e retornar as operações em
controles de tabela separados.
Para o formulário principal, precisamos de uma tabela na qual a caixa de listagem possa escrever um valor
vinculado a essa tabela. A tabela requer um campo inteiro e uma chave primária. Ele sempre conterá
apenas um registro, portanto, o ID do campo de chave primária pode ser declarado com segurança como
Tiny Integer. A tabela a seguir denominada Filtro deve, portanto, ser criada.
Nome da tabela: filtro
Nome do campo Tipo de campo
identidade Número inteiro pequeno,
chave primária
Inteiro Inteiro

A tabela recebe uma chave primária com o valor 0. Esse registro será repetidamente lido e reescrito pelo
formulário principal.

O formulário principal é baseado na tabela Filtro . Ele apenas lerá o valor da tabela que está associada à
chave primária ( ID ) de 0. Nenhum dado será adicionado; o registro atual será reescrito repetidamente.
Como somente edições de um único registro são permitidas, uma barra de navegação seria supérflua.

Este formulário principal está ligado ao subformulário de tal forma que o valor do campo Integer na tabela
Filter é o mesmo que o valor do campo Reader_ID na tabela Loan Table. As propriedades do subformulário
são inalteradas da versão mostrada acima.
Antes de criarmos uma caixa de listagem no formulário principal, devemos desativar os assistentes. O
Assistente de lista só permite criar uma caixa que mostra o conteúdo de um único campo; que seria
impossível ter o sobrenome um nome dado nd e um número adicional na área de exibição de uma caixa de
lista. Como na forma mais simples, entramos agora no conteúdo da caixa de listagem Sobrenome, Nome -
ID Nr . A caixa de listagem transmite o ID para a tabela subjacente.

Ao lado da caixa de listagem, um botão é criado. Este botão é na verdade parte do subformulário. Ele
assume duas funções: salvar o registro no formulário principal e atualizar a tabela no subformulário. É bom
o suficiente para confiar a atualização para o botão no subformulário. O processo de salvamento do
formulário principal modificado é então executado automaticamente.
O botão pode simplesmente ser rotulado como OK . A ação atribuída a ele nas propriedades gerais do
botão é Atualizar Formulário .
Figura 39:
Formulário principal
como filtro para um
subformulário

O formulário principal consiste apenas no título e na caixa de listagem; o subformulário contém outro título,
o controle de tabela da versão anterior e o botão.
O formulário agora funciona melhor nisso:
•Nenhum leitor pode agora ser editado, alterado ou excluído, e
• Osleitores podem ser encontrados mais rapidamente digitando no controle do que usando um filtro.
Para um maior grau de funcionalidade (retornos sem alteração de dados anteriores), um segundo
subformulário deve ser criado, vinculado à mesma tabela Empréstimos. Para assegurar a funcionalidade
da caixa de lista na Fig ure 39 , ambas as subformas deve ser colocado um nível mais baixo, como
subformas de um subformulário. Os dados são atualizados hierarquicamente desde o formulário principal
até os subformulários. O botão no formulário descrito anteriormente deve agora ser colocado no primeiro
subformulário e não nos dois subformulários que vêm sob ele.

Aqui o F orm N avigator é utilizado para mostrar os diferentes níveis. No formulário principal, temos o
campo de texto para o título do formulário e a caixa de listagem para encontrar o leitor. A caixa de listagem
aparece na parte inferior do formulário, como é declarado após o subformulário. Infelizmente esta
sequência de exibição não pode ser alterada. O subformulário tem apenas um botão, para atualizar seu
conteúdo e ao mesmo tempo salvar o formulário principal. Um nível abaixo são os dois subformulários
adicionais. Estes recebem nomes diferentes quando criados, para que não haja confusão em qualquer nível
da árvore.

Nota Basicamente, os nomes de formulários e controles são irrelevantes. No


entanto, se esses nomes devem ser acessados por macros, eles devem ser
distinguíveis. Você não pode distinguir nomes idênticos no mesmo nível.
Naturalmente, faz sentido, ao criar estruturas de formulários maiores, ter
nomes significativos para formulários e seus controles. Caso contrário,
encontrar o campo certo pode se tornar rapidamente problemático.

O formulário principal e o subformulário usam a mesma tabela. No subformulário, nenhum dado é inserido.
É por este motivo que todos os campos deste formulário estão definidos como Não. O formulário principal e
o subformulário estão ligados através do campo, cujo valor deve ser transmitido para os sub-
subformulários: o campo Integer na tabela Filter .

No primeiro sub-subformulário, nenhum dado existente é exibido; é usado apenas para criar novos dados.
Para isso, o filtro sugerido é adequado. Apenas registros correspondentes ao Reader_ID e com um campo
de data de empréstimo vazio (" Loan_Date" IS NULL ) serão exibidos. Na prática, isso significa um controle
de tabela vazio. Como o controle de tabela não é atualizado continuamente, a mídia recém-emprestada
permanecerá dentro dela até que o botão de atualização OK seja usado para selecionar um novo nome ou
para transferir os dados para o segundo sub-subformulário.

O segundo subformulário requer mais configurações. Este formulário também contém dados da tabela
"Empréstimos" . Aqui os dados são filtrados para uma data de retorno vazia. (" Return_Date" IS NULL ). Os
dados são classificados como no formulário anterior, para que a mídia emprestada por mais tempo seja
imediatamente visível.
Os seguintes pontos também são importantes. Registros antigos podem ser alterados, mas nenhum novo
registro pode ser adicionado. A exclusão também é impossível. Este é o primeiro passo necessário para
evitar que os registros de empréstimos sejam simplesmente excluídos mais tarde. Mas ainda seria
possível mudar o meio e a data do empréstimo. Portanto, as propriedades das colunas exigirão ajuste.
Eventualmente, o meio e a data do empréstimo devem ser exibidos, mas protegidos da modificação.
O controle de tabela é simplesmente duplicado após a criação do formulário. Isso é feito selecionando-o,
copiando, desmarcando e colando-o da área de transferência. A cópia estará na mesma posição do original
e, portanto, precisará ser arrastada. Depois disso, os dois controles de tabela podem ser editados
separadamente. O controle de tabela para o retorno de mídia pode ser praticamente o mesmo. Somente o
acesso de gravação para as colunas de data Media e L oan precisa ser alterado.
Enquanto para a data Lo , é necessário apenas escolher Read only , isto não é suficiente para list box.
Essa configuração não impede que a caixa de listagem seja usada para fazer alterações. No entanto, se
Ativado estiver definido como Não , não será possível fazer uma escolha. Uma caixa de listagem contida
no controle de tabela é exibida como um campo de texto somente leitura.
No controle de tabela acima, todos os campos que não têm nada a ver com o empréstimo são removidos.
Apenas o meio como um campo de seleção e a data do empréstimo, Loan_Date, permanecem.
Se, finalmente, a consulta da caixa de listagem no controle de tabela superior estiver selecionada, apenas
as mídias serão exibidas e poderão, na verdade, ser emprestadas. Mais sobre este é em Capítulo 5, Quer
ies .

Figura 40: O campo de


seleção no subformulário
superior mostra apenas
mídias que não estão
emprestadas.

O formulário de empréstimo de mídia já é significativamente mais útil. Quando um leitor chega ao balcão de
empréstimo, o nome dele ou dela é pesquisado. A mídia a ser emprestada pode ser selecionada usando a
caixa de listagem e a data do empréstimo inserida. A tecla T ab leva você ao próximo registro.
Uma melhoria final também é desejável: no momento, a data do empréstimo deve ser selecionada a cada
vez. Imagine um dia na biblioteca com talvez 200 transações de empréstimo, talvez apenas uma pessoa,
que deve emprestar cerca de 10 mídias a cada vez. Isso exigiria a mesma entrada para o campo de data e
outra vez. Deve haver uma maneira de simplificar isso.
Nosso formulário principal está vinculado à tabela de filtros . O formulário principal funciona apenas com o
registro que tem como chave primária o " ID" 0 . Mas campos adicionais podem ser construídos na tabela
Filter . No momento não há campo que possa armazenar uma data, mas podemos criar facilmente um
novo campo com o nome do campo Data e o tipo de campo D ate. Na tabela Filter nós agora
armazenamos não apenas o Reader_ID ("Filter". "Integer"), mas também o Loan_Date ("Filter". "Date").
No formulário principal, um campo de data adicional é exibido, junto com um rótulo referente ao seu
conteúdo. O valor do campo de data é armazenado na tabela Filtro e transferido pelas vinculações de
subformulário para sub-subformulário.

A ligação entre as duas formas agora se refere a dois campos. O campo Integer é ligado ao campo
Reader_ID do sub-subformulário. O campo Data está vinculado ao campo Loan_Date . Isso garante que o
Loan_Date seja transferido automaticamente da tabela Filtro para a tabela Empréstimos quando o
empréstimo for feito.
Figura 41: A dó da l oan
é inserida apenas uma
vez. Quando o Reader c
trava, deve ser
reinserido.

O campo de data agora é removido do controle de tabela, de modo que o último contenha apenas um
campo de pesquisa. Este seria o requisito ideal para acelerar ainda mais o trabalho da biblioteca. Pois, de
fato, cada mídia terá um número de acesso impresso, então por que isso tem que ser pesquisado? Você
pode simplesmente digitar o número diretamente. Ou, melhor ainda, poderia ser digitalizado com um leitor
de código de barras. Então, a mídia pode ser emprestada tão rapidamente quanto o mutuário pode guardá-
la em sua bolsa.
Isso é ilustrado no banco de dados de exemplo. O exemplo acima deve ser suficiente para entender o
design do formulário inicial, mas, como o banco de dados de exemplo, Media_without_Macros.odb,
desenvolve o formulário ainda mais, os refinamentos extras são brevemente apresentados abaixo.
O formulário Empréstimo mostra as seguintes propriedades:
• Osleitores são exibidos em um controle de tabela. Aqui você também pode inserir novos leitores.
•Usando um filtro, vinculado à tabela Filter, os nomes podem ser filtrados usando sua letra inicial. Então, se
você digitar A, somente as pessoas cujo sobrenome começa com A serão exibidas. Essa filtragem é
independente de maiúsculas e minúsculas.
•O subtítulo mostra novamente o nome da pessoa a quem o empréstimo deve ser feito. Se um bloqueio foi
colocado neste mutuário, isso também é exibido.
•A data do empréstimo é definida para a data atual. Isso é feito na tabela de filtros usando SQL, de modo
que, quando nenhuma data é inserida, o valor padrão a ser armazenado é a data atual.
•Mídia utilizável é selecionada usando uma caixa de listagem. Quando o botão Atualizar é pressionado, o
empréstimo é transferido para o controle de tabela abaixo.
•O controle de tabela no meio serve apenas para exibir a data real do empréstimo para a mídia. Aqui
também é possível corrigir um erro retrospectivamente excluindo a linha.
•No controle de tabela inferior, como no exemplo acima, a alteração de mídia e datas de empréstimo não é
possível. Também não é possível excluir registros.
•Além da entrada da data de devolução ou, se for o caso, uma extensão do empréstimo, essa tabela
também exibe o número de dias para os quais o meio pode ser emprestado e quantos dias restam do
período de empréstimo atual.
•Se esse tempo restante se tornar negativo, o meio deve ser devolvido imediatamente. O problema é
bloqueado. Torna-se possível novamente apenas quando o meio é devolvido. Após o retorno, o botão
Atualizar só precisa ser pressionado uma vez.
Essa forma, feita usando consultas, é significativamente mais complexa em sua estrutura do que a versão
mostrada anteriormente. Você pode aprender mais sobre o essencial disso no Capítulo 5, Consultas.

Um ponto de vista - m qualquer f ORMs


Embora o exemplo do formulário Empréstimos envolva apenas entradas em uma tabela (a tabela
Empréstimos) e, além disso, permita a entrada em um formulário mais simples para novos leitores, o
procedimento de entrada para mídia é significativamente mais extenso. Em sua forma final, a tabela de
mídia é cercada por um total de oito tabelas adicionais (veja o Capítulo 3, Tabelas).
As tabelas Subtitle e rel_Media_author estão vinculadas a subformulários do formulário Mídia por meio de
um relacionamento: 1. Por outro lado, as tabelas com um relacionamento 1: n para a tabela Mídia devem
ser representadas por formulários que estão acima da tabela Mídia. Como existem várias dessas tabelas,
seus valores são inseridos no formulário principal usando caixas de listagem.
A tabela de um formulário principal corresponde à tabela de um subformulário em um relacionamento 1: n
ou, em alguns casos excepcionais, 1: 1. Portanto, após o uso prolongado do banco de dados, o formulário
principal geralmente gerencia uma tabela que possui significativamente menos registros do que a tabela
pertencente ao subformulário.
Várias formas principais não podem incluir o mesmo subformulário. Portanto, não é possível criar um
arranjo de formulário para muitos relacionamentos simultâneos de 1: n nos quais o subformulário possui o
mesmo conteúdo. Quando há uma relação de 1: n para a tabela pertencente a uma forma, y o u podem
usar uma caixa de lista. Aqui há apenas alguns termos disponíveis em outra tabela, aqueles cujas chaves
estrangeiras podem ser inseridas na tabela do formulário principal dessa maneira.

Usando caixas de listagem, o formulário principal com base na tabela de mídia pode receber valores das
tabelas Categoria, Cidade ou Editor. S ubforms são o uso d para ligar o rel_Media_Author e mesas de
legenda com o formulário principal e através dele com o quadro de mídia.
O subformulário para o r mesa el_Media_Author novamente consiste de duas caixas de listagem para que
as chaves estrangeiras de seus autores e Author_Add_ID (adições pode ser, por exemplo editor, fotógrafo,
e assim por diante ) não tem que ser inseridos diretamente como números.
Para o formulário de entrada de mídia, as caixas de listagem geralmente precisam ser preenchidas
gradualmente durante o processo de entrada. Para este propósito, outros formulários são construídos ao
lado do formulário principal. Eles existem independentemente da forma principal.

A forma geral de inserir mídia é semelhante a esta:

No lado esquerdo é o formulário principal, com vista à busca e entrada de novas mídias. No lado direito do
formulário há uma caixa de grupo com o rótulo Edit list content contents , fornecendo uma área separada
destinada a preencher as caixas de listagem no formulário principal. Se o banco de dados não existir por
muito tempo, muitas vezes será necessário fazer entradas nesses campos. No entanto, as mais entradas
que estão disponíveis para as caixas de lista do formulário principal, menos frequentemente o acesso aos
comandos da tabela na caixa de grupo ser necessário.
Os controles de tabela a seguir são todos subordinados como formulários secundários individuais ao
formulário principal, o formulário de entrada.
Aqui, em cada caso, os dados completos de uma tabela são inseridos. Nos estágios iniciais, muitas vezes
é necessário recorrer a essas formas colaterais, uma vez que muitos autores ainda não estão
armazenados na tabela correspondente.
Quando um novo registro é armazenado em um dos controles de tabela, é necessário encontrar a caixa de
listagem correspondente no formulário principal e usar o controle Update (consulte N avigation bar) para ler
os novos valores.
O F orm N avigator mostra uma correspondentemente grande lista de formas.

Os f ORMs foram nomeados individualmente para facilitar o seu reconhecimento. Apenas o formulário
principal ainda tem o nome do MainForm dado a ele pelo Assistente. Ao todo, existem oito formas
paralelas. O formulário Filter hospeda uma função de pesquisa enquanto o formulário MainForm é a
interface de entrada principal. Todas as outras formas estão relacionadas a um ou outro dos controles de
tabela mostrados acima.
Sem os controles de tabela, o formulário principal parece um pouco mais simples.
O campo para o termo de pesquisa está no formulário Filtro , os dois controles de tabela (para o autor e o
subtítulo) estão no subformulário do formulário principal Entrada de Mídia.
No F orm N avigator, este formulário parece muito mais complexo, pois todos os controles e rótulos
aparecem lá. Na forma anterior, a maioria dos campos eram realmente colunas dentro dos controlos de
mesa e eram, portanto, invisível para o F orm N avigator.
Infelizmente, a sequência dentro do F orm N avigator não pode ser facilmente alterado. Assim, por
exemplo, parece mais sensato colocar os subformulários Subtítulo e Autor como ramificações do
MainForm logo no início. Mas no âmbito da F orm N avigator, controlos e subformas individuais são
simplesmente mostrada na ordem na qual eles foram criados.

O Assistente de Formulário fornece os controles com abreviações específicas que aparecem ao lado dos
ícones e indicam que tipo de controle é esse. Os rótulos começam com 'lbl', campos de texto com 'txt' e
assim por diante. Rótulos completos fornecem apenas informações secundárias para entrada de dados.
Eles também podem ser colocados diretamente acima quadros de texto e, em seguida, não aparecem na F
orm N avigator.
A sequência dos elementos no navegador não tem nada a ver com a sequência de guias. Isso é
determinado pela ordem de ativação .

A sequência de ativação de um formulário específico é invocada, quando um elemento do formulário é


selecionado e, em seguida, o botão Sequência de ativação é clicado. Para uma forma simples, não é
necessário fazer as coisas nesta ordem, mas onde há muitas formas paralelas, a função precisa saber
qual a forma pretendida. Caso contrário, por defeito, que é a primeira forma no F orm N avigator. No
exemplo acima, isso contém apenas um único campo de texto.

A seqüência de ativação permite que todos os elementos que transmitem dados para a tabela subjacente
do formulário ou possam realizar ações, sejam colocados em ordem. Isso corresponde à configuração da
seqüência de ativação nas propriedades de controle listadas na página 70 .
Observe que na sequência de ativação, alguns controles aparecem para os quais a parada de tabulação
está realmente desativada. Eles estão incluídos na lista, mas na verdade não são acessados pelo teclado
ao trabalhar com o formulário.
Os campos podem ser classificados automaticamente na ordem em que aparecem no plano de fundo do
formulário. Quanto mais alto estiver um campo, mais cedo ele vem na sequência quando você usa a
Classificação automática. Para campos na mesma altura, o campo mais à esquerda é o primeiro. Essa
classificação funciona sem erros somente quando os elementos foram posicionados exatamente usando a
grade quando o formulário foi criado. Caso contrário, você precisará ajustá-los. Basta selecionar um
controle e usar Mover para cima ou Mover para baixo para movê- lo para cima ou para baixo na sequência.
Se houver um subformulário, o Automatic Sort salta diretamente para o subformulário depois de concluir o
formulário principal. No caso de um controle de tabela, isso faz com que o cursor durante a entrada do
teclado fique preso dentro deste subformulário; você só pode liberá-lo usando o mouse ou pressionando
Ctrl + Tab .
A classificação automática funciona apenas uma vez para um controle de tabela. Um subformulário
subseqüente com um controle de tabela não será incluído. Formas paralelas também não são levadas em
consideração. Uma classificação automática não pode ser feita retrospectivamente para um subformulário
com um controle de tabela. O subformulário deve ser completamente removido (temporariamente movido
para outra forma).

O substrato de dados para o formulário de entrada de mídia é, nesse caso, não uma tabela, mas uma
consulta. Isso é necessário, pois o formulário deve ser usado não apenas para inserir registros, mas
também para pesquisar. O formulário também contém um campo de texto que mostra, após salvar, se o
número ISBN inserido estava correto. Isso também só é possível usando uma consulta abrangente. Para
entender o contexto disso, é necessário discutir os fundamentos das consultas, abordadas no Capítulo 5.
Capítulo 5 Consultas

Informações gerais sobre consultas


Consultas a um banco de dados são a ferramenta mais poderosa que temos para usar bancos de dados de
uma maneira prática. Eles podem reunir dados de diferentes tabelas, calcular resultados quando
necessário e filtrar rapidamente um registro específico de uma massa de dados. Os grandes bancos de
dados da Internet que as pessoas usam todos os dias existem principalmente para fornecer um resultado
rápido e prático para o usuário a partir de uma enorme quantidade de informações por meio de uma seleção
criteriosa de palavras-chave - incluindo anúncios relacionados a buscas que incentivam as pessoas a fazer
compras.

Inserindo consultas
As consultas podem ser inseridas na GUI e diretamente como código SQL. Em ambos os casos, uma
janela é aberta, onde você pode criar uma consulta e também corrigi-la, se necessário.

Criando consultas usando o diálogo Design da Consulta


A criação de consultas usando o Assistente é descrita resumidamente no Capítulo 8 do Guia de Introdução
, Introdução à Base. Aqui vamos explicar a criação direta de consultas em D esign V iew.
I a janela banco de dados principal n, clique no ícone Consultas na seção Bancos de dados, em seguida, na
seção Tarefas, clique em Criar Quer y na vista de estrutura . T wo diálogo s aparecer. Um fornece a base
para uma criação de visão de design da consulta; o outro serve para adicionar tabelas, visualizações ou
consultas à consulta atual.
Como nossa forma simples se refere à tabela Empréstimo, iremos primeiro explicar a criação de uma
consulta usando esta tabela.

Nas tabelas disponíveis, selecione a tabela Empréstimo. Essa janela permite que várias tabelas (e também
visualizações e consultas) sejam combinadas. Para selecionar uma tabela, clique em seu nome e, em
seguida, clique no botão Adicionar . Ou clique duas vezes no nome da tabela. Qualquer método add s da
mesa para a área gráfica do Q uery de diálogo projeto .
Quando todas as tabelas necessárias foram selecionados, clique no C perder botão . Tabelas e consultas
adicionais podem ser adicionadas posteriormente, se necessário. No entanto, nenhuma consulta pode ser
criada sem pelo menos uma tabela, portanto, uma seleção deve ser feita no início.
Figura 42: As áreas do Q uery D esign diálogo
Figura 42 s comos as divisões básicas do diálogo Design de consulta : a área gráfica exibe as tabelas que
estão a ser vinculado à consulta. Suas relações entre si em relação à consulta também podem ser
mostradas. A área da tabela é para a seleção de campos para exibição ou para definir condições
relacionadas a esses campos.
C lamber no campo na primeira coluna na área da tabela para revelar uma seta para baixo. Clique nesta
seta para abrir a lista suspensa de disponível campo s . O formato é Table_name.Field_name - é
por isso que todos os nomes de campo aqui começam com a palavra Empréstimo .

A designação de campo selecionada Empréstimo * tem um significado especial. Aqui, um clique


permite adicionar todos os campos da tabela subjacente à consulta. Quando você usa essa designação de
campo com o caractere curinga * para todos os campos, a consulta se torna indistinguível da tabela.
Os primeiros cinco campos da tabela Empréstimo são selecionados. Consultas no Design Mode sempre
podem ser executadas como testes. Isso faz com que uma visualização tabular dos dados apareça acima
da visualização gráfica da tabela Empréstimo com sua lista de campos . Uma execução de teste de uma
consulta é sempre útil antes de salvá-la, para esclarecer para o usuário se a consulta realmente atinge sua
meta. Geralmente, um erro lógico impede que uma consulta recupere dados. Em outros casos, pode
acontecer que precisamente esses registros sejam exibidos que você deseja excluir.
Em princípio, uma consulta que produz uma mensagem de erro no banco de dados subjacente não pode
ser salva até que o erro seja corrigido .

Figura 43: Uma consulta editável


No teste acima, atenção especial deve ser dada à primeira coluna do resultado da consulta. O marcador de
registro ativo (seta verde) sempre aparece no lado esquerdo da tabela, apontando para o primeiro registro
como o registro ativo. Enquanto o primeiro campo do primeiro registro na Figura 43 é destacado, o campo
correspondente na Figura 44 mostra apenas uma borda tracejada. O destaque indica que esse campo
pode ser modificado. Os registros, em outras palavras, são editáveis. A borda tracejada indica que esse
campo não pode ser modificado. A Figura 43 também contém uma linha extra para a entrada de um novo
registro, com o campo ID já marcado como <AutoField> . Isso também mostra que novas entradas são
possíveis.

Uma regra básica é que nenhuma nova entrada é possível se a chave primária
Gorjeta na tabela consultada não estiver incluída na consulta.

Os Loan_Date e RETURN_DATE campos são dadas aliases. Isso não faz com que eles sejam
renomeados, mas apenas para aparecer sob esses nomes para o usuário da consulta.
A exibição de tabela acima mostra como os aliases substituem os nomes de campo reais.

O campo Return_Date recebe não apenas um alias, mas também um critério de pesquisa, o que fará com
que apenas os registros sejam exibidos para os quais o campo Return_Date está vazio. (Insira IS EMPTY
na linha Criterion do campo Return_Date.) Esse critério de exclusão fará com que apenas os registros
sejam exibidos relacionados a mídias que ainda não foram retornadas do empréstimo.

Para aprender melhor a linguagem SQL, vale a pena alternar de tempos em tempos entre o Modo Design e
o Modo SQL .

Aqui a fórmula SQL criada por nossas escolhas anteriores é revelada. Para facilitar a leitura, algumas
quebras de linha foram incluídas. Infelizmente, o editor não armazena essas quebras de linha, portanto,
quando a consulta for acessada novamente, ela aparecerá como uma quebra de linha contínua única na
borda da janela.
SELECT inicia os critérios de seleção. AS especifica os aliases de campo a serem usados. FROM mostra
a tabela que deve ser usada como a origem da consulta. WHERE fornece as condições para a consulta, ou
seja, o campo Return_date deve estar vazio ( IS NULL ). ORDER BY define os critérios de classificação,
ou seja, ordem crescente (ASC - ascendente) para os dois campos Reader_ID e Data do Empréstimo.
Esta especificação de classificação ilustra como o alias do campo Loan_Date pode ser usado dentro da
própria consulta.

Ao trabalhar no Modo Design View, use IS EMPTY para exigir que um campo
fique vazio. Ao trabalhar no modo SQL, use IS NULL, que é o que o SQL
Gorjeta (Structured Query Language) requer.
Quando você quiser classificar por ordem decrescente usando SQL , use
DESC em vez de ASC .

Até agora, os campos Media_ID e Reader_ID são visíveis apenas como campos numéricos. Os nomes
dos leitores não são claros. Para mostrá-los em uma consulta, a tabela do Reader deve ser incluída. Para
este propósito, retornamos ao modo Design. Em seguida, uma nova tabela pode ser adicionada à
visualização Design.
Aqui, outras tabelas ou consultas podem ser posteriormente adicionadas e tornadas visíveis na interface
gráfica do usuário. Se os links entre as tabelas foram declarados no momento de sua criação (consulte o
Capítulo 3, Tabelas), essas tabelas serão mostradas com os links diretos correspondentes.

Se um link estiver ausente, ele pode ser criado neste momento arrastando o mouse de " Empréstimo".
"Reader_ID" para " Reader". "ID" .
Agora os campos da tabela do Reader podem ser inseridos na área tabular. Os campos são inicialmente
adicionados ao final da consulta.

A posição dos campos pode ser corrigida na área tabular do editor usando o mouse. Por exemplo, o campo
First_name foi arrastado para a posição diretamente antes do campo Loan_date.

Agora os nomes são visíveis. O Reader_ID se tornou supérfluo. Também classificar por sobrenome e
nome_do_nome faz mais sentido que classificação por Reader_ID.
Esta consulta não é mais adequada para uso como uma consulta que permite novas entradas na tabela
resultante, uma vez que não possui a chave primária para a tabela do Reader adicionada. Somente se essa
chave primária estiver incorporada, a consulta se tornará editável novamente. Na verdade, ele se torna
completamente editável para que os nomes dos leitores também possam ser alterados. Por esse motivo,
tornar os resultados da consulta editáveis é um recurso que deve ser usado com extrema cautela, se
necessário, sob o controle de um formulário.

Ter uma consulta que você pode editar pode criar problemas. Edição de dados
na consulta também edita os dados na tabela subjacente e os registros
Cuidado contidos na tabela. Os dados podem não ter o mesmo significado. Por
exemplo, altere o nome do leitor e também alterou os livros que o leitor
emprestou e devolveu.
Se você tiver que editar dados, faça isso em um formulário para poder ver os
efeitos da edição de dados.

Mesmo quando uma consulta pode ser editada, ela não é tão fácil de usar como um formulário com caixas
de listagem, que mostram os nomes dos leitores, mas contêm o Reader_ID da tabela. Caixas de listagem
não podem ser adicionadas a uma consulta; eles só são utilizáveis em formas.

Se voltarmos agora para o SQL View, vemos que todos os campos agora são mostrados entre aspas
duplas: "Table _name". "Field_name" . Isso é necessário para que o banco de dados saiba de
qual tabela os campos selecionados anteriormente vêm. Afinal, campos em tabelas diferentes podem
facilmente ter os mesmos nomes de campos. Na estrutura da tabela acima é particularmente verdadeiro
para o ID de f iel d.

Nota A consulta a seguir funciona sem colocar nomes de tabelas na frente dos
nomes de campos:
SELECIONE "ID", "Número", "Preço" DE "Estoque",
"Despacho" ONDE "Despacho". "StockID" = "Stock". "ID"
Aqui o ID é retirado da tabela que vem primeiro na definição FROM. A definição
da tabela na WHERE Formula também é supérflua, porque o stockID só ocorre
uma vez (na tabela Dispatch) e o ID foi claramente retirado da tabela Stock (da
posição da tabela na consulta).

Se um campo na consulta tiver um alias, ele poderá ser consultado - por exemplo, na classificação - por
esse alias sem que um nome de tabela seja fornecido. A classificação é realizada na interface gráfica do
usuário de acordo com a sequência de campos na visualização tabular. Se, em vez disso, você quiser
classificar primeiro por "Data do Empréstimo" e depois por " Empréstimo". "Reader_ID" , isso pode ser feito
se:
•A sequência de campos na área da tabela da interface gráfica do usuário é alterada (arraste e solte " Data
do empréstimo " à esquerda de " Empréstimo". "Reader_ID" ou
•A n campo adicional é adicionado, definido para ser invisível, apenas para ordenar (no entanto, o editor irá
registrar isso só temporariamente se nenhum alias foi definido por ele) [adicionar outro " data Loan " campo
pouco antes do " Empréstimo " . " Reader_ID " ou adicione outro " Empréstimo " . Campo " Reader_ID "
logo após " Data do empréstimo " ] , ou
•O texto para o comando ORDER BY no editor de SQL é alterado correspondentemente (ORDER BY "
Loan date " , " Loan " . "Reader_ID" ).
Especificar a ordem de classificação pode não estar completamente livre de erros , dependendo da versão
do LibreOffice . A partir da versão 3.5.3, a triagem da visão SQL está registrado corretamente e exibidos na
interface gráfica do usuário, incluindo os campos que são usados na consulta, mas são não visível na
saída da consulta. (Esses campos não têm uma verificação na linha visível ) .

Uma consulta pode exigir um campo que não faz parte da saída da consulta.
Gorjeta No gráfico da próxima seção , Return_Date é um exemplo. Esta consulta está
procurando por registros que não contêm uma data de retorno. Esse campo
fornece um critério para a consulta, mas nenhum dado visível útil.

Usando funções em uma consulta


O uso de funções permite que uma consulta forneça mais do que apenas uma visualização filtrada dos
dados em uma ou mais tabelas. A consulta a seguir calcula quantas mídias foram emprestadas,
dependendo do Reader_ID.

Para o ID da tabela Empréstimo , a função Contagem é selecionada. Em princípio, não faz diferença qual
campo de uma tabela é escolhido para isso. A única condição é: O campo não deve estar vazio em
nenhum dos registros . Por esse motivo, o campo da chave primária, que nunca está vazio, é a opção mais
adequada. Todos os campos com um conteúdo diferente de NULL são contados.
Para o R eader_ID , que dá acesso às informações do leitor, a função Agrupar é escolhida. Dessa maneira,
os registros com o mesmo Reader_ID são agrupados. O resultado mostra o número de registros para cada
Reader_ID .
Como critério de pesquisa, o Return_ D comeu está definido para “ESTÁ VAZIO ”, como no exemplo
anterior. (Abaixo, o SQL para isso é WHERE "Return_Date" IS NULL .)

O resultado da consulta mostra que o Reader_ID ' 0' tem um total de 3 mídias emprestadas. Se o conde
função tinha sido atribuído ao Return_ D comeu em vez do ID, cada Reader_ID teria '0' media por
empréstimo, já que RETURN_DATE é pré-definido como NULL.
A fórmula correspondente no código SQL é mostrada acima.
Ao todo, a interface gráfica do usuário fornece as seguintes funções, que correspondem às funções no
HSQLDB subjacente.
Para obter uma explicação das funções, consulte “ Aprimoramento de consulta usando o modo SQL ” na
página 134 .
Se um campo em uma consulta estiver associado a uma função, todos os demais campos mencionados
na consulta também deverão estar associados a funções, se forem exibidos. Se isso não for garantido,
você receberá a seguinte mensagem de erro:

Uma tradução um pouco livre seria: A expressão a seguir não contém função agregada ou agrupamento.

Ao usar o modo de exibição de design, um campo só é visível se a linha


Gorjeta visível contiver uma marca de seleção para o campo. Ao usar o modo SQL,
um campo só fica visível quando ele segue a palavra-chave, SELECT.

Quando um campo não está associado a uma função, o número de linhas na


saída da consulta é determinado pelas condições de pesquisa. Quando um
campo é associado a uma função, o número de linhas na saída da consulta é
determinado se existe algum agrupamento ou não. Se não houver agrupamento,
haverá apenas uma linha na saída da consulta. Se houver agrupamento, o
número de linhas corresponderá ao número de valores distintos que o campo de
agrupamento possui. Portanto, todos os campos visíveis devem estar
associados a uma função ou não estar associados a uma função para evitar
Nota esse conflito na saída da consulta.
Depois disso, a consulta completa é listada na mensagem de erro , mas
infelizmente sem o campo ofensivo sendo nomeado especificamente. Neste
caso, o campo Return_ D ate foi adicionado como um campo exibido. Este
campo não tem nenhuma função associada a ele e não está incluído na instrução
de agrupamento.
As informações fornecidas usando o botão Mais não são muito esclarecedoras
para o usuário normal do banco de dados. Apenas exibe o código de erro do SQL.

Para corrigir o erro, remova a marca de verificação na linha Visível do campo Return_Date. Sua condição
de pesquisa (Critério) é aplicada quando a consulta é executada, mas não é visível na saída da consulta.
Usando a GUI, cálculos básicos e funções adicionais podem ser usados.

Suponha que uma biblioteca não emita avisos de recall quando um item é devido para devolução, mas
emite avisos atrasados nos casos em que o período de empréstimo expirou e o item não foi retornado.
Esta é uma prática comum em bibliotecas escolares e públicas que emitem empréstimos apenas por
períodos curtos e fixos. Neste caso, a emissão de um aviso atrasado significa automaticamente que uma
multa deve ser paga. Como calculamos essas multas?
Na consulta mostrada acima, as tabelas Empréstimo e Recuperação são consultadas em conjunto. A partir
da contagem das entradas de dados na tabela Recalls, o número total de avisos de rechamada é
determinado. A multa para mídia vencida é definida na consulta como 2,00 €. Em vez de um nome de
campo, a designação de campo é dada como Count (Recalls.Date) * 2 . A interface gráfica do
usuário adiciona as aspas e converte o termo “ count ” no comando SQL apropriado.

Apenas para pessoas que usam uma vírgula para seu separador decimal:
Se desejar inserir números com casas decimais usando a interface gráfica
Cuidado com o usuário, você deve garantir que um ponto decimal em vez de uma
vírgula seja usado para separar as casas decimais na instrução SQL final.
Vírgulas são usadas como separadores de campo, portanto , novos campos
de consulta são criados para a parte decimal.
Uma entrada n com uma vírgula na visualização SQL sempre leva a um outro
campo contendo o valor numérico da parte decimal.

A consulta agora gera para cada meio ainda em empréstimo as multas que foram provisionadas, com base
nos avisos de recall emitidos e no campo de multiplicação adicional. A estrutura de consulta a seguir
também será útil para calcular as multas devidas por usuários individuais.

O " Empréstimo", "ID" e " Empréstimo". Os campos "Media_ID" foram removidos. Eles foram usados na
consulta anterior para criar agrupando um registro separado para cada mídia. Agora vamos agrupar apenas
pelo leitor. O resultado da consulta é assim:

Em vez de listar a mídia para Reader_ID = 0 separadamente, todos os campos " Recalls". "Date" foram
contados e o total de 8.00 € entrou como a multa devida.

Definição de relacionamento na consulta


Quando os dados são pesquisados em tabelas ou formulários, a pesquisa geralmente é limitada a uma
tabela ou a um formulário. Mesmo o caminho de um formulário principal para um subformulário não é
navegável pela função de pesquisa interna. Para tais fins, os dados a serem pesquisados são melhor
coletados usando uma consulta.
A consulta simples para o campo Título da tabela Mídia mostra as entradas de teste para esta tabela, 9
registros no total. Mas se você inserir Subtítulo na tabela de consulta, o conteúdo do registro da tabela
Mídia será reduzido para apenas dois Títulos. Apenas para estes dois títulos há também legendas na
tabela. Para todos os outros títulos, não há legendas. Isso corresponde à condição de associação em que
apenas os registros para os quais o campo Media_ID na tabela de legendas é igual ao campo de ID na
tabela Mídia devem ser mostrados. Todos os outros registros são excluídos.

As condições de junção devem ser abertas para edição para exibir todos os registros desejados. Referimo-
nos aqui para não se unir entre tabelas no design de relacionamento, mas para unir as consultas .

Por padrão, os relacionamentos são definidos como Intern Internins . A janela fornece informações sobre o
modo como esse tipo de junção funciona na prática.
As duas tabelas previamente selecionadas são listadas como Tabelas I envolvidas. Eles não são
selecionáveis aqui. Os campos relevantes das duas tabelas são lidos a partir das definições da tabela. Se
não houver relacionamento especificado na definição da tabela, será possível criar um neste ponto para a
consulta. No entanto, se você planejou seu banco de dados de maneira ordenada usando o HSQLDB, não
será necessário alterar esses campos.
A configuração mais importante é a opção Join . Aqui os relacionamentos podem ser escolhidos de tal
forma que todos os registros da tabela de legendas são selecionados, mas apenas os registros da mídia
que possuem uma legenda inserida na tabela de legendas.
Ou você pode escolher o oposto: que, em qualquer caso, todos os registros da tabela Mídia são exibidos,
independentemente de terem uma legenda.
A opção Natural especifica que os campos vinculados nas tabelas são tratados como iguais. Você também
pode evitar ter que usar essa configuração definindo seus relacionamentos corretamente no início do
planejamento do seu banco de dados.
Para o tipo Right join , a descrição mostra que todos os registros da tabela Media serão exibidos (Subtitle
RIGHT JOIN Media) . Como não há um subtítulo que não tenha um título na mídia, mas certamente há
títulos na mídia que não possuem um subtítulo, essa é a escolha certa.

Depois de confirmar a associação correta, os resultados da consulta são como desejávamos. Título e
subtítulo são exibidos juntos em uma consulta. Naturalmente, os títulos aparecem mais de uma vez, como
no relacionamento anterior. No entanto, desde que os hits não sejam contados, essa consulta poderá ser
usada como base para uma função de pesquisa. Ver os fragmentos de código neste capítulo, no Capítulo 9
( macros ), e em C apítulo 8 ( D atabase t pergunta ) .

Consulta e aprimoramento usando o modo SQL


Se durante a entrada gráfica você usa Ver > Mudar Modo Design On / Off para alternar exibição de
design fora, você consulte o comando SQL para o que anteriormente apareceu em D esign V iew. Essa é a
melhor maneira de os iniciantes aprenderem a Linguagem de Consulta Padrão para Bancos de Dados. Às
vezes, também é a única maneira de inserir uma consulta no banco de dados quando a GUI não pode
converter seus requisitos nos comandos SQL necessários.
SELECT * FROM "Table_name"
Isso mostrará tudo o que está na tabela Table_name . O "*" representa todos os campos da tabela.
SELECT * FROM "Table_name" WHERE "Nome_do_campo" = 'Karl'
Aqui há uma restrição significativa. Apenas os registros são exibidos para os quais o campo Field_name
contém o termo 'Karl' - o termo exato, não por exemplo 'Karl Egon'.
Por vezes, as consultas no Base de Dados de não pode ser levada a cabo utilizando a interface gráfica,
como comandos particulares podem não ser reconhe z ed. Em tais casos, é necessário mudar D esign V
iew fora e usar Editar > comando SQL executado diretamente para acesso direto ao banco de dados.
Esse método tem a desvantagem de que você só pode trabalhar com a consulta no modo SQL.
O uso direto de comandos SQL também é acessível usando a interface gráfica do usuário, como mostra a
figura acima. Clique no ícone destacado ( comando Executar SQL diretamente ) para desativar o ícone
Design View Off / On. Agora, quando você clica no ícone Executar , a consulta executa os comandos SQL
diretamente.
Aqui está um exemplo das extensas possibilidades disponíveis para fazer perguntas ao banco de dados e
especificar o tipo de resultado necessário:
SELECT [{LIMIT <deslocamento> <limite> | TOP <limite>}] [ALL | DISTINCT]
{<Select-Formulation> | "Table_name". * | *} [, ...]
[INTO [CACHED | TEMP | TEXT] "new_Table"]
FROM "Table_list"
[WHERE Expressão SQL]
[GROUP BY SQL-Expression [, ...]]
[TENDO SQL Expression]
[{UNION [ALL | DISTINCT] | {MENOS [DISTINCT] | EXCETO [DISTINCT]} |
INTERSECT [DISTINCT]} instrução de consulta]
[ORDEM POR ORDEM DE MANEIRA [, ...]]
[LIMIT <limite> [OFFSET <offset>]];
[{LIMIT <deslocamento> <limite> | TOP <limite>}]:
Isso limita o número de registros a serem exibidos. O LIMIT 10 20 começa no 11º registro e
mostra os 20 registros a seguir. TOP 10 mostra sempre os 10 primeiros registros. Isso é o mesmo
que LIMIT 0 10 . LIMIT 10 0 omite os 10 primeiros registros e exibe todos os registros a
partir do 11º.
Você pode fazer a mesma coisa usando a última condição SELECT na fórmula [LIMIT
<limite> [OFFSET <offset>]] . O LIMITE 10 mostra apenas 10 registros. Adicionar
OFFSET 20 faz com que a exibição comece no 21º registro. Antes de usar essa forma final de
limitação de exibição, você precisa incluir uma condição de classificação (ORDER BY…).
Limitar a exibição dos resultados da consulta só é possível usando comandos SQL diretos. Ao fazer
isso, você determina como os dados da consulta são classificados e, portanto, quais dados serão
mostrados.
[TODOS | DISTINCT]
SELECT ALL é o padrão. Todos os registros são exibidos e preenchem as condições de pesquisa.
Exemplo: SELECT ALL "Nome" FROM "Table_name" produz todos os nomes; se "Peter"
ocorrer três vezes e "Egon" quatro vezes na tabela, esses nomes serão exibidos três e quatro vezes,
respectivamente. SELECT DISTINCT "Name" FROM "Table_name" suprime os resultados da
consulta que possuem o mesmo conteúdo. Neste caso, 'Peter' e 'Egon' ocorrem apenas uma vez.
DISTINCT refere-se a todo o registro acessado pela consulta. Portanto, se, por exemplo, o
sobrenome for solicitado, os registros de 'Peter Müller' e 'Peter Maier' serão contados como distintos.
Mesmo se você especificar a condição DISTINCT ,
<Select-Formulation>
{Expression | COUNT (*) |
{COUNT | MIN | MAX | SUM | AVG | ALGUNS | CADA | VAR_POP | VAR_SAMP |
STDDEV_POP | STDDEV_SAMP}
([ALL | DISTINCT]] Expression)} [[AS] "display_name"]
Nomes de campos, cálculos, totais de registros são todas as entradas possíveis. Além disso,
diferentes funções estão disponíveis para o campo mostrado . Exceto para COUNT (*) (que conta
todos os registros), nenhuma dessas funções acessa campos NULL .
COUNT | MIN | MAX | SUM | AVG | ALGUNS | CADA | VAR_POP | VAR_SAMP |
STDDEV_POP | STDDEV_SAMP
COUNT ("Name") conta todas as entradas para o campo Name . MIN ("Nome") mostra o
primeiro nome em ordem alfabética. O resultado dessa função é sempre formatado exatamente como
ocorre no campo. O texto é mostrado como texto, inteiros como inteiros, decimais como decimais e
assim por diante. MAX ( "Nome") mostra o último nome de um l phabetically. SUM (
"Number") pode adicionar apenas os valores numéricos em al campos. A função falha nos campos
de data. AVG ("Número") mostra a média do conteúdo de uma coluna. Esta função também é
limitado a numéricos al campos. ALGUNS("

F ield _N ame ") : Os campos usados com o SE


função s deve ter o Sim / Não [ BOOLEAN ] tipo de campo (só contém 0 ou 1) . Além disso, eles
produzem um resumo do teor de campo aos quais eles são aplicados.
ALGUMAS retorna VERDADEIRO (ou 1 ), se pelo menos uma entrada para o campo é 1 , e ele
retorna FALSE (ou 0 ) somente se todas as entradas são 0 . EVERY retorna 1 somente se cada
entrada para o campo for 1 e retorna FALSE se pelo menos uma entrada for 0 .

Gorjeta O tipo de campo booleano é Sim / Não [BOOLEAN]. No entanto, esse campo
contém apenas 0 ou 1. Nas condições de pesquisa de consulta, use TRUE , 1
, FALSE ou 0 . Para a condição Yes , você pode usar TRUE ou 1 . Para a
condição No , use FALSE ou 0 . Se você tentar usar um “Sim” ou “Não” em
vez , você recebe uma mensagem de erro. Então você terá que corrigir seu
erro.

Exemplo:
SELECT "Class", EVERY ("Swimmer") FROM "Tabela1" GROUP BY "Classe";
Classe contém os nomes da classe de natação. Nadador é um campo booleano que descreve se um
aluno pode nadar ou não (1 ou 0). Alunos contém os nomes dos alunos. A Tabela 1 contém estes
campos: sua chave primária, Classe, Nadador e Alunos. Apenas classe e nadador são necessários
para essa consulta.
Como a consulta é agrupada pelas entradas do campo Class, EVERY retornará um valor para o
campo, Swimmer, para cada classe. Quando cada pessoa em uma aula de natação pode nadar, CADA
retorna TRUE. Caso contrário, EVERY retornará FALSE porque pelo menos um aluno da turma não
poderá nadar. Como a saída para o campo Nadador é uma caixa de seleção, Uma marca de seleção
indica VERDADEIRO e nenhuma marca de seleção indica FALSO.
VAR_POP | VAR_SAMP | STDDEV_POP | STDDEV_SAMP são funções estatísticas e afetam
apenas campos inteiros e decimais.
Todas estas funções retornam 0, se os valores dentro do grupo forem todos iguais.
As funções estatísticas não permitem que a limitação DISTINCT seja usada. Basicamente, eles
calculam todos os valores cobertos pela consulta, enquanto DISTINCT exclui registros com os
mesmos valores da exibição.
[AS] "display_name": Os campos podem receber uma designação diferente (alias) dentro da
consulta.
"Table_name". * | * [, ...]
Cada campo a ser exibido é fornecido com seus nomes de campos, separados por vírgulas. Se
campos de várias tabelas forem inseridos na consulta, uma combinação do nome do campo com o
nome da tabela será necessária: "Table_name". "Field_name" .
Em vez de uma detalhada lista de todos os campos de uma tabela , i t é o conteúdo total pode ser
exibido. Para isso você usa o símbolo "*". Em seguida, é desnecessário usar o nome da tabela, se os
resultados se aplicarem apenas à tabela. No entanto, se a consulta incluir todos os campos de uma
tabela e pelo menos um campo de uma segunda tabela, use:
"Table_name 1". *, "Table_name 2". "Field_name".
[INTO [CACHED | TEMP | TEXTO] "new_table"]
O resultado desta consulta deve ser escrito diretamente em uma nova tabela que é nomeada aqui. As
propriedades do campo para a nova tabela são definidas a partir das definições de campo contidas na
consulta.
Escrever em uma nova tabela não funciona no Modo SQL, já que isso lida apenas com resultados
exibidos. Em vez disso, você deve usar Ferramentas > SQL . A tabela resultante inicialmente não é
editável, uma vez que carece de um p chave rimary.
FROM <Table_list>
"Table_name 1" [{CROSS | INNER | ESQUERDA EXTERNA | DIREITA EXTERIOR} JOIN
"Table_name 2" ON Expression] [, ...]
As tabelas que devem ser pesquisadas em conjunto geralmente estão em uma lista separada por
vírgulas. O relacionamento das tabelas entre si é então definido adicionalmente pela palavra-chave
WHERE .
Se as tabelas estão ligadas através de um JOIN em vez de uma vírgula, o relacionamento delas é
definido pelo termo que começa com ON, o que ocorre diretamente após a segunda tabela.
Um simples JOIN tem o efeito de que apenas os registros são exibidos para os quais as condições
em ambas as tabelas se aplicam.
Exemplo:
SELECT "Tabela1". "Nome", "Tabela2". "Classe" FROM "Tabela1", "Tabela2" WHERE "Tabela1".
"ClassID" = "Tabela2". "ID"
é equivalente a:
SELECT "Tabela1". "Nome", "Tabela2". "Classe" FROM "Tabela1" JOIN "Tabela2"
ON "Tabela1". "ClassID" = "Tabela2". "ID"
Aqui os nomes e as classes correspondentes são exibidos. Se um nome não tiver uma classe listada
para ele, esse nome não será incluído na exibição. Se uma classe não tiver nomes, ela também não
será exibida. A adição do INNER não altera isso.
SELECT "Table1". "Name", "Table2". "Classe" FROM "Tabela1" LEFT JOIN
"Tabela2" ON "Tabela1". "ClassID" = "Tabela2". "ID"
Se ESQUERDA for adicionada, todos os "Nomes" de "Tabela1" serão exibidos mesmo que não
tenham "Classe". Se, ao contrário, RIGHT for adicionado, todas as Classes serão exibidas, mesmo
que não tenham nomes. A adição de OUTER não precisa ser mostrada aqui. (Right Outer Join é a
mesma coisa que Right Join; Left Outer Join é a mesma coisa que Left Join.)
SELECT "Tabela1". "Jogador1", "Tabela2". "Jogador2" FROM "Tabela1" AS
"Tabela1" CROSS JOIN "Tabela2" AS "Tabela1" WHERE "Tabela1". "Jogador1" <>
"Tabela2". "Jogador2"
Um CROSS JOIN requer que a tabela seja fornecida com um alias, mas a adição do termo ON
nem sempre é necessária. Todos os registros da primeira tabela são pareados com todos os registros
da segunda tabela. Assim, a consulta acima gera todos os pares possíveis de registros da primeira
tabela com os da segunda tabela, exceto para emparelhamentos entre registros para o mesmo jogador.
No caso de um CROSS JOIN , a condição não deve incluir um link entre as tabelas
especificadas no termo ON . Em vez disso, ONDE as condições podem ser inseridas. Se as
condições são formuladas exatamente como no caso de um simples JOIN, você obtém o mesmo
resultado:
SELECT "Tabela1". "Nome", "Tabela2". "Classe" FROM "Tabela1" JOIN "Tabela2"
ON "Tabela1". "ClassID" = "Tabela2". "ID"
dá o mesmo resultado que
SELECT "Tabela1". "Nome", "Tabela2". "Classe" FROM "Tabela1" AS "Tabela1"
CROSS JOIN "Tabela2" AS "Tabela2" WHERE "Tabela1". "ClassID" = "Tabela2".
"ID"
[WHERE Expressão SQL]
A introdução padrão para condições de solicitar uma filtragem mais precisa dos dados. Aqui também os
relacionamentos entre tabelas são geralmente definidos se eles não estiverem vinculados ao JOIN.
[GROUP BY SQL-Expression [,…]]
Use isso quando quiser dividir os dados da consulta em grupos antes de aplicar as funções a cada um
dos grupos separadamente. A divisão é baseada nos valores do campo ou campos contidos no termo
GROUP BY.
Exemplo:
SELECT "Nome", SUM ("Entrada" - "Saída") AS "Saldo" DE "Tabela1" GROUP BY
"Nome";
Registros com o mesmo nome são somados. No resultado da consulta, a soma de Entrada -
Saída é dada para cada pessoa. Este campo deve ser chamado de saldo . Cada linha do
resultado da consulta contém um valor da tabela "Nome" e o saldo calculado para esse valor
específico.

Quando os campos são processados usando uma função específica (por


exemplo , COUNT, SUM ...), todos os campos que não são processados
Gorjeta
com uma função, mas que devem ser exibidos, são agrupados usando
GROUP BY .

[TENDO SQL Expression]


A fórmula HAVING é muito semelhante à fórmula WHERE . A diferença é que a fórmula WHERE
se aplica aos valores dos campos selecionados na consulta. A fórmula HAVING se aplica a valores
calculados selecionados. Especificamente, t ele ONDE fórmula pode não usar uma função agregada
como parte de uma condição de pesquisa; a fórmula HAVING faz.
A fórmula HAVING serve a dois propósitos, conforme mostrado nos dois exemplos abaixo. No primeiro,
a condição de pesquisa requer que o tempo de execução mínimo seja menor que 40 minutos. No
segundo exemplo, a condição de pesquisa requer que o saldo de um indivíduo seja positivo.
Os resultados da consulta para o primeiro lista os nomes das pessoas cujo tempo de execução foi
menor que 40 minutos pelo menos uma vez e o tempo de execução mínimo. As pessoas cujos tempos
de execução sejam todas maiores que 40 minutos não são listadas.
Os resultados da consulta para o segundo lista os nomes das pessoas que têm uma saída total maior
do que a entrada e seu saldo. As pessoas cujo saldo é 0 ou menor não estão listadas.
Exemplo s :
SELECT "Nome", "Tempo de Execução" FROM "Tabela1" GROUP BY "Nome", "Tempo
de Execução" HAVING MIN ("Tempo de Execução") <'00: 40: 00 ';
SELECT "Name", SUM ("Input" - "Saída") AS "Balance" FROM "Tabela1" GROUP BY
"Nome" HAVING SUM ("Entrada" - "Saída") > 0 ;
[SQL Expression]
Expressões SQL são combinadas de acordo com o seguinte esquema:
Condição [NOT] [{OR | AND} condição]
Exemplo:
SELECT * FROM "Table_name" ONDE NÃO "Return_date" IS NULL E "ReaderID" = 2;
Os registros lidos da tabela são aqueles para os quais um “Return_date” foi inserido e o “ReaderID” é 2.
Na prática, isso significa que todas as mídias emprestadas a uma pessoa específica e retornadas
podem ser recuperadas. As condições são vinculadas apenas ao AND . O NOT refere-se apenas
à primeira condição.
SELECT * FROM "Table_name" onde não ("Return_date" IS NULL e "ReaderID" =
2);
Parênteses em torno da condição, com NOT fora deles, mostram apenas os registros que não
preenchem completamente a condição entre parênteses. Isso abrangeria todos os registros, exceto
aqueles para "ReaderID" número 2, que ainda não foram retornados.
[SQL Expression]: condições
{value [|| v alue]
Um valor pode ser único ou vários valores unidos por duas linhas verticais || . Naturalmente, isso
também se aplica ao conteúdo do campo.
SELECIONE "Sobrenome" || ',' || "First_name" como "nome" FROM "Table_name"
O conteúdo dos campos "Sobrenome" e "Primeiro_nome" são exibidos juntos em um campo chamado
"Nome". Observe que uma vírgula e um espaço são inseridos entre "Sobrenome" e "Primeiro_nome".
| v alue {= | <| <= | > | > = | <> | ! =} v alue
Esses sinais correspondem aos operadores matemáticos conhecidos:
{Equal to | Menos que | Menor ou igual a | Maior que | Maior que ou igual a | Não é igual a | Não é igual
a}
| v alue IS [NOT] NULL
O campo correspondente não tem conteúdo, porque nada foi escrito para ele. Isso não pode ser
determinado unambiguo u escondidas na GUI, uma vez que um campo de texto visualmente vazio não
significa que o campo é totalmente sem conteúdo. No entanto, a configuração padrão no Base é que os
campos vazios no banco de dados são definidos como NULL .
| EXISTS (Query_result)
E x amplo:
SELECT "Name" FROM "Tabela1" WHERE EXISTS (SELECT "First_name" FROM
"Tabela2" WHERE "Tabela2". "First_name" = "Tabela1". "Nome")
Os nomes da Tabela1 são exibidos para os quais os primeiros nomes são fornecidos na Tabela2.
| Valor entre valor e valor
ENTRE v alue1 AND v alue2 produz todos os valores de v alue1 até e incluindo
v alue2. Se os valores forem letras, será usada uma classificação alfabética em que letras minúsculas
terão o mesmo valor que as letras maiúsculas correspondentes.
SELECT "Nome" FROM "Table_name" WHERE "Nome" ENTRE 'A' E 'E';
Essa consulta gera todos os nomes que começam com A, B, C ou D (e também com as letras
minúsculas correspondentes). Como E é definido como o limite superior, os nomes iniciados por E não
são incluídos. A letra E ocorre antes dos nomes que começam com E.
| v alue [NOT] IN ({ v al dente [, ...] | Resultado da consulta})
Isso requer uma lista de valores ou uma consulta. A condição é preenchida se o valor estiver incluído
na lista de valores ou no resultado da consulta.
| v alusão [NOT] LIKE v alo [ESCAPE] v alue}
O operador LIKE é aquele que é necessário em muitas funções simples de pesquisa. O valor é
inserido usando o seguinte padrão:
'%' significa qualquer número de caracteres (incluindo 0),
'_' substitui exatamente um caractere.
Para procurar por ' % ' ou ' _ ', os caracteres devem seguir imediatamente outro caractere
definido como ESCAPE .
SELECT "Nome" FROM "Table_name" WHERE "Nome" LIKE '\ _%' ESCAPE '\'
Esta consulta di s reproduz todos os nomes que começam com um sublinhado. ' \ ' é definido aqui
como o caractere ESCAPE .
[SQL Expression]: v alores
[+ | -] {Expressão [{+ | - | * | / | || } Expressão]
Os valores podem ter um sinal anterior. Adição, subtração, multiplicação, divisão e concatenação de
expressões são permitidas. Um exemplo de concatenação:
SELECT "Sobrenome" || ',' || "First_name" FROM "Tabela"
Desta forma, os registros são exibidos pela consulta com um campo contendo "Sobrenome,
nome_do_primeiro". O operador de concatenação pode ser qualificado pelas seguintes expressões.
| (Condição)
Veja a seção anterior para isso.
| Função ([Parâmetro] [, ...])
Veja a seção sobre Funções no apêndice.
As seguintes consultas também são referidas como subconsultas (subseleções).
| Resultado da consulta que produz exatamente uma resposta
Como um registro pode ter apenas um valor em cada campo, apenas uma consulta que produz
precisamente um valor pode ser exibida integralmente.
| {ANY | ALL} (resultado da consulta que produz exatamente uma resposta de
uma coluna inteira)
Frequentemente há uma condição que compara uma expressão com um grupo inteiro de valores.
Combinado com QUALQUER isso significa que a expressão deve ocorrer pelo menos uma vez no
grupo. Isso também pode ser especificado usando a condição IN . = ANY produz o mesmo
resultado que IN .
Combinado com ALL significa que todos os valores do grupo devem corresponder a uma
expressão.
[SQL Expression]: expressão
{'Texto' | Inteiro | Número de ponto flutuante
| ["Tabela".] "Campo" | TRUE | FALSE | NULO }
Basicamente, os valores servem como argumentos para várias expressões, dependendo do formato
de origem. Para procurar o conteúdo dos campos de texto, coloque o conteúdo entre aspas. Inteiros
são escritos sem aspas, assim como os números de ponto flutuante.
Os campos representam os valores que ocorrem nesses campos na tabela. Normalmente, os campos
são comparados entre si ou com valores específicos. Em SQL, nomes de campos deve ser colocado
entre aspas, pois eles podem não ser corretamente reconhe z ed contrário. Geralmente o SQL assume
que o texto sem aspas duplas é sem caracteres especiais, ou seja, uma única palavra sem espaços e
em maiúsculas. Se várias tabelas estiverem contidas na consulta, o nome da tabela deve ser fornecido
além do nome do campo, separado do último por um ponto.
VERDADEe FALSE geralmente derivam de campos Sim / Não.
NULL significa sem conteúdo. Não é a mesma coisa que 0, mas corresponde a “vazio”.
UNIÃO [ALL | DISTINCT] Query_result
Isso vincula consultas para que o conteúdo da segunda consulta seja gravado sob o primeiro. Para que
isso funcione, todos os campos nas duas consultas devem corresponder ao tipo. Essa ligação de
várias consultas funciona apenas no modo de comando SQL direto.
SELECT "First_name" FROM "Tabela1" UNION DISTINCT SELECT "First_name" FROM
"Tabela2";
Essa consulta gera todos os primeiros nomes de table1 e Table2; o termo adicional DISTINCT
significa que nenhum primeiro nome duplicado será exibido. DISTINCT é o padrão neste contexto.
Por padrão, os primeiros nomes são classificados alfabeticamente em ordem crescente. ALL faz
com que todos os primeiros nomes na Tabela 1 sejam exibidos, seguido pelo primeiro nome na Tabela2.
Nesse caso, o padrão é classificar por chave primária.
MENOS [DISTINCT] | EXCETO [DISTINTO] Query_result
SELECT "First_name" FROM "Tabela1" EXCEPTO SELECT "First_name" FROM
"Tabela2";
Mostra todos os primeiros nomes de table1, exceto os primeiros nomes contidos na Tabela 2.
MINUS e EXCEPT levam ao mesmo resultado. A classificação é alfabética.
INTERSECT [DISTINCT] Query_result
SELECT "First_name" FROM "Tabela1" INTERSECT SELECT "First_name" FROM
"Tabela2";
Isso exibe os primeiros nomes que ocorrem nas duas tabelas. A classificação é novamente alfabética.
Atualmente, isso só funciona no modo de comando SQL direto.
[ORDEM POR Encomenda-Expressão [,…]]
A expressão pode ser um nome de campo, um número de coluna (começando com 1 da esquerda),
um alias (formulado com AS, por exemplo ) ou uma expressão de valor composto (consulte
[SQL Expression]: values). A ordem de classificação geralmente é ascendente ( ASC ). Se você
quiser uma classificação descendente, você deve especificar DESC explicitamente.
SELECT "First_name", "Apelido" AS "Nome" FROM "Tabela1" ORDER BY "Apelido";
é idêntico a
SELECT "First_name", "Apelido" AS "Nome" FROM "Tabela1" ORDER BY 2;
é idêntico a
SELECT "First_name", "Apelido" AS "Nome" FROM "Tabela1" ORDER BY "Nome";

Usando um alias em uma consulta


As consultas podem reproduzir campos com nomes alterados.
SELECT "First_name", "Apelido" AS "Nome" FROM "Tabela1"
O campo Sobrenome é chamado Nome no display.
Se uma consulta envolve duas tabelas, cada nome de campo deve ser precedido pelo nome da tabela:
SELECT "Tabela1". "Primeiro_nome", "Tabela1". "Sobrenome" AS "Nome",
"Tabela2". "Classe" FROM "Tabela1", "Tabela2" WHERE "Tabela1". "Class_ID" =
"Tabela2". " IDENTIDADE"
O nome da tabela também pode receber um apelido, mas isso não será reproduzido na exibição de tabela.
Se esse alias estiver definido, todos os nomes de tabela na consulta deverão ser alterados de acordo:
SELECT "a". "First_name", "a". "Sobrenome" AS "Nome", "b". "Classe" FROM
"Tabela1" AS "a", "Tabela2" AS "b" WHERE "a". Class_ID "=" b "." ID "
A atribuição de um alias para uma tabela pode ser executada de forma mais breve sem usar o termo AS:
SELECT "a". "First_name", "a". "Sobrenome" AS "Nome", "b". "Classe" FROM
"Tabela1" "a", "Tabela2" "b" WHERE "a". "Class_ID" = "b". "ID"
Isso, no entanto, torna o código menos legível. Por causa disso, a forma abreviada deve ser usada
somente em circunstâncias excepcionais.

Consultas para a criação de campos da caixa de listagem


Os campos da caixa de listagem mostram um valor que não corresponde ao conteúdo da tabela
subjacente. Eles são usados para exibir o valor atribuído por um usuário a uma chave estrangeira, em vez
da própria chave. O valor que é finalmente salvo no formulário não deve ocorrer na primeira posição do
campo da caixa de listagem.
SELECT "First_name", "ID" FROM "Tabela1";
Essa consulta mostraria todos os primeiros nomes e os valores de "ID" de chave primária fornecidos pela
tabela subjacente do formulário. Claro que ainda não é o ideal. Os primeiros nomes aparecem sem
classificação e, no caso de nomes próprios idênticos, é impossível determinar qual pessoa é pretendida.
SELECIONE "First_name" || ' '|| "Sobrenome", "ID" DE "Tabela1" ORDER BY
"First_name" ||' '|| "Apelido";
Agora, o primeiro nome e o sobrenome aparecem, separados por um espaço. Os nomes se tornam
distinguíveis e também são classificados. Mas o tipo segue a lógica usual de começar com a primeira letra
da string, então ordena pelo primeiro nome e só depois pelo sobrenome. Uma ordem de classificação
diferente daquela em que os campos são exibidos só seria confusa.
SELECT "Sobrenome" || ',' || "First_name", "ID" FROM "Tabela1" ORDER BY
"Sobrenome" || ',' || "First_name";
Isso agora leva a uma classificação que corresponde melhor ao costume normal. Os membros da família
aparecem juntos, um sob o outro; no entanto, famílias diferentes com o mesmo sobrenome seriam
intercaladas. Para distingui-los, precisaríamos agrupá-los de maneira diferente na tabela.
Há um último problema: se duas pessoas tiverem o mesmo sobrenome e primeiro nome, elas ainda não
serão distinguíveis. Uma solução pode ser usar um sufixo de nome. Mas imagine como ficaria se uma
saudação fosse lida pelo Sr. "Müller II"!
SELECT "Sobrenome" || ',' || "First_name" || ' - ID: '|| "ID", "ID" FROM
"Tabela1" ORDER BY "Sobrenome" ||', '|| "First_name" || "ID";
Aqui todos os registros são distinguíveis. O que é realmente exibido é "Sobrenome, Nome - ID: valor do
ID".
No formulário de empréstimo, há uma caixa de listagem que mostra apenas as mídias que ainda não foram
emprestadas. Ele é criado usando a seguinte fórmula SQL:
SELECIONE "Título" || '- Nr. '|| "ID", "ID" FROM "Mídia" ONDE "ID" NÃO IN
(SELECT "Media_ID" FROM "Empréstimo" ONDE "Return_Date" É NULL) ORDER BY
"Title" || '- Nr. '|| "ID" ASC

Consultas como base para informações adicionais em f ORMs


Se você deseja que um formulário exiba informações adicionais que, de outra forma, não seriam visíveis,
há várias possibilidades de consulta. O mais simples é recuperar essas informações com consultas
independentes e inserir os resultados no formulário. A desvantagem desse método é que as alterações nos
registros podem afetar o resultado da consulta, mas infelizmente essas alterações não são exibidas
automaticamente.
Aqui está um exemplo da esfera de controle de estoque para um simples checkout.
A tabela de verificação contém totais e chaves estrangeiras para itens de estoque e um número de
recebimento. O comprador tem muito pouca informação se não houver nenhum resultado de consulta
adicional impresso no recibo. Afinal, os itens são identificados apenas pela leitura em um código de barras.
Sem uma consulta, o formulário mostra apenas:
Total Código de barras
3 17
2 24
O que está oculto atrás dos números não pode ser visível usando uma caixa de listagem, pois a chave
estrangeira é inserida diretamente usando o código de barras. Da mesma forma, é impossível usar uma
caixa de listagem ao lado do item para mostrar pelo menos o preço unitário.
Aqui uma consulta pode ajudar.
SELECT "Checkout". "Receipt_ID", "Checkout". "Total", "da". "Item", "da".
"Unit_ P arroz", "Checkout". "Total" * "da". "UNIT_PRICE" AS " arroz Total_
P " de "Checkout", "Item", onde "estoque". "ID" = "Checkout". "Item _ ID";
Agora, pelo menos, após a informação ter sido inserida, sabemos quanto precisa ser pago por 3 * Item'17 '.
Além disso, apenas as informações relevantes para o Receipt_ID correspondente precisam ser filtradas
por meio do formulário. O que ainda falta é o que o cliente precisa pagar em geral.
SELECIONE "Checkout". "Receipt_ID", SUM ("Checkout". "Total" * "Stock".
"Unit_price") COMO "Soma" DE "Checkout", "Stock" ONDE "Stock". "ID" =
"Checkout item". " _ ID" GROUP BY "Checkout Receipt_ID "".";
Projete o formulário para mostrar um registro da consulta por vez. Como a consulta é agrupada por
Receipt_ID, o formulário mostra informações sobre um cliente por vez.

Possibilidades de entrada de dados em consultas


Para criar entradas em uma consulta, a chave primária da tabela subjacente à consulta deve estar
presente. Isso também se aplica a uma consulta que vincula várias tabelas juntas.
No empréstimo de mídia, não faz sentido exibir para um leitor itens que já foram retornados há algum
tempo.
SELECT "ID", "Leitor _ ID", "Media _ ID", "Loan_date" de "empréstimo" ONDE
"Return_ D comeu" IS NULL;
Desta forma, um formulário pode mostrar dentro de um campo de controle de tabela tudo o que um
determinado leitor tomou emprestado ao longo do tempo. Aqui também a consulta deve filtrar usando a
estrutura de formulário apropriada (leitor no formulário principal, consulta no subformulário), para que
apenas as mídias realmente emprestadas sejam exibidas. A consulta é adequada para entrada de dados,
pois a chave primária é incluída na consulta.
A consulta deixa de ser editável, se consistir em mais de uma tabela e as tabelas forem acessadas por
meio de um alias. Não faz diferença nesse caso se a chave primária está ou não presente na consulta.
SELECT "Mídia". "ID", "Mídia". "Título", "Categoria". "Categoria",
"Categoria". "ID" AS " K em _ ID" FROM "Mídia", "Categoria" ONDE "Mídia "."
Category_ID "=" Categoria "." ID ";
Essa consulta é editável, pois ambas as chaves primárias são incluídas e podem ser acessadas nas
tabelas sem usar um alias.
SELECT "m". "ID", "m". "Título", "Categoria". "Categoria", "Categoria".
"ID" AS " K em _ ID" FROM "Mídia" AS "m", "Categoria "WHERE" m "."
Category_ID "=" Categoria "." ID ";
Nesta consulta, a tabela "Mídia" é acessada usando um alias. A consulta não pode ser editada.
No exemplo acima, esse problema é facilmente evitado. Se, no entanto, uma subconsulta correlacionada
(na página 145 ) for usada, você precisará usar um alias de tabela. Uma consulta só é editável nesse caso
se contiver apenas uma tabela na consulta principal.

Uso de parâmetros em consultas


Se você costuma usar a mesma consulta básica, mas com valores diferentes a cada vez, consultas com
parâmetros podem ser usadas. Em princípio, consultas com parâmetros funcionam como consultas para
um subformulário:
SELECT "ID", "ReaderID", "Media_ID", "Empréstimo_date" FROM "Empréstimos"
ONDE "Return_ D ate" IS NULL E "Reader_ID" = 2;
Esta consulta mostra apenas a mídia emprestada ao leitor com o número 2.
SELECT "ID", "Reader_ID", "Media_ID", "Empréstimo_date" FROM "Empréstimos"
ONDE "Return_ D ate" IS NULL E "Reader_ID" =: Readernumber;
Agora, quando você executa a consulta, um campo de entrada é exibido. Ele solicita que você insira um
número de leitor. Seja qual for o valor que você inserir aqui, a mídia atualmente emprestada a esse leitor
será exibida.
Ao usar formulários, o parâmetro pode ser passado do formulário principal para um subformulário. No
entanto, às vezes, as consultas que usam parâmetros nos subformulários não são atualizadas, se os
dados forem alterados ou forem inseridos novamente.
Muitas vezes, seria bom alterar o conteúdo das caixas de listagem usando as configurações no formulário
principal. Assim, por exemplo, poderíamos impedir que a mídia de biblioteca fosse emprestada a indivíduos
que estão banidos de tomar emprestada mídia. Infelizmente controlar as configurações de caixa de lista
neste personali z maneira ed usando parâmetros não é possível.

Subqueries
As subconsultas construídas em campos sempre podem retornar apenas um registro. O campo também
pode retornar apenas um valor.
SELECIONAR "ID", "Renda", "Despesas", (SELECIONAR SOMA ("Renda") - SOMA
("Despesas") DE "Verificação de Saída") COMO "Saldo" DE "Verificação";
Esta consulta permite a entrada de dados (chave primária incluída). A subconsulta produz precisamente
um valor, ou seja, o saldo total. Isso permite que o saldo no caixa seja lido após cada entrada. Isso ainda
não é comparável com o formulário de verificação de supermercado descrito em “ Consultas como base
para informações adicionais em formulários ”. Naturalmente, faltam os cálculos individuais de Total *
Unit_price, mas também a presença do número do recibo. Apenas a soma total é dada. Pelo menos, o
número do recibo pode ser incluído usando um parâmetro de consulta:
SELECT "ID", "Renda", "Despesas", (SELECT SUM ( "Lucro") - SUM (
"Despesas") de "Checkout" ONDE "Receipt_ID" =: Receipt_ N umber) como
"equilíbrio" de "Checkout" ONDE "Receipt_ID" =: Receipt_ N úmero;
Em uma consulta com parâmetros, o parâmetro deve ser o mesmo em ambas as instruções de consulta,
se é para ser reconhe z ed como um parâmetro.
Para subformulários, esses parâmetros podem ser incluídos. O subformulário recebe, em vez de um nome
de campo, o nome do parâmetro correspondente. Esse link só pode ser inserido nas propriedades do
subformulário e não quando o Assistente for usado.

Subformulações baseadas em consultas não são atualizadas


Nota automaticamente com base em seus parâmetros. É mais apropriado passar o
parâmetro diretamente do formulário principal.

Subconsultas Correlacionadas
Usando uma consulta ainda mais refinada, uma consulta editável permite que uma pessoa carregue o
saldo em execução para o caixa de depósito:
SELECT "ID", "Renda", "Despesas", (SELECT SUM ("Renda") - SUM ("Despesas")
DE "Checkout" ONDE "ID" <= "a". "ID") AS "Saldo" FROM "Checkout" COMO "a"
ORDER BY "ID" ASC
A tabela de check-out é a mesma que a tabela "a". "a", no entanto, produz apenas a relação com os valores
atuais neste registro. Dessa forma, o valor atual do ID da consulta externa pode ser avaliado na
subconsulta. Assim, dependendo do ID, o saldo anterior no tempo correspondente é determinado, se você
partir do fato de que o ID, que é um autovalor, é incrementado sozinho.

Consultas como tabelas de origem para consultas


Uma consulta é necessária para definir um bloqueio contra todos os leitores que receberam um terceiro
aviso atrasado para um meio.
SELECIONAR "Empréstimo". "Reader_ID", "Terceiro Expirado - o leitor está na
lista negra 'COMO" Bloquear "
FROM (SELECT COUNT ("Date") como " Total_Count ", "Loan_ID" FROM "Recupera"
GROUP BY "Loan_ID") como "a", "Empréstimo"
WHERE "a". "Loan_ID" = "Empréstimo". "ID" AND "a". " Total_Count "> 2
Primeiro, vamos examinar a consulta interna , à qual a consulta externa se relaciona. Nessa consulta, o
número de entradas de data, agrupadas pela chave externa Loan_ID, é determinado. Isso não deve
depender do R eader_ID, um s que causaria não apenas três avisos atrasados para um único meio, mas
também três mídias com um aviso em atraso cada um a ser contado. A consulta interna recebe um alias
para que possa ser vinculada ao Reader_ID da consulta externa.
A consulta externa refere-se, neste caso, apenas à fórmula condicional da consulta interna. Ele mostra
apenas um Reader_ID e o texto para o campo Lock quando o " Empréstimo", "ID" e " a". "Loan_ID" são
iguais e " a". " Total_Count " > 2 .
Em princípio, todos os campos da consulta interna estão disponíveis para o externo. Assim, por exemplo, a
soma "a". " Total_Count " pode ser mesclada na consulta externa para fornecer o total das multas reais.
No entanto, pode acontecer, na caixa de diálogo Q uery Design , que o Modo Design View não funcione
mais depois de tal construção. Se você tentar abrir a consulta para edição novamente, receberá o seguinte
aviso:

Se você, em seguida, abrir a consulta para edição na vista de SQL e tentar mudar de lá para o projeto V
iew, você recebe a mensagem de erro:

O Modo Design View não pode encontrar o campo contido na consulta interna " Loan_ID" , que controla o
relacionamento entre as consultas interna e externa.
Quando a consulta é executada no modo SQL , o conteúdo correspondente da subconsulta é reproduzido
sem erros. Portanto, você não não tem que usar o modo SQL direto neste caso.
A consulta externa usou os resultados da consulta interna para produzir os resultados finais. Estes são
uma lista dos valores "Loan_ID" que devem ser bloqueados e por quê. Se você quiser limitar ainda mais os
resultados finais, use as funções de classificação e filtro da interface gráfica do usuário.

Summari z ing dados com consultas


Quando os dados são pesquisados em um banco de dados inteiro, o uso de funções de formulário simples
geralmente leva a problemas. Um formulário refere-se, afinal de contas, a apenas uma tabela e a função de
pesquisa é movida apenas pelos registros subjacentes desse formulário.
Obter todos os dados é mais simples quando você usa consultas, que podem fornecer uma imagem de
todos os registros. A seção sobre " Definição de relacionamento na consulta " sugere essa construção de
consulta. Isso é construído para o banco de dados de exemplo da seguinte maneira:
SELECIONAR "Mídia". "Título", "Legenda", "Legenda", "Autor". "Autor"
FROM "Mídia"
LEFT JOIN "Subtitle" ON "Mídia". "ID" = "Subtítulo". "Media_ID"
LEFT JOIN "rel_Media_Author" ON "Mídia". "ID" = "rel_Media_Author".
"Media_ID"
LEFT JOIN "Autor" ON "rel_Media_Author". "Author_ID" = "Autor". "ID"
Aqui todos os "Títulos", "Legendas" e "Autores" são exibidos juntos.
A tabela de mídia contém um total de 9 títulos. Para dois desses títulos, há um total de 8 legendas. Sem um
LEFT JOIN , ambas as tabelas exibidas juntas geram apenas 8 registros. Para cada subtítulo, o
título correspondente é procurado e esse é o final da consulta. Títulos sem legenda não são mostrados.
Agora, para mostrar todas as mídias, incluindo aquelas sem legendas: A mídia está no lado esquerdo da
tarefa, a legenda no lado direito. Um LEFT JOIN mostrará todos os títulos da mídia, mas apenas um
subtítulo para aqueles que têm um título. A mídia se torna a tabela decisiva para determinar quais registros
devem ser exibidos. Isso já estava planejado quando a mesa foi construída (veja C apítulo 3, Tabelas).
Como existem legendas para dois dos nove títulos, a consulta agora exibe 9 + 8 - 2 = 15 registros.

Nota A ligação normal das tabelas, depois de todas as tabelas terem sido contadas,
segue a palavra-chave WHERE.
Se houver um LEFT JOIN ou um RIGHT JOIN , a atribuição é
definida diretamente após os dois nomes de tabela usando ON . Portanto, a
seqüência é sempre
Tabela1 LEFT JOIN Table2 ON Table1.Field1 =
Table2.Field1 LEFT JOIN Table3. Table2. Field1 =
Table3.Field1 ...

Dois títulos da tabela Mídia ainda não possuem uma entrada de autor ou uma legenda. Ao mesmo tempo,
um título tem um total de três autores. Se a tabela de autor estiver vinculada sem um LEFT JOIN, as
duas mídias sem um autor não serão exibidas. Mas como um meio tem três autores em vez de um, o
número total de registros exibidos ainda será 15.
Só usando LEFT JOIN irá a consulta ser instruídos a usar a mídia t capaz de determinar quais
registros para mostrar. Agora os registros sem Subtitl e ou Author aparecem novamente, dando um total de
17 registros.
O uso de Joins apropriados geralmente aumenta a quantidade de dados exibidos. Mas esse conjunto de
dados ampliado pode ser facilmente verificado, pois os autores e legendas são exibidos além dos títulos.
No banco de dados de exemplo, todas as tabelas dependentes de mídia podem ser acessadas.

Acesso mais rápido a consultas usando visualizações de tabela


As visualizações no SQL são mais rápidas que as consultas, especialmente para bancos de dados
externos, pois estão ancoradas diretamente no banco de dados e o servidor retorna apenas os resultados.
Por contraste, as consultas são primeiro enviadas para o servidor e processadas lá.
Se uma nova consulta estiver relacionada a outra consulta, a visualização SQL na Base fará a outra
consulta parecer uma tabela. Se você criar uma vista a partir dele, você pode ver que você está realmente
trabalhando com uma subconsulta (selecione usado dentro de outra seleção ). Por causa disso, uma
Consulta 2 relacionada a outra Consulta 1 não pode ser executada usando o comando Editar> Executar
SQL diretamente , já que apenas a interface gráfica do usuário e não o próprio banco de dados conhecem
a Consulta 1.
O banco de dados não oferece acesso direto a consultas. Isso também se aplica ao acesso usando
macros. Visualizações, por outro lado, pode ser acessado a partir de ambas as macros e mesas. No
entanto, nenhum registro pode ser editado em uma exibição. (Eles devem ser editados em uma tabela ou
formulário.)

Uma consulta criada usando Criar consulta no SQL View tem a


desvantagem de não poder ser classificada ou filtrada usando a GUI. Existem,
portanto, limites para seu uso.
Gorjeta Um View, por outro lado, pode ser gerenciado no Base como uma tabela
normal - com a exceção de que nenhuma alteração nos dados é possível.
Aqui, portanto, mesmo em comandos SQL diretos, todas as possibilidades de
classificação e filtragem estão disponíveis.

As visualizações são uma solução para muitas consultas, se você quiser obter algum resultado. Se por
exemplo, um Subselect é para ser usado no resultado s de uma consulta, criar uma exibição que lhe dá
esses resultados. Em seguida, use a subseleção na visualização. Exemplos correspondentes são para ser
encontrados em C apítulo 8, Tarefas de banco de dados.
Criar uma vista a partir de uma consulta é bastante fácil e direto.
1)Clique no objeto Table na seção Database.
2)Clique em Criar Vista .
3)Feche o diálogo Adicionar Tabela.
4)Clique no ícone Design View On / OFF. (Este é o modo SQL para uma vista.)
5)Obtendo o SQL para o View:
a)Edite a consulta no SQL View.
b)Use Control + A para realçar o SQL da consulta.
c)Use Control + C para copiar o SQL.
6)No Modo SQL da Vista use Control + V para colar o SQL.
7)Feche, salve e nomeie a exibição.
Capítulo 6
Relatórios
Criando relatórios usando o Report Builder
Os relatórios são usados para apresentar dados de uma forma que os torna facilmente entendidos por
pessoas sem conhecimento do banco de dados. Relatórios podem:
•P ressentem dados em tabelas fáceis de ler
•C gráficos reate para a exibição de dados
•M ake possível usar os dados para impressão de etiquetas
•P cartas de formulário roduce tais como facturas, avisos de recall, ou notificações para as pessoas se
juntam ou abandonam uma associação
Para criar um relatório, é necessário um trabalho preparatório cuidadoso no banco de dados subjacente. Ao
contrário de um formulário, um relatório não pode incluir sub-relatórios e, portanto, incorporar fontes de
dados adicionais. Nenhum relatório pode apresentar elementos de dados diferentes daqueles que estão
disponíveis na fonte de dados subjacente, como um formulário pode fazer usando caixas de listagem.
Os relatórios são preparados melhor usando consultas. Desta forma, todas as variáveis podem ser
determinadas. Em particular, se a classificação dentro do relatório for necessária, sempre use uma
consulta que faça provisão para classificação. Isso significa que as consultas no modo SQL direto devem
ser evitadas sob essas condições. Se você precisar usar uma consulta desse tipo em seu banco de
dados, poderá executar a classificação criando primeiro uma exibição da consulta. Essa visão sempre
pode ser classificada e filtrada usando a interface gráfica do usuário (GUI) da Base.

Ao usar o Report Builder, você deve salvar seu trabalho com frequência
durante a edição. Além de salvar no próprio Report Builder após cada etapa
Cuidado significativa, você também deve salvar o banco de dados inteiro.
Dependendo da versão do LibreOffice que você está usando, o Report Builder
pode falhar durante a edição.
A funcionalidade dos relatórios concluídos não é afetada, mesmo que tenham
sido criados em outra versão, na qual o problema não ocorre.

O u Ser i nterface do Report Builder


Para iniciar o Report Builder a partir do Base, use Reports > Create Report in Design View .
A janela inicial do Report Builder (figura45 ) mostra três partes. À esquerda, a divisão atual do relatório no
cabeçalho da página, no detalhe e no rodapé da página; no meio estão as áreas correspondentes onde o
conteúdo será inserido; e, à direita, as propriedades dessas regiões são mostradas.
Ao mesmo tempo, a caixa de diálogo Adicionar campos é exibida. Este diálogo corresponde ao da criação
de formulário. Cria campos com seus rótulos de campo correspondentes.
Sem conteúdo do banco de dados, um relatório não tem função adequada. Por esse motivo, a caixa de
diálogo é aberta na guia Dados. Aqui você pode definir o conteúdo do relatório; no exemplo é a exibição _
Report_Recall t capaz. Contanto que o comando Analisar SQL esteja definido como Sim , o relatório
poderá ser submetido a classificação, agrupamento e filtragem. Uma visão foi escolhida para a base deste
relatório, portanto nenhum filtro será aplicado; i t já foi incluído na consulta subjacente à vista.
Figura 45: Janela inicial do Report Builder

Dois formatos de saída para relatórios estão disponíveis para seleção: Documento de texto ODF (um
documento do Writer) ou Planilha do ODF (um documento do Calc). Se você quiser apenas uma
visualização tabular dos seus dados, o documento do Calc definitivamente deve ser escolhido para o seu
relatório. É significativamente mais rápido criar e também é mais fácil de formatar posteriormente, pois há
menos opções a serem consideradas e as colunas podem ser facilmente arrastadas para a largura
desejada posteriormente .
Por padrão, o Construtor de Relatórios procura por sua fonte de dados na primeira tabela do banco de
dados. Isso garante que pelo menos um teste das funções seja possível. Uma fonte de dados deve ser
escolhida antes que o relatório possa ser fornecido com campos.
O Report Builder fornece muitos botões adicionais, portanto, a tabela na próxima página mostra os botões
com suas descrições. Os botões para alinhar elementos não são descritos mais detalhadamente neste
capítulo. Eles são úteis para o ajuste rápido de campos em uma única área do Report Builder, mas, em
princípio, tudo pode ser feito pela edição direta das propriedades do campo.
Botões para edição de conteúdo Botões para alinhar elementos
Assim como nos formulários, é útil usar o navegador apropriado. Por exemplo, um clique imprudente no
início do Criador de relatórios pode dificultar a localização das propriedades dos dados do relatório. Esses
dados só podem ser acessados pelo navegador de relatórios. L eft clique sobre Relatório e as propriedades
do relatório são uma vez mais acessível.

Inicialmente, o navegador mostra, além das seções visíveis do documento (cabeçalho da página, grupos,
detalhes e rodapé da página), a possibilidade de incluir funções. Os grupos podem ser usados, por
exemplo, para atribuir todas as mídias que estão sendo chamadas à pessoa que as emprestou, para evitar
vários avisos de recall. As áreas de detalhes mostram os registros pertencentes a um grupo. Funções são
usadas para cálculos como somas.
Para obter resultados úteis no exemplo acima, o conteúdo da visualização deve ser reproduzido com
agrupamento adequado. Cada leitor deve estar vinculado aos avisos de recall de todas as mídias
emprestadas e atrasadas.
Ver > Ordenação e Agrupamento ou o botão correspondente inicia a função de agrupamento.

Figura 46: Ordenação e Agrupamento


Aqui agrupamento e classificação são pelo campo Reader_Name . Campos adicionais também podem ser
incluídos na tabela acima. Por exemplo, se você também quiser agrupar e classificar pelo campo
Loan_Date , escolha essa como a segunda linha.
Diretamente sob a tabela, várias ações de agrupamento estão disponíveis para seleção. Você pode mover
um grupo para cima ou para baixo na lista ou removê-lo completamente. Como apenas um grupo é
necessário para o relatório planejado, a Figura 46 mostra apenas o símbolo Excluir na extrema direita das
ações do grupo, conforme disponível.
A propriedade de classificação é autoexplicativa.
Quando a entrada foi criada, o lado esquerdo do Report Builder mostrou imediatamente uma nova divisão.
Ao lado da descrição do campo Reader_Name, você pode ver o cabeçalho . Esta seção é para o
cabeçalho do grupo no relatório. O cabeçalho pode conter o nome da pessoa que receberá o aviso de
recall. Nesse caso, não há rodapé de grupo. Tal rodapé pode conter a multa devida, ou o local e data atual e
um espaço para a assinatura da pessoa que envia o aviso.
Por padrão, há um novo grupo para cada valor. Então, se o Reader_Name mudar, um novo grupo será
iniciado. Alternativamente, você pode agrupar por letra inicial. No caso de um aviso de recall, no entanto,
isso colocaria todos os leitores com a mesma inicial juntos em um grupo. Schmidt, Schulze e Schulte
receberiam um aviso de recall comum, o que seria bastante inútil neste exemplo.
Ao agrupar por letra inicial, você pode especificar quantas letras depois o próximo grupo deve começar.
Pode-se imaginar, por exemplo, um agrupamento para uma pequena lista telefônica. De acordo com o
tamanho da lista de contatos, pode-se imaginar um agrupamento em cada segunda letra inicial. Então A e B
formariam o primeiro grupo, depois C e D, e assim por diante.
Um grupo pode ser definido para ser mantido em conjunto com a primeira seção de detalhes ou, na medida
do possível, como um grupo completo. Por padrão, essa opção está definida como Não . Para avisos de
rechamada, você provavelmente desejaria que o grupo fosse organizado de modo que uma página
separada fosse impressa para cada pessoa que receberia uma carta de rechamada. Em outro menu, você
pode escolher que cada grupo (neste caso, cada nome de leitor) seja seguido por uma quebra de página
antes de lidar com o próximo valor.
Se você optou por ter um cabeçalho de grupo e talvez um rodapé de grupo, esses elementos aparecerão
como seções no navegador de relatórios sob o nome de campo correspondente Reader_Name . Aqui
também você tem a possibilidade de usar funções, que serão limitadas a este grupo.
T o adicionar campos, nos um e do Adicionar campo função, como com formas. No entanto, neste caso, o
rótulo e o conteúdo do campo não estão vinculados. Ambos podem ser movidos independentemente,
alterados em tamanho e arrastados para seções diferentes.

Figura 47: Design do relatório, por exemplo, aviso de recall


Figura 47 mostra o design do relatório para o aviso de recall. No cabeçalho da página está o cabeçalho
Libre Office Library, inserido como um campo de rótulo. Aqui você também pode ter um papel timbrado
com um logotipo, já que a incorporação de gráficos é possível. O fato de esse nível ser chamado de
cabeçalho de página não implica que não haja espaço acima dele. Isso depende das configurações da
página; Se uma margem superior foi definida, ela fica acima do cabeçalho da página.
O cabeçalho Reader_Name é o cabeçalho dos dados agrupados e classificados. Nos campos que devem
conter dados, os nomes dos campos de dados correspondentes são exibidos em cinza claro. Assim, por
exemplo, a visualização subjacente ao relatório tem um campo denominado Endereço, contendo o
endereço completo do destinatário com rua e cidade. Colocar isso em um único campo requer quebras de
linha na consulta. Você pode usar o CHAR (13) para criá-los.
Exemplo:
SELECIONE "Nome" || ' '|| "Sobrenome" || CHAR (13) || "Rua" ||' '||
"Não" || CHAR13 || "Código postal" ||' '|| "Town" FROM "nome"
O campo = TODAY () representa uma função interna, que insere a data atual nessa posição.
No cabeçalho Reader_Name , além da saudação, vemos os títulos das colunas para a seguinte exibição
de tabela. Esses elementos devem aparecer apenas uma vez, mesmo que várias mídias estejam listadas.
No fundo desses cabeçalhos de coluna há um retângulo cinza, que também serve como um quadro para
os dados.
A área de detalhes é repetida com a mesma freqüência que existem registros separados com os mesmos
dados de Reader_Name . Aqui estão listadas todas as mídias que não foram devolvidas a tempo. Há outro
retângulo no fundo para enquadrar o conteúdo. Este retângulo é preenchido com branco em vez de cinza.

Em princípio, o L ibre O ffice fornece a possibilidade de adicionar linhas


horizontais e verticais. Estes são exibidos no modo de design. No momento,
eles não aparecem quando o relatório está completo.
Nota Essas linhas têm a desvantagem de serem interpretadas apenas como linhas
aéreas. Eles podem ser reproduzidos melhor se forem usados retângulos.
Configure o fundo do retângulo para preto e o tamanho para , por exemplo,
17cm de largura e 0,03cm de altura. Isto irá criar uma linha horizontal com uma
espessura de 0,03 cm e um comprimento de 17 cm.

O rodapé Reader_Name fecha a carta com uma fórmula de saudação e uma área para a assinatura. O
rodapé é tão definido que uma quebra de página adicional ocorrerá após essa área. Além disso, ao
contrário da configuração padrão, é especificado que essa área deve ser mantida em conjunto em todos os
casos. Afinal, seria muito estranho se muitos avisos de recall tivessem a assinatura em uma página
separada.
Manter juntos refere-se aqui à quebra de página. Se você quiser que o conteúdo de um registro seja
mantido em conjunto independentemente da quebra, isso só é possível no momento, se o registro não for
lido como Detalhes, mas for usado como base para um agrupamento. Você pode escolher Manter juntos =
Sim , mas não funciona; a área Detalhes fica separada. Você tem que colocar o conteúdo dos detalhes em
um grupo separado para mantê-lo juntos.
Uma função interna é usada para calcular as multas totais.
Abaixo está o que um aviso de recall real seria semelhante. A área de detalhes contém 5 mídias que o leitor
retirou por empréstimo. O rodapé do grupo contém a multa total devida.
Os relatórios para registros únicos também podem se estender por mais de
uma página. O tamanho do relatório é bem separado do tamanho da página.
No entanto, o alongamento da área de detalhes em mais de uma página pode
levar a quebras falhas. Aqui, o Report Builder ainda tem problemas em calcular
o espaçamento corretamente. Se ambas as áreas de agrupamento e
Nota elementos gráficos forem incluídos, isso pode resultar em tamanhos
imprevisíveis para determinadas áreas.
Até agora, os elementos individuais podem ser movidos para posições fora do
tamanho de uma única página apenas com as teclas do mouse e do cursor. As
propriedades dos elementos sempre fornecem a mesma distância máxima do
canto superior de qualquer área que esteja na primeira página.

Propriedades gerais dos campos


Existem apenas três tipos de campo para a apresentação de dados. Além dos campos de texto (que, ao
contrário do nome, também podem conter números e formatação), há também um tipo de campo que pode
conter imagens do banco de dados. O campo do gráfico exibe um resumo dos dados.
Como nos formulários, os campos recebem nomes. Por padrão, o nome é o do campo do banco de dados
subjacente.
Um campo pode ser configurado para ser invisível. Isso pode parecer um pouco inútil no caso de campos,
mas é útil para cabeçalhos e rodapés de grupo, que podem ser necessários para executar outras funções
do agrupamento sem conter nada que precise ser exibido.
Se Imprimir valores repetidos estiver desativado, a exibição do campo será inibida quando um campo com
o mesmo conteúdo for carregado diretamente antes. Isso funciona corretamente apenas para campos de
dados que contêm texto. Campos numéricos ou campos de data ignoram a instrução de desativação, os
campos Label são completamente desbotados quando desativados, mesmo que ocorram apenas uma vez.
No Report Builder, a exibição de determinado conteúdo pode ser inibida usando a Expressão de Impressão
Condicional ou o valor do campo pode ser usado como base para formatar texto e plano de fundo. Mais
sobre expressões condicionais é dado em “Impressão condicional ” na página 169 .
A configuração da roda do mouse não tem efeito porque os campos do relatório não são editáveis. Parece
ser uma sobra da caixa de diálogo de definição de formulário.
A impressão Ao Mudança Grupo função não poderia ser reproduzida em relatórios também.
Se o plano de fundo não estiver definido como transparente, uma cor de plano de fundo poderá ser definida
para cada campo.
As outras entradas lidam com o conteúdo interno do campo em questão. Isso cobre a fonte (para cor da
fonte, peso da fonte e assim por diante, consulte a Figura 48 ), o alinhamento do texto dentro do campo e a
formatação com a caixa de diálogo Caractere correspondente (consulte a Figura 49 ).

Figura 48 : Fontes: Configurações de Caracteres


Figura 49: Formatando números

Propriedades especiais de controles gráficos

Um controle gráfico pode conter gráficos de dentro e de fora do banco de dados. Infelizmente, não é
possível no momento armazenar um gráfico, como um logotipo, permanentemente na Base. Por isso, é
essencial que o gráfico está disponível no caminho de procura, mesmo quando você é apresentado com a
escolha de incorporar, em vez de imagens ligando e o primeiro campo Configurar uma s l de tinta pode ser
definido (literalmente fechado) a uma funcionalidade planejada correspondente. Esta é uma das várias
funções que estão previstas para Base e estão na GUI mas ha ve n o t realmente foi implementado ainda-
para que os botões e caixas de seleção não têm nenhum efeito .
Como alternativa, é claro, um gráfico pode ser armazenado no próprio banco de dados e, assim, fica
disponível internamente. Mas, nesse caso, ele deve estar acessível por meio de um dos campos da
consulta subjacente ao relatório.
Para pegar um gráfico externo, use o botão de seleção ao lado do campo Gráfico para carregá-lo. Para
carregar o campo do banco de dados de agendamento, especifique o campo na guia Dados .
A configuração de alinhamento vertical parece não ter nenhum efeito durante o estágio de projeto. Quando
você chama o relatório, no entanto, o gráfico aparece na posição correta.
Ao dimensionar, você pode selecionar Não , Manter proporção ou Autom. Tamanho . Isso corresponde às
configurações de um formulário:
•Não : a imagem não está ajustada ao controle. Se for muito grande, uma versão recortada será mostrada.
A imagem original não é afetada por isso.
•Manter a proporção : a imagem é ajustada ao controle, mas não distorcida.
•Tamanho automático : a imagem é ajustada ao controle e, em alguns casos, pode ser distorcida.
Incorporando gráficos no relatório
Você pode inserir c cervos i nto um relatório por usando o controle correspondente ou com Inserir >
controles de relatório > Gráfico . Um gráfico é a única maneira de reproduzir dados que não são
encontrados na fonte de dados especificada para o relatório. Um gráfico pode, portanto, ser visto como um
tipo de sub-relatório, mas também como um componente autônomo do relatório.
Você deve desenhar o lugar para o gráfico usando o mouse. Nas propriedades gerais, além dos campos
familiares, você pode choos um e um tipo de gráfico (ver os tipos correspondentes no Calc). Além disso,
você pode definir um número máximo de registros para a visualização, o que dará uma impressão de como
o gráfico finalmente será exibido.
Os gráficos podem ser formatados da mesma maneira que no Calc (clique duas vezes no gráfico). Para
mais informações, consulte a descrição no Guia do LibreOffice Calc .

O gráfico está vinculado na seção Dados com os campos de dados necessários. Aqui, em um exemplo de
lista de Top 10 de mídia , o gráfico mostra a frequência com que determinadas mídias são emprestadas. O
Editor de Consultas é usado para criar um comando SQL adequado, como você faria para uma caixa de
listagem em um formulário. A primeira coluna na consulta será usada para fornecer os rótulos para as
barras verticais no gráfico, enquanto a segunda coluna gerará o número total de transações de empréstimo,
mostrado na altura das barras.
No exemplo acima, o gráfico mostra muito pouco no início, uma vez que apenas empréstimos de teste
limitados foram executados antes do comando SQL ser emitido.
O gráfico na próxima página , do banco de dados de associação de uma sociedade (em alemão:
Mitgliederstatistik), foi preparado a partir de uma consulta que precisa ser inserida no modo SQL direto, pois
a interface gráfica do usuário não a entende. Por esse motivo, Não (Alemão: Nein) foi escolhido para o
comando Analisar SQL , uma opção que exclui qualquer filtragem e classificação com as ferramentas
internas do Report Builder. Portanto, esses campos estão esmaecidos. Nas propriedades de dados do
gráfico, Consulta (Alemão: Abfrage) foi inserida.
Os campos são vinculados da mesma maneira que para um formulário principal com um subformulário. No
relatório em si, as distribuições de idade dos membros masculinos e femininos são listadas em forma de
tabela. Eles estão agrupados por gênero. Cada grupo recebe seu próprio gráfico. Assim que o gráfico
contém apenas dados para o gênero correto, o Gender fi eld (alemão: Geschlecht) no relatório i s ligados ao
Sexo no gráfico .

Figura 50: Campos vinculados para um gráfico, o mesmo que em formulários. Este exemplo é n o t
traduzido, porque o relatório é nt parte do exemplo de base de dados.

A criação de gráficos funciona atualmente apenas nas versões 3.3. xe 3.4. x .


A partir da Versão 3.5, o L ibre O ffice não pode mais abrir esses relatórios.
Eles ainda podem ser produzidos, no entanto.
Nota
O LibreOffice não é o único programa que tem problemas com gráficos . Na
versão 3.3 do OpenOffice. org , a exibição também não funciona. Escritório
aberto. org abre os relatórios, mas com os gráficos faltando.

Propriedades de dados de f fields


Na caixa de diálogo de propriedades, a guia Dados mostra, por padrão, apenas o campo do banco de
dados a partir do qual os dados desse campo de relatório serão lidos. Entretanto, além dos campos Field e
Formula, os tipos Function , Counter e User-defined function estão disponíveis.
Você pode selecionar antecipadamente o Soma, Mínimo, um nd máximas de f unções . Eles vão aplicar
tanto para o grupo atual ou para todo o relatório. Essas funções podem causar problemas se um campo
estiver vazio (NULL). Nesses campos, se tiverem sido formatados como números, " NaN" será exibido;
isto é, não há valor numérico presente. Para campos vazios, nenhum cálculo é executado e o resultado é
sempre 0.
Esses campos podem ser reformatados para exibir um valor de 0 usando a seguinte fórmula na área de
dados da exibição.
IF ([numericfield]; [numericfield]; 0)
Essa função calcula com o valor real de um campo sem valor. Parece mais simples formular a consulta
subjacente para o relatório para que 0 seja fornecido em vez de NULL para campos numéricos.
O Contador conta apenas os registros que ocorrerão no grupo ou no relatório como um todo. Se o contador
for inserido na área Detalhes, cada registro será fornecido com um número em execução. A numeração
será aplicada somente aos registros no grupo ou no relatório inteiro.

Finalmente, a função detalhada definida pelo usuário está disponível. Pode acontecer de o próprio Report
Builder escolher essa variante, se um cálculo tiver sido solicitado, mas, por algum motivo, não puder
interpretar corretamente a fonte de dados.

Funções no Report Builder


O Report Builder fornece uma variedade de funções, tanto para exibir dados quanto para definir condições.
Se isso não for suficiente, as funções definidas pelo usuário podem ser criadas usando etapas de cálculo
simples, que são particularmente úteis em rodapés de grupos e resumos.

Entrando f ormulas
O Report Builder é baseado no Pentaho Report Builder. Uma pequena parte de sua documentação é em h
ttp: //wiki.pentaho.com/display/Reporting/9.+Report+Designer+Formula+Expressions .
Uma outra fonte são as Especificações para o Padrão OpenFormula:
http://www.oasis-open.org/committees/download.php/16826/openformula-spec-20060221.html
Princípios básicos:

Fórmulas começam com um sinal de igual. =


Referências a campos de dados são colocadas [Nome do campo]
entre colchetes.
Se os campos de dados contiverem caracteres [ " Este nome deve estar
especiais (incluindo espaços), o nome do entre aspas " ]
campo também deve ser colocado entre aspas.
A entrada de texto deve estar sempre entre " Entrada de texto "
aspas duplas.
Os seguintes operadores são permitidos. +, -,
* (Multiplicação),
/ (Divisão),
% (divide o número precedente por 100),
^ (Aumenta para o poder do número seguinte),
& (concatenar texto),
Os seguintes relacionamentos são possíveis. =, <>, <, <=,>,> =
Os suportes redondos são permitidos. ()
Mensagem de erro padrão. NA (não disponível)
Mensagem de erro para um campo vazio que NaN (talvez "não um número"?)
foi definido como um número.
Toda entrada de fórmula se aplica somente ao registro atual. Relacionamentos com registros anteriores ou
posteriores, portanto, não são possíveis.

Ao lado do campo de data há um botão com três pontos sempre que uma fórmula pode ser inserida. Este
botão inicia o Assistente de funções.

No entanto, existem muito menos funções do que no Calc. Muitas funções têm equivalentes do Calc. O
Assistente calcula o resultado da função diretamente.
O Assistente de Funções nem sempre funciona perfeitamente. Por exemplo, as entradas de texto não são
ocupadas por aspas duplas. No entanto, somente entradas com aspas duplas são processadas ao iniciar a
função.
As seguintes funções estão disponíveis:
Função Descrição
Funções de data e hora
ENCONTRO Produz uma data válida a partir de valores numéricos para o
ano, o mês e o dia.
DATEDIF Retorna o total de anos, meses ou dias entre dois valores de
(DAY | MONTH | YEAR) data.
DATEVALUE Converte uma entrada de data americana em formato de texto
(cotado) em um valor de data. A variante americana que é
produzida pode ser reformatada.
DIA Retorna o dia do mês para uma determinada data.
DAY ([campo de data])
DIAS Retorna o número de dias entre duas datas.
HORA Retorna as horas de um determinado horário no formato de 24
horas.
HOUR ([DateTimeField]) calcula as horas no campo.
MINUTO Retorna os minutos de uma data no formato numérico interno
MINUTE ([Timefield]) calcula a parte dos minutos da hora.
MÊS Retorna o mês para uma data inserida como um número.
MÊS ([Campo de data])
AGORA Retorna a data e hora atuais.
SEGUNDO Retorna os segundos de uma data no formato numérico
interno.
SECOND (NOW ()) mostra a parte dos segundos da hora em
que o comando é executado.
TEMPO Mostra a hora atual.
VALOR DO TEMPO Converte uma entrada de texto por um tempo em um valor de
tempo para cálculos.
HOJE Mostra a data atual.
WEEKDAY Retorna o dia da semana como um número. O dia 1 é o
domingo.
ANO Retorna a parte do ano de uma entrada de data.
Funções lógicas
E Rendimentos TRUE quando todos os seus argumentos são
verdadeiros.
FALSO Define o valor lógico como FALSE.
E SE Se uma condição for TRUE, esse valor, senão outro valor.
IFNA (desde LO 3.5)
NÃO Reverte o valor lógico de um argumento.
OU Rendimentos TRUE quando uma de suas condições é TRUE.
VERDADE Define o valor lógico como TRUE.
XOR Rende TRUE quando apenas um dos valores vinculados é
VERDADEIRO.
Funções de arredondamento
INT Arredonda para o inteiro anterior.
Mathemati cal f un c ção s
ABS Retorna o valor absoluto (não negativo) de um número.
ACOS Calcula o arccosine de um número. - argumentos entre -1 e 1.
(desde LO 3.5)
ACOSH Calcula a áreacosina (cosseno hiperbólico inverso) -
argumento> = 1.
(desde LO 3.5)
COMO EM Calcula o arco seno de um argumento numérico entre -1 e 1.
(desde o LO 3.5)
UM BRONZEADO Calcula o arco tangente de um número.
(desde LO 3.5)
ATAN2 Calcula o arco tangente de uma coordenada xe uma
coordenada y.
(desde LO 3.5)
MÉDIA Dá a média dos valores inseridos. (ocorre duas vezes no LO
3.3.4 Formula Wizard)
AVERAGEA Dá a média dos valores inseridos. O texto é tratado como
zero.
(desde LO 3.5)
COS O argumento é o ângulo em radianos cujo cosseno deve ser
calculado.
(desde LO 3.5)
ATÉ Arredonda um número positivo para cima ou um número
negativo para o próximo número inteiro ímpar.
EXP Calcula a função exponencial (Base 'e').
(desde LO 3.5)
LN Calcula o logaritmo natural de um número.
(desde LO 3.5)
LOG10 Calcula o logaritmo de um número (Base '10').
(desde LO 3.5)
MAX Retorna o máximo de uma série de números.
MAXA Retorna o valor máximo em uma linha. Qualquer texto é
definido como zero.
MIN Retorna o menor de uma série de valores.
MINA Retorna o valor mínimo em uma linha. Qualquer texto é
definido como zero.
MOD Retorna o restante para uma divisão quando você insere o
dividendo e o divisor.
ÍMPAR Arredonda um número positivo para cima ou um número
negativo para baixo até o próximo número inteiro ímpar.
PI Dá o valor do número ' π'.
(desde LO 3.5)
PODER Eleva a base ao poder do expoente.
(Desde LO 3.5)
PECADO Calcula o seno de um número.
(desde LO 3.5)
SQRT Calcula a raiz quadrada de um número.
(desde LO 3.5)
SOMA Soma uma lista de valores numéricos
SUMA Soma uma lista de valores numéricos. Texto um nd campos
Sim / Não são permitidos. Infelizmente esta função (ainda)
termina com uma mensagem de erro.
(desde LO 3.5)
VAR Calcula a variação, começando de uma amostra.
(desde LO 3.5)

Divertido texto c ção s


EXATO Mostra se duas cadeias de texto são exatamente iguais.
ENCONTRAR Dá o deslocamento de uma string de texto dentro de outra
string.
ESQUERDA O número especificado de caracteres de uma cadeia de texto
é reproduzido a partir da esquerda.
LEN Dá o número de caracteres em uma string de texto.
MAIS BAIXO Converte o texto em minúscula.
MENSAGEM Formata o valor no formato de saída fornecido.
(desde LO 3.5)
MID O número especificado de caracteres de uma cadeia de texto
é reproduzido a partir de uma posição de caractere
especificada.
SUBSTITUIR Substitui uma substring por uma substring diferente. A posição
inicial e o comprimento da substring a ser substituída devem
ser dados.
REPT Repete o texto um número especificado de vezes.
CERTO O número especificado de caracteres de uma cadeia de texto
é reproduzido a partir da direita.
SUBSTITUTO Substitui partes específicas de uma determinada string de
texto por um novo texto. Além disso, você pode especificar
quais das várias ocorrências da string de destino devem ser
substituídas.
T Retorna o texto ou uma string de texto vazia se o valor não for
texto (por exemplo, um número).
TEXTO Conversão de números ou horas em texto.
APARAR Remove espaços iniciais e espaços de terminal e reduz
vários espaços para um único espaço.
UNICHAR Converte um número decimal Unicode em um caractere
Unicode. Por exemplo, 196 se torna 'Ä' ('Ä' tem o valor
hexadecimal 00C4, que é 196 em decimais sem zeros à
esquerda).
UNICODE Converte um caractere Unicode em um número decimal
Unicode.
'Ä' torna-se 196.
SUPERIOR Retorna uma string de texto em maiúscula.
URLENCODE Converte um determinado texto em um que esteja em
conformidade com um URL válido. Se nenhum padrão
específico for especificado, o ISO-8859-1 é seguido.
Funções de informação
ESCOLHER O primeiro argumento é um índice, seguido por uma lista de
valores. O valor representado pelo índice é retornado.
ESCOLHER (2; "Apple"; "Pear"; "Banana")
retorna Pear .
ESCOLHER ([age_level_field]; "Leite";
"Cola"; "Cerveja") retorna uma bebida possível para o
dado ' age_level_field' .
CONTAGEM Apenas campos contendo um número ou uma data são
contados.
COUNT ([time]; [number]) retorna 2 , se ambos
os campos contiverem um valor (não-NULL) ou outro 1 ou 0.
COUNTA Inclui também campos contendo texto. Mesmo NULL é
contado, junto com os campos booleanos.
COUNTBLANK Conta os campos vazios em uma região.
MUDOU Verifica se a coluna nomeada foi alterada. No entanto,
nenhuma informação sobre a coluna é fornecida.
ÍNDICE Funciona com regiões ( s ince LO 3.5).
ESTÁ EM BRANCO Testa se o campo é NULL (vazio).
ISERR Retorna TRUE se a entrada tiver um erro diferente de NA.
ISERR (1/0) dá TRUE

ISERROR Como o ISERR, exceto que NA também retorna TRUE.


ISEVEN Testa se um número é par.
ISLOGICAL Testa se este é um valor Sim / Não.
(ISTLOG) ISLOGICAL (TRUE ()) ou ISLOGICAL (FALSE
()) yield TRUE , Valores de texto como ISLOGICAL
("TRUE") resultam em FALSE .

ISNA Testa se a expressão é um erro do tipo NA.


ISONTEXTO Testa se o valor não é texto.
ISNUMBER Testa se algo é numérico.
ISNUMBER (1) produz TRUE , ISNUMBER ("1")
produz FALSE

É ESTRANHO Testa se um número é um número ímpar.


ISREF Testa se algo é uma referência de campo.
ISREF ([Fieldname]) produz TRUE , ISREF
(1) produz FALSE .

ISTEXT Testa se o conteúdo do campo é texto.


NA Retorna o código de erro NA .
(NV)
VALOR (desde LO 3.5)
Usuário definido
CSVARRAY Converte o texto CSV em uma matriz. (desde LO 3.5)
CSVTEXT Converte uma matriz em texto CSV. (desde LO 3.5)
NORMALIZARAR (desde LO 3.5)
NULO Retorna NULL.
PARSEDADO Converte texto em uma data. Usa o SimpleDateFormat.
Requer uma data no texto, conforme descrito neste formato
de data. Exemplo: PARSEDATE ("9.10.2012"; "dd.MM.aaaa")
produz o número utilizável internamente para a data. (desde
LO 3.5)
Informação do documento
AUTOR Autor, conforme lido em Ferramentas → Opções →
LibreOffice → Dados do usuário . Este não é, portanto, o
autor real, mas o usuário atual do banco de dados.
TÍTULO Retorna o título do relatório.

Definidos pelo usuário f unções


Você pode usar as funções definidas por você para retornar resultados intermediários específicos para um
grupo de registros. No exemplo acima, uma função desse tipo foi usada para calcular as multas na área
Reader_Name_Footer .

No R elatório N avigator a função é exibido sob Reader_Name grupo. Clicando com o botão direito do
mouse nessa função, você pode definir funções adicionais por nome.
As propriedades da função SummeGebuehrLeser_Name são mostradas acima. A fórmula adiciona o
campo Charge ao valor já armazenado na própria função. O valor inicial é o valor do campo Charge na
primeira travessia do grupo. Esse valor é armazenado na função sob o nome da função e é reutilizado na
fórmula, até que o loop seja finalizado e o rodapé do grupo seja gravado.
A travessia profunda parece não ter função por enquanto, a menos que os gráficos sejam tratados aqui
como sub-relatórios.
Se Pré-avaliação estiver ativada para a função, o resultado também pode ser colocado no cabeçalho do
grupo . Caso contrário, o cabeçalho do grupo contém apenas o valor correspondente do primeiro campo do
grupo.
As funções definidas pelo usuário também podem referenciar outras funções definidas pelo usuário. Nesse
caso, você deve garantir que as funções usadas já tenham sido criadas. Pré-cálculo em funções que se
referem a outras funções devem ser excluídas.
[SumMarksClass] / ([ClassNumber] +1)
refere-se ao grupo de classes . O conteúdo do campo Marcas é somado e a soma de todos os registros é
retornada. A soma das marcas é dividida pela soma dos registros. Para obter o número correto, 1 deve ser
adicionado conforme mostrado com [ClassNumber] . Isso produzirá as marcas médias.

Entrada fórmula para um f ield


Usando dados > Campo de dados você pode inserir fórmulas t h a afetar apenas um campo na área de
detalhes.
IF ([boolean_field]; " Sim " ; " Não " )
define os valores permitidos para "Yes" ou "No" em vez de TRUE e FALSE.

Condicional p rint

As propriedades gerais de cabeçalhos de grupo, rodapés de grupo e campos incluem um campo C


onditional Print Expression . Fórmulas t h em estão escritas neste campo influenciar o conteúdo de um
campo ou a exibição de uma região inteira. Aqui, também, você pode fazer uso do Assistente de Funções.
[Fieldname] = " true "
faz com que o conteúdo do campo nomeado seja exibido apenas se for verdadeiro.
Muitas formas de exibição condicional não são totalmente determinadas pelas propriedades especificadas.
Por exemplo, se uma linha separadora gráfica deve ser inserido após a dez º lugar de uma lista de
resultados da competição, você não pode simplesmente usar o seguinte comando de exibição condicional
para o gráfico:
[Local] = 10
Este comando não funciona. Em vez disso, o gráfico continuará aparecendo na seção Detalhes após cada
registro subseqüente.
É mais seguro vincular a exibição condicional a um grupo fo r, em vez de vincular o gráfico, se isso não for
necessário. A linha está posicionada no grupo foote r . Então a linha realmente aparece depois do 10º lugar,
quando formulada como acima. Mas, nesse caso, o conteúdo que apareceria anteriormente na seção
Detalhes deve ser armazenado no cabeçalho do grupo .

Condicional f ormatting
A formatação condicional pode ser usada, por exemplo, para formatar um calendário, de modo que os finais
de semana sejam exibidos de forma diferente. Escolha Formato > C formatação onditional e digite:
WEEKDAY ([Data]) = 1
e a formatação correspondente para os domingos.
Se você usar 'Expression is' na formatação condicional, poderá inserir uma fórmula. Como é habitual no
Calc, várias condições podem ser formuladas e avaliadas sequencialmente. No exemplo acima, primeiro
domingo é testado, e depois sábado. Finalmente, pode haver uma consulta sobre o conteúdo do campo.
Por exemplo, o conteúdo "Férias" levaria a um formato diferente.

O Report Builder é um plug-in. Se ocorrerem erros incorrigíveis adicionais


Nota (fórmulas não implementadas, texto muito longo mostrado como um campo
vazio e assim por diante ), às vezes é necessário excluir partes do relatório ou
simplesmente criá-lo novamente.
Capítulo 7 Vinculando aos Bancos
de Dados

Notas gerais sobre ligação d atabase


Base permite que você use documentos no LibreOffice Writer e no Calc de várias maneiras como fontes de
dados. Isso significa que o uso de Base não está necessariamente vinculado ao registro de bancos de
dados na configuração do LibreOffice. Os formulários externos também podem interagir diretamente com o
Base, desde que o caminho para as fontes de dados seja fornecido.

Registro de bancos de dados


Muitas funções, como imprimir etiquetas ou usar dados para cartas-modelo, exigem o registro de um
banco de dados na configuração do LibreOffice.
Usando Ferramentas > Opções > LibreOffice Base > Bancos de dados > Novo , um banco de dados
pode ser registrado para uso posterior por outros componentes do LibreOffice.

O banco de dados é encontrado usando o navegador de arquivos e conectado ao LibreOffice de maneira


similar a um formulário simples. O próprio banco de dados deve receber um nome informativo adequado,
para o qual você pode simplesmente usar o nome do arquivo de banco de dados. O nome serve como um
alias, que também pode ser usado em consultas ao banco de dados.

Navegador da fonte de dados


O navegador da fonte de dados permite acessar tabelas e consultas de todos os bancos de dados
registrados sob seus nomes registrados. O navegador pode ser aberto usando Visualizar > Fontes de
dados ou pressionando a tecla F4 ou usando o símbolo correspondente na barra de ferramentas padrão.

As origens de dados registradas são mostradas no lado esquerdo do navegador da fonte de dados. A fonte
de dados da Bibliografia está incluída no LibreOffice por padrão. As outras fontes de dados são listadas por
seus nomes registrados.

Um clique no sinal de expansão na frente do nome do banco de dados abre o banco de dados e mostra
uma subpasta para consultas e outra para tabelas. Outras subpastas do banco de dados não são
disponibilizadas aqui. Formulários e relatórios internos só podem ser acessados abrindo o próprio banco de
dados.
Somente quando você clica no T ables pasta é o banco de dados realmente ac c Essed. Para bancos de
dados protegidos por uma senha, a senha deve ser inserida neste ponto.
À direita da árvore de nomes, você pode ver a tabela que você selecionou. Pode ser editado como na
Base. No entanto, a entrada direta em tabelas deve ser realizada com cautela em bancos de dados
relacionais muito complexos, pois as tabelas são vinculadas a chaves estrangeiras. Por exemplo, o banco
de dados mostrado abaixo tem tabelas separadas para nomes de ruas, códigos postais e cidades.
Para uma visão adequada dos dados (mas sem a capacidade de editar), as consultas ou visualizações são
mais adequadas.

Dos ícones na barra de ferramentas, muitos estarão familiarizados com a entrada de dados em tabelas. Os
principais novos são os da última seção: Dados para texto, Dados para campos, Mala direta, Fonte de
dados do documento atual, Ativar / desativar o Explorer .

Figura 51: Barra de ferramentas do navegador da fonte de dados

Dados para texto


A função Data to Text está disponível assim que um registro é selecionado.

Figura 52: Selecionando um registro de dados

Se você escolher agora Dados para texto, um assistente aparecerá para realizar a formatação necessária.
Figura 53: Dados e ntry como t capaz
Existem várias possibilidades para inserir dados como texto: como uma tabela, como campos únicos ou
como texto comum.
A figura acima mostra a opção Inserir dados como tabela . No caso de campos numéricos e de data, o
formato do banco de dados pode ser alterado para um formato escolhido. Caso contrário, a formatação
será executada automaticamente quando os campos da tabela forem selecionados. A seqüência de
campos é ajustada usando as teclas de seta.
Assim que as colunas da tabela forem selecionadas, o botão Propriedades da tabela será ativado. Isso
permite que você defina as propriedades usuais da tabela para o Writer (largura da tabela, largura da coluna
e assim por diante) .
A caixa de seleção determina se um cabeçalho de tabela é obrigatório. Se não estiver marcado, nenhuma
linha separada será reservada para os títulos.
A linha escolhida para os títulos da tabela pode ser retirada dos nomes das colunas, ou o registro pode ser
escrito com espaço deixado para os títulos a serem editados posteriormente.
O botão Auto F ormat fornece várias visualizações de tabela pré-formatadas. Além do formato padrão
sugerido , todos os formatos podem ser renomeados.
Para adicionar uma formatação automática, uma tabela nesse formato deve ser criada primeiro. Isso é
então selecionado e pode ser adicionado à lista usando o botão Adicionar .
Finalmente, a tabela é criada com as colunas selecionadas.

Figura 54: Auto F Ormat fornece uma escolha de guia le formatos


Inserir dados como Campos fornece a possibilidade de usar um mini-editor para posicionar os vários
campos da tabela sucessivamente no texto. O texto criado dessa maneira também pode ser fornecido com
um estilo de parágrafo. Neste caso também, a formatação de datas e números pode ser especificada
separadamente ou pode ser lida diretamente das configurações da tabela no banco de dados.
Figura 55: I NSERT dados como Fields - corresponde também ao diálogo para Inserir dados como texto
Os campos inseridos no texto dessa maneira podem ser excluídos posteriormente ou usados para uma
mala direta.
Se você escolher Inserir dados como texto , a única diferença de usar campos é que os campos
permanecem vinculados ao banco de dados. Quando você insere como texto, somente o conteúdo dos
campos especificados é transferido e não o link para o banco de dados real. Isso explica porque o diálogo
para esta opção é o mesmo que para o anterior.
Os resultados dos dois procedimentos são comparados abaixo.

Figura 56: Comparação de dados como campos e dados como texto


Os campos têm um fundo cinza. Se o mouse é passado sobre os campos, isso mostra que os campos
estão ligados à mídia de banco de dados, para a mesa leitor e, dentro deste quadro, para o campo I D .
Assim, por exemplo, um duplo - clique no campo I D abre a seguinte visão geral. Isso deixa claro qual
campo foi criado por meio do procedimento Inserir Dados como Campos . É o mesmo tipo de campo
mostrado por Inserir > Campos > Outro > Banco de Dados .

Figura 57: Duplo - clique em um campo inserido para mostrar as propriedades dos campos de mala direta
É mais simples criar um tal campo selecionando o cabeçalho da coluna da tabela no navegador da fonte de
dados e arrastando-o para o documento com o mouse. Você pode criar uma carta de formulário
diretamente dessa maneira.

Dados para campos


Da ta como Campos , conforme descrito na seção anterior, é usado para criar campos de mala direta em
um documento do Writer. Se agora você selecionar um registro diferente no navegador da fonte de dados e,
em seguida, escolher D ata como Campos , os dados inseridos anteriormente são substituídos pelos
novos dados.
Aqui outro registro foi selecionado. Enquanto o Insert d ata como Campos opção leva aos valores
anteriores está sendo alterada para os valores para o novo registro, no caso de dados Inserção como texto
, o texto existente permanece inalterado.

Mala direta
Th e mala direta botão lança o M ail M Assistente erge. Como a carta de formulário no exemplo acima
monta seus dados de diferentes tabelas, primeiro é necessário iniciar o banco de dados. No banco de
dados, você cria uma nova consulta para disponibilizar os dados necessários.

O banco de dados é lançado através de um direito - clique no próprio banco de dados ou em uma de suas
tabelas ou consultas, que refresca imediatamente a exibição no navegador da fonte de dados. Depois
disso, o Assistente de mala direta pode ser chamado usando o botão correspondente.

Fonte de dados de C urrent d ocument


Um clique no th e fonte de dados do documento atual botão abre uma vista directa sobre a mesa que forma
a base para os dados inseridos no documento. No exemplo acima, a tabela Person do banco de dados
Endereços é exibida .

Explorador o / off
Alternando th e Explorador On / Off mostras botão ou oculta a árvore de diretórios à esquerda da exibição
de tabela. Isso permite mais espaço, se necessário, para uma exibição dos dados. Para acessar outra
tabela, você precisará alternar o Explorer novamente.

Criando m ail m documentos Erge


O Assistente de mala direta também está acessível no navegador do banco de dados. Esse assistente
permite que o campo de endereço e a saudação sejam construídos a partir de uma fonte de dados em
pequenas etapas. Em princípio, você pode criar esses campos sem usar o Assistente. Aqui vamos
trabalhar com os passos do Wizard como um exemplo.

O documento inicial para a carta de formulário é o documento a que a base de dados campos de re
ligado .
O documento mesclado é o que contém os dados para as várias pessoas que receberão as cartas-
modelo. No documento mesclado, não há ligação com a fonte de dados. É semelhante à saída de Inserir
Dados como Texto .
O Assistente do M ail M erge pode produzir cartas ou e-mails usando registros do banco de dados.

A entrada do bloco de endereço permite a configuração mais extensa. A lista de endereços sugerida vem
da consulta ou tabela atualmente selecionada no banco de dados atualmente selecionado.
O passo 2 determina a aparência geral do bloco de endereços. Esse bloco de endereço pode ser
personalizado usando o botão Mais . Veja a figura a seguir.
A etapa 3 serve para vincular os campos nomeados no bloco de endereço aos campos corretos no banco
de dados. O Assistente inicialmente reconhe z es apenas os campos de banco de dados que têm
exatamente os mesmos nomes do Assistente usa.
Na etapa 4, os endereços são exibidos. Você pode escolher quais endereços obter do banco de dados
usando as teclas de seta. Nos endereços exibidos, dois elementos exigem edição adicional:
•Não há saudação.
•Além do primeiro nome, todos os outros campos são <ainda não alocados> , porque os nomes de campo
no banco de dados são diferentes dos nomes que o Assistente usa inicialmente.
Para corrigir esses erros, o bloco de endereços da Etapa 2 deve ser tornado editável.
Você pode ver no fundo que, quando escolhe editar, você é apresentado a uma lista ampliada de blocos de
endereços. Aqui você pode selecionar o bloco de endereços mais adequado para começar e depois editá-
lo.
O bloco de endereços não pode ser editado diretamente. Em vez disso, a organização dos campos é
executada usando os botões de seta visíveis à direita para mover os campos para dentro ou para fora do
bloco de endereço.
Para a saudação, o campo Saudação é inserido . Todos os outros campos, exceto FirstName, devem ser
inseridos de forma apropriada.

Aqui, os elementos de endereço são associados aos elementos correspondentes da consulta do banco de
dados transferidos com êxito pelo Assistente de mala direta. Novamente, o primeiro registro na consulta é
usado para a visualização.
As configurações do banco de dados são essencialmente finalizadas na Etapa 4. Aqui, é apenas uma
questão de escolher de qual campo o gênero do destinatário deve ser retirado. Este campo já foi nomeado,
de modo que somente o conteúdo do campo para um destinatário feminino ainda precisa ser especificado.
Três saudações diferentes devem ser produzidas. Todos os registros com um 'w' começam com Dear
Ms… , todos aqueles com 'm' com Dear Mr… Se não houver gênero, Dear Sir / Madam está selecionado.
Normalmente, o documento é inicialmente um esboço que pode ser editado no Writer. Isso pode ser feito no
Passo 6.
Até agora todos os documentos foram idênticos, exceto pelo conteúdo diferente dos campos lidos no banco
de dados. Isso pode ser alterado no Passo 7.

O documento inicial é o documento no qual as propriedades do campo e a vinculação ao banco de


dados são armazenadas. Enquanto isso, no fundo, você pode ver o documento original com o conteúdo do
primeiro registro a ser convertido na carta-modelo. Isso é chamado de documento de mala direta.
Somente quando uma das opções é realmente executada (no exemplo acima para salvar o documento
inicial) o Assistente de mala direta é encerrado.

Impressão de etiquetas
Arquivos > Novo > Etiquetas inicia o Assistente de impressão de etiquetas. Ele abre um diálogo, que
inclui todas as questões de formatação e conteúdo para rótulos, antes que os rótulos sejam produzidos. As
configurações nesta caixa de diálogo são salvas nas configurações pessoais do usuário.

As configurações básicas do conteúdo estão na guia Labels . Se para o texto Label você marcar a caixa
Endereço, todas as etiquetas terão o mesmo conteúdo, retirado das configurações do LibreOffice para o
usuário do programa.
Como exemplo, usaremos novamente o banco de dados Endereços . Embora o próximo campo de
seleção seja intitulado Tabelas , Tabelas e Consultas estão listadas aqui, assim como no navegador da
fonte de dados.
Os botões de seta são usados para inserir campos de banco de dados individuais no editor. O nome do
campo do banco de dados Sobrenome é definido aqui como <Addresses.MailMergeQuery.1.Surname> . A
sequência é, portanto, <database.Table.1.database field> .
Você pode trabalhar com o teclado no editor. Assim, por exemplo, é possível inserir uma quebra de linha no
início, para que as etiquetas não sejam impressas diretamente na borda superior, mas o conteúdo pode ser
impresso de forma completa e claramente visível.
O formato pode ser selecionado na guia Etiquetas . Aqui, muitas marcas de rótulos são incorporadas para
que a maioria das outras configurações na guia Formato não seja necessária.

Nas versões 3.4.x a 3.5.2, devido a uma alteração nas configurações básicas
no assistente de etiqueta, ocorreram erros de exibição quando as etiquetas
tinham a mesma largura que a largura da página. Sob essas condições, o
Nota
último rótulo simplesmente desliza por uma linha.
Na versão 3.5.3, as configurações da página foram adicionadas na guia
Formato .

A guia Formato permite que você defina o tamanho da etiqueta com precisão. As configurações só são
significativos quando o m ake e typ e das etiquetas não é conhecido. Vale ressaltar que, para imprimir
rótulos de 7,00 cm de largura, você precisa de uma largura de página um pouco maior que 3 * 7,00 cm =
21,00 cm. Somente então três etiquetas serão impressas em uma linha na página.

Na guia Opções, você pode especificar se apenas um único rótulo ou uma página inteira de rótulos serão
produzidos. A página será então preenchida com dados de registros sucessivos do banco de dados,
começando com o primeiro registro. Se houver mais registros que caberão na página, a próxima página
será preenchida automaticamente com o próximo conjunto de registros.
O Synchroni z e conteúdo caixa de seleção liga todos os rótulos em conjunto para que as alterações
subsequentes no layout de qualquer rótulo será aplicado a todos os outros. Para transferir o conteúdo
editado, basta usar o inc l botão UDED rotulado Synchroni z e , que aparece durante a produção de
etiquetas, se tiver seleccionado esta opção .
Finalmente, o botão Novo documento é usado para criar um documento contendo os campos
selecionados.
Quando você inicia o processo de impressão, a seguinte pergunta aparece:

Escolha Y es para preencher os campos de banco de dados de endereços com o conteúdo


correspondente.

A origem dos dados para a impressão de etiquetas não é encontrada automaticamente; somente o banco
de dados é pré-selecionado. A consulta real deve ser especificada pelo usuário, porque neste caso não
estamos lidando com uma tabela.
Quando a consulta é selecionada e os registros correspondentes escolhidos (nesse caso, All ), a
impressão pode começar. É aconselhável, especialmente para os primeiros testes, escolher Saída para
um Arquivo , o que salvará as etiquetas como um documento. A opção de salvar em vários documentos
não é apropriada para impressão de etiquetas, mas sim para cartas para diferentes destinatários, que
podem ser trabalhadas posteriormente.

Criação direta de mala direta e documentos de etiqueta


Em vez de usar o Assistente, você pode produzir diretamente mala direta e rotular documentos
diretamente.

Mala direta usando o mouse


Os campos de mala direta podem ser obtidos do navegador do banco de dados usando o mouse:

Selecione o cabeçalho da tabela com o botão esquerdo do mouse. Mantenha o botão pressionado e arraste
o cursor pelo documento de texto. O cursor muda sua forma para um símbolo de inserção. O campo
MailMerge é inserido no documento de texto, mostrado aqui na descrição completa, que fica visível usando
os nomes View > Field .
Criando cartas formulário selecionando campos
Os campos de mala direta podem ser inseridos usando Inserir > Campos > Outro > Banco de Dados .

Aqui todas as tabelas e consultas no banco de dados selecionado estão disponíveis. Usando o botão '
Inserir ', os vários campos podem ser inseridos um após o outro diretamente no texto na posição atual do
cursor.
Se você quiser criar uma saudação, o que é comum em cartas, você pode usar um parágrafo oculto ou um
texto oculto: Inserir > Campos > Outro > Funções > Parágrafo oculto . Para ambas as variantes, tome
cuidado para que a condição que você formular não seja cumprida, pois você deseja que o parágrafo fique
visível.
Para a fórmula Caro Sra. <Apelido>, para aparecer apenas quando a pessoa é do sexo feminino, uma
condição suficiente é:
[Addresses.Mailmergequery.Gender]! = "F"
Agora, o único problema remanescente é que pode não haver sobrenome. Nestas circunstâncias, " Dear
Sir / Madam " deve aparecer, então esta é a condição que você deve inserir. A condição geral é:
[Addresses.MailMergeQuery.Gender]! = "W" OU NÃO
[Addresses.MailMergeQuery.Surname]
Isso exclui a possibilidade de este parágrafo aparecer quando a pessoa não é do sexo feminino ou não há
um sobrenome inserido.
Da mesma forma, você pode criar entradas para o gênero masculino e para entradas faltantes para os dois
tipos restantes de saudação.
Naturalmente, você pode criar uma saudação no campo de endereço exatamente da mesma maneira,
sempre que o gênero for especificado.
Mais informações são fornecidas na Ajuda do LibreOffice em Texto oculto e Texto condicional .
É claro que ainda seria mais simples se alguém que entende bancos de dados colocar toda a saudação
diretamente na consulta. Isso pode ser feito usando uma subconsulta correlacionada (consulte o capítulo
sobre Consultas neste Manual).
Particularmente interessante para rótulos é o tipo de campo Próximo registro. Se esse tipo de campo for
escolhido no final de um rótulo, o próximo rótulo será preenchido com os dados do registro a seguir. Os
rótulos típicos para impressão de etiquetas sequencial são semelhantes à figura a seguir quando você usa
Visualizar > Nomes de campos para tornar visíveis as designações de campos correspondentes:

Figura 58: Seleção de campo para rótulos com conteúdo seqüencial

Externas f ORMs
Se as propriedades de formulário simples disponíveis no LibreOffice forem usadas em outros módulos do
programa, como o Writer e o Calc, você só precisará exibir a barra de ferramentas de design de formulário,
usando Exibir > Barras de ferramentas > Design de formulário e abra o navegador Formulário. Você
pode criar um formulário ou, conforme descrito no capítulo F ormas, criar um campo de formulário. A guia
Dados da caixa de diálogo Propriedades do formulário parece um pouco diferente da que você vê quando
os formulários são criados diretamente em um arquivo de banco de dados ODB :
Figura 59: Formulário com uma fonte de dados externa

Figura 60: Formulário com uma fonte de dados interna.


A fonte de dados deve ser selecionada separadamente ao usar um formulário externo. Use o botão à direita
da caixa de listagem da fonte de dados para abrir o navegador de arquivos. Qualquer arquivo ODB pode
ser selecionado. Além disso, o campo da fonte de dados contém um link, começando com file: ///.
Se, em vez disso, você procurar no conteúdo da caixa de listagem, verá os bancos de dados já registrados
no LibreOffice sob seus nomes registrados.
Os formulários são criados exatamente da mesma maneira que na própria Base.
Vantagens de formulários externos
Base não precisa ser aberta primeiro para trabalhar com o banco de dados. Portanto, você não precisa
de uma janela extra aberta em segundo plano.
Em um banco de dados que já está completo, os usuários existentes do banco de dados podem,
posteriormente, receber o formulário aprimorado sem problemas. Eles podem continuar usando o
banco de dados durante o desenvolvimento de formulários adicionais e não precisam copiar formulários
externos complicados de um banco de dados para outro.
Formulários para um banco de dados podem ser variados para atender o usuário. Os usuários que não
têm autoridade para corrigir dados ou fazer novas entradas podem receber um conjunto de dados atual
de outros usuários e simplesmente substituir o arquivo * .odb para ter uma exibição atualizada. Isso
poderia, por exemplo, ser útil para um banco de dados para uma associação em que todos os
membros do comitê obtêm o banco de dados, mas apenas uma pessoa pode editar os dados; os
outros ainda podem ver os endereços de seus respectivos departamentos.
Desvantagens de formulários externos
Os usuários devem sempre instalar formulários e base com a mesma estrutura de diretórios. Essa é a
única maneira que o acesso ao banco de dados pode estar livre de erros. Como os links são
armazenados em relação ao formulário, é suficiente armazenar o banco de dados e seus formulários
em um diretório comum.
Somente formulários podem ser criados externamente, não consultas ou relatórios. Um simples olhar
para uma consulta, portanto, deve passar por um formulário. Um relatório, por outro lado, requer a
abertura do banco de dados. Como alternativa, pode ser possível criá-lo, pelo menos parcialmente,
usando a mala direta.

Uso do banco de dados no Calc


Os dados podem ser usados no Calc para fins de cálculo. Para isso, é necessário primeiro tornar os dados
acessíveis em uma planilha do Calc.

Inserção de d ados em Calc


Existem várias maneiras de inserir dados no Calc.
Selecione uma tabela com o botão esquerdo do mouse e arraste-a para uma planilha do Calc. O cursor
define o canto superior esquerdo da tabela. A tabela é criada completa com nomes de campo. O navegador
da fonte de dados, neste caso, não oferece as opções de Dados em texto ou Dados em campos .
Dados arrastado para Calc desta forma mostra s as seguintes propriedades:
Não apenas os dados são importados, mas as propriedades do campo também são lidas e atuadas
durante a importação. Campos como números de casas, que foram declarados como campos de texto,
são formatados como texto após a inserção no Calc.
A importação se torna um intervalo do Calc, que, por padrão, recebe o nome Import1. Os dados podem ser
acessados posteriormente usando esse intervalo. Data > Refresh Range permite que o intervalo, quando
apropriado, seja fornecido com novos dados do banco de dados.
Os dados importados é não formatado exceto quando as propriedades do banco de dados campos
requerem.
Você também pode usar o menu de contexto de uma tabela para fazer uma cópia dos dados. Neste caso,
no entanto, não há importação, mas apenas uma cópia. As propriedades dos campos de dados não são
lidas com elas, mas são determinadas pelo Calc. Além disso, os nomes dos campos são formatados
como cabeçalhos de tabela.
Você vê a diferença especialmente nos campos do banco de dados formatados como texto. Na
importação, o Calc os transforma em campos de texto e precede números, que, de outra forma, seriam
interpretados como tal, com uma única citação ('137) . Esses números não podem mais ser usados
nos cálculos.
Se você exportá-los novamente, a aspa simples será removida, para que os dados permaneçam como
estavam.

Exportação de d ados a partir de Calc numa base de dados


Selecione os dados na planilha do Calc. Mantenha o botão esquerdo do mouse pressionado e arraste os
dados que você deseja transformar em um banco de dados para a área da tabela do navegador de banco
de dados.

O cursor muda sua aparência, mostrando que algo pode ser inserido.
O Copiar Tabela d ialog aparece. No caso acima, uma nova tabela é criada. O nome da tabela é "Nomes".
Definição e Da ta devem ser transferidos. A primeira linha contém os cabeçalhos da coluna.
Neste ponto, você pode criar um novo campo adicional para uma chave primária. O nome desse campo de
banco de dados não deve ser um que já exista como um cabeçalho de coluna na planilha Calc. Caso
contrário, você receberá a mensagem de erro:
Os campos a seguir já estão definidos como chave primária: ID
Infelizmente esta mensagem não descreve o problema corretamente.
Se você quiser que um campo existente seja usado como chave, não marque a caixa Criar chave primária
. I n tais casos, a chave primária é definida usando o terceiro diálogo no assistente.

Os campos apropriados são selecionados.


A formatação das colunas precisa ser verificada, especialmente para campos numéricos. Outros campos
também devem ser verificados quanto ao tamanho. Acontece que a tabela de teste contém apenas os
primeiros nomes com um comprimento máximo de 10 caracteres, para que possa se tornar um campo do
tipo Varchar com um comprimento de 10 caracteres.
Aqui, o campo ID, que é a chave primária, é formatado. A chave primária deve ser definida usando o menu
de contexto de seu nome de campo, nos casos em que ela não foi criada pelo Assistente na caixa de
diálogo Copiar Tabela como um campo adicional. Depois de clicar no botão Concluir , a tabela é criada.
A nova chave primária não é uma chave de valor automático . Para criar essa chave, você deve abrir o
banco de dados para edição. Lá você pode realizar mais formatação da tabela.

Convertendo d ados a partir de uma base de dados para outra


No explorador do navegador da fonte de dados, as tabelas podem ser copiadas de um banco de dados
para outro, selecionando a tabela de origem com o botão esquerdo do mouse, mantendo o botão
pressionado e arrastando-o para o banco de dados de destino no contêiner da tabela. Isso faz com que a
caixa de diálogo para copiar tabelas seja exibida.
Dessa forma, por exemplo, bancos de dados somente leitura (fontes de dados, como catálogos de
endereços de um programa de e-mail ou uma tabela de planilhas) podem ser usados como base para um
banco de dados no qual os dados se tornam editáveis. Também os dados podem ser copiados diretamente
ao mudar para outro programa de banco de dados (por exemplo, mudando do PostgreSQL para o MySQL).
Se você deseja que o novo banco de dados tenha relacionamentos diferentes do original, você pode
organizá-lo usando consultas apropriadas. Aqueles que não são suficientemente especialistas podem usar
o Calc. Basta arrastar os dados para uma planilha e prepará-los para importação no banco de dados de
destino usando os recursos que o Calc fornece.
Para a importação mais limpa possível em um novo banco de dados, as tabelas devem ser preparadas
com antecedência. Isso permite que problemas de formatação e os que envolvem a criação de chaves
primárias para ser reconhe z ed com bastante antecedência.

Capítulo 8 Tarefas do banco de


dados

Comentários gerais sobre tarefas de banco de dados


Este capítulo descreve algumas soluções para problemas que surgem para muitos usuários do datsbase.

Filtragem de dados
A filtragem de dados usando a GUI é descrita no capítulo sobre entrada de dados em tabelas. Aqui,
descrevemos uma solução para um problema que muitos usuários levantaram: como usar listboxes para
pesquisar o conteúdo de campos em tabelas, que depois aparecem filtrados na seção de formulário
subjacente e podem ser editados.
A base para essa filtragem é uma consulta editável (consulte o capítulo sobre consultas) e uma tabela
adicional, na qual os dados a serem filtrados são armazenados. A consulta mostra a partir de sua tabela
subjacente apenas os registros que correspondem aos valores do filtro. Se nenhum valor de filtro for
fornecido, a consulta mostrará todos os registros.
O exemplo a seguir inicia em uma tabela de Exemplo de Mídia que inclui, entre outros, os
seguintes campos: ID (chave primária), Título , Categoria . Os tipos de campo são
INTEGER , VARCHAR e VARCHAR, respectivamente.
Primeiro, precisamos de uma tabela de exemplo de filtro . Esta tabela contém uma
chave primária e dois campos de filtro (claro que você pode ter mais se quiser): "ID" (chave primária),
Filter_1 , Filter_2 . Como os campos da tabela Media Example , que devem
ser filtrados, são do tipo VA RCHAR , os campos Filter_1 e Filter_2 também são
desse tipo. O ID pode ser o menor tipo numérico, T INYINT, porque a tabela
Filtro nunca conterá mais de um registro.

Você também pode filtrar campos que ocorrem na tabela de exemplo de mídia apenas como chaves
estrangeiras. Nesse caso, você deve fornecer aos campos correspondentes na tabela de Exemplo de
Filtro o tipo apropriado para as chaves estrangeiras, geralmente INTEGER .
A consulta a seguir é certamente editável:
SELECT * FROM " Exemplo de Mídia "
Todos os registros da tabela de exemplo de mídia são exibidos, incluindo a chave primária.
SELECT * FROM " Exemplo de Mídia " WHERE "Título" = IFNULL ((SELECT
"Filter_1" FROM " Exemplo de Filtro "), "Título")
Se o campo Filter_1 não for NULL , esses registros serão exibidos para os quais o título é
o mesmo que Filter_1 . Se o campo Filter_1 for NULL , o valor do campo Title
será usado. Como Título é o mesmo que "Título" , todos os registros são exibidos. Essa
suposição não é válida, no entanto, se o campo Título de qualquer registro estiver vazio (contém
NULL) . Isso significa que esses registros nunca serão exibidos sem entrada de título. Portanto,
precisamos melhorar a consulta:
SELECT *, IFNULL ("Title", '') AS "T" DE " Exemplo de Mídia " WHERE "T" =
IFNULL ((SELECT "Filter_1" FROM " Exemplo de Filtro "), "T")

IFNULL (expressão, valor) requer que a expressão tenha o


mesmo tipo de campo que o valor .
•.Se a expressão ha s o tipo de campo VARCHAR , utilize duas aspas
simples '' como o valor .
Gorjeta •.Se ha s DATA como seu tipo de campo, inserir uma data que o valor que não
está contido no campo da tabela t o ser filtrada. Use este formato: {D 'AAAA-
MM-DD'} .
•.Se for qualquer um dos tipos de campos numéricos, use o tipo de campo
NUMERIC para o valor. Digite um número que não aparece no campo da
tabela a ser filtrada.

Essa variante levará ao objetivo desejado. Em vez de filtragem Título diretamente, um campo é
filtrada que carrega o alias T . Este campo não tem conteúdo, mas não é NULL . Nas condições
apenas o campo T é considerado. Todos os registros são exibidos, mesmo se o título for
NULL .
Infelizmente você não pode fazer isso usando a GUI. Este comando está disponível apenas diretamente
com o SQL. Para torná-lo editável na GUI, é necessária uma modificação adicional:
SELECT " Exemplo de Mídia ". *, IFNULL (" Exemplo de Mídia ". "Título", '')
AS "T" DE " Exemplo de Mídia " WHERE "T" = IFNULL ((SELECT "Filter_1" FROM
" Exemplo de Filtro "), "T")
Se o relacionamento da tabela com os campos estiver configurado agora, a consulta se tornará editável na
GUI.
Como teste, você pode colocar um título em "Filtro". "Filtro_1" . Como "Filtro",
"ID" defina o valor '0 ' . O registro é salvo e a filtragem pode ser compreendida. Se
"Filtro". "Filtro_1" for esvaziado, a GUI trata isso como NULL . Um novo teste produz uma
exibição de todas as mídias. Em qualquer caso, antes que um formulário seja criado e testado, apenas um
registro com uma chave primária deve ser inserido na tabela Filtro . Deve ser apenas um registro,
pois as subconsultas mostradas acima só podem transmitir um valor.
A consulta agora pode ser ampliada para filtrar dois campos:
SELECT " Exemplo de Mídia ". *, IFNULL (" Exemplo de Mídia ". "Título", '')
AS "T", IFNULL (" Exemplo de Mídia ". "Categoria", '') AS "K" FROM "
Exemplo de Mídia " WHERE "T" = IFNULL ((SELECT "Filtro_1" FROM " Exemplo de
Filtro "), "T") E "K" = IFNULL ((SELECT "Filter_2" DE " Exemplo de Filtro
"), "K")
Isso conclui a criação da consulta editável. Agora, para a consulta básica das duas caixas de listagem:
SELECT DISTINCT "Title", "Title" FROM " Exemplo de Mídia " ORDER BY "Title"
ASC
A caixa de listagem deve mostrar o título e, em seguida, também transmitir esse título para
o campo Filter_1 na tabela de filtro que sustenta o formulário. Além disso, nenhum valor
duplicado deve ser mostrado ( condição 'D ISTINCT' ). E a coisa toda deve ser
classificada na ordem correta.
Uma consulta correspondente é criada para o campo Categoria , que é gravar seus dados no campo
Filter_2 na tabela Filter .
Se um desses campos contiver uma chave estrangeira, a consulta será adaptada para que a chave
estrangeira seja passada para a tabela de Filtros subjacente .
O formulário consiste em duas partes. Formulário 1 é o formulário baseado na tabela de filtros . O
formulário 2 é o formulário baseado na consulta. O formulário 1 não tem barra de navegação e o ciclo está
definido como Registro atual . Além disso, a propriedade Permitir adições é definida como Não . O
primeiro e único registro para este formulário já existe.
Formulário 1 contém um ins duas caixas de listagem com rótulos apropriados. Listbox 1 retorna valores
para Filter_1 e está vinculado à consulta do campo Title . O Listbox 2 retorna valores para
Filter_2 e está relacionado à consulta do campo Category .
Forma 2 contém um campo de controlo de quadro, em que todos os campos da consulta podem ser
listados, excepto para os campos t und K . O formulário ainda funcionaria se esses campos
estivessem presentes; eles são omitidos para evitar uma duplicação confusa do conteúdo do campo. Além
disso, o formulário 2 contém um botão, vinculado à função Atualizar formulário . Uma barra de navegação
adicional pode ser incorporada para evitar que a tela pisque toda vez que o formulário for alterado, devido à
barra de navegação estar presente em um formulário e não no outro.
Quando o formulário estiver concluído, a fase de teste será iniciada. Quando uma caixa de listagem é
alterada, o botão no formulário 2 é usado para armazenar esse valor e atualizar o Formulário 2. Isso agora
está relacionado ao valor que a caixa de listagem fornece. A filtragem pode ser feita retrospectivamente,
escolhendo um campo vazio na caixa de listagem.

Procurando por dados


A principal diferença entre pesquisar dados e filtrar dados é na técnica de consulta. O objetivo é fornecer,
em resposta a termos de pesquisa de idiomas gratuitos, uma lista resultante de registros que podem conter
apenas parcialmente esses termos reais. Primeiro, as abordagens semelhantes à tabela e à forma são
descritas.
A tabela para o conteúdo da pesquisa pode ser a mesma que já contém os valores do filtro. A tabela
Filtro é simplesmente expandida para incluir um campo denominado Searchterm . Assim, se
necessário, a mesma tabela pode ser acessada e, usando os formulários, simultaneamente filtrada e
pesquisada. Searchterm tem o tipo de campo VARCHAR .
O formulário é criado apenas para filtragem. Em vez de uma caixa de listagem, precisamos de um campo
de entrada de texto para o termo de pesquisa e talvez também um campo de rótulo com o título Pesquisar.
O campo para o termo de pesquisa pode ser independente no formulário ou junto com os campos para
filtragem, se ambas as funções forem desejadas.
A diferença entre filtragem e s earching está na técnica de consulta. Enquanto a filtragem usa um termo que
já ocorre na tabela subjacente, a pesquisa usa entradas arbitrárias. ( Um epois de tudo, a listagem é
construído a partir do conteúdo da tabela).
SELECT * FROM " Exemplo de Mídia " WHERE "Título" = (SELECT "Searchterm"
FROM " Exemplo de Filtro ")
Essa consulta normalmente leva a uma lista de resultados vazia por esses motivos:
8)Ao entrar em termos de pesquisa, as pessoas raramente sabem completamente e com precisão qual é o
título. Portanto, o título correto não é exibido. Para encontrar o livro "Per Anhalter através da Galáxia", deve
ser suficiente colocar "Anhalter" no campo de pesquisa ou até mesmo apenas "Anh".
9)Se o campo “Searchterm” estiver vazio, somente os registros são exibidos nos quais não há título. O
campo "Searchterm" está vazio, o campo Título também deve estar vazio. Isso só acontece em
uma das duas possibilidades: o item não tem um título ou alguém não inseriu seu título.
A última condição pode ser removida se a condição de filtragem for:
SELECT * FROM " Exemplo de Mídia " WHERE "Título" = IFNULL ((SELECT
"Searchterm" FROM " Exemplo de Filtro "), "Título")
Com esse refinamento da filtragem (o que acontece se o título for NULL ?), Obtemos um resultado mais
alinhado com as expectativas. Mas a primeira condição ainda não é cumprida. A pesquisa deve funcionar
bem quando apenas conhecimento fragmentário estiver disponível. A técnica de consulta deve, portanto,
usar a condição LIKE :
SELECT * FROM " Exemplo de Mídia " WHERE "Título" LIKE (SELECT '%' ||
"Searchterm" || '%' FROM " Exemplo de Filtro ")
ou melhor ainda:
SELECT * FROM " Exemplo de Mídia " WHERE "Título" LIKE IFNULL ((SELECT '%'
|| "Searchterm" || '%' FROM " Exemplo de Filtro "), "Título")
LIKE , juntamente com % , significa que todos os registros são exibidos com o termo de pesquisa
em qualquer lugar dentro deles. % é um curinga para qualquer número de caracteres antes ou depois do
termo de pesquisa. Vários projetos ainda permanecem depois que essa versão da consulta foi criada:
•É comum usar letras minúsculas para termos de pesquisa. Então, como obtenho um resultado se eu
digitar "anhalter" em vez de "Anhalter"?
•Quais outras convenções por escrito precisam ser consideradas ?
•E os campos que não estão formatados como campos de texto? Você pode pesquisar por datas ou
números com o mesmo campo de pesquisa?
•E se, como no caso do filtro, você quiser impedir que valores NULL no campo façam com que todos
os registros sejam exibidos?
A seguinte variante cobre uma ou duas dessas possibilidades:
SELECT * FROM " Exemplo de Mídia " ONDE
LOWER ("Title") LIKE IFNULL ((SELECT '%' || LOWER ("Searchterm") || '%'
FROM " Exemplo de Filtro "), LOWER ("Title"))
A condição altera o termo de pesquisa e o conteúdo do campo para minúsculas. Isso também permite que
sentenças inteiras sejam comparadas.
SELECT * FROM " Exemplo de Mídia " ONDE
LOWER ("Title") LIKE IFNULL ((SELECT '%' || LOWER ("Searchterm") || '%'
FROM " Exemplo de Filtro "), LOWER ("Title")) OU
LOWER ("Category") LIKE (SELECT '%' || LOWER ("Searchterm") || '%' FROM "
Exemplo de Filtro ")
A função I FNULL deve ocorrer apenas uma vez, para que quando o termo de pesquisa
for NULL , LOWER ("Title") LIKE LOWER ("Title") é consultado. E como o título
deve ser um campo que não pode ser NULL , nesses casos todos os registros são exibidos.
Naturalmente, para pesquisas de campo múltiplas, esse código se torna correspondentemente mais longo.
Nesses casos, é melhor usar uma macro para permitir que o código cubra todos os campos de uma só
vez.
Mas o código ainda funciona com campos que não são texto? Embora a condição LIKE é realmente
adaptada ao texto, ele também funciona para números, datas e horas sem necessidade de qualquer
alteração s . Então, na verdade, a conversão de texto não precisa ocorrer. No entanto, um campo de tempo
que é uma mistura de texto e números não pode interagir com os resultados da pesquisa - a menos que a
consulta seja ampliada, de modo que um único termo de pesquisa seja subdividido em todos os espaços
entre o texto e os números . Isso, no entanto, irá inchar significativamente a consulta.

Partes de codigo
Esses trechos de código vêm de consultas para listas de discussão. Surgem problemas particulares que
talvez possam ser úteis como soluções para seus próprios experimentos de banco de dados.

Obtendo a idade atual de alguém


Uma consulta precisa calcular a idade real de uma pessoa a partir de uma data de nascimento. Veja
também as funções no apêndice deste Manual Base.
SELECT DATEDIFF ('yy', "Birthdate", CURDATE ()) COMO "Idade" DE "Pessoa"
Esta consulta dá a idade como uma diferença em anos. Mas a idade de uma criança nascida em 31 de
dezembro de 2011 seria dada como 1 ano em 1º de janeiro de 2012. Portanto, também precisamos
considerar a posição do dia dentro do ano. Isso é acessível usando a função 'DAYOFYEAR ()' . Outra
função realizará a comparação.
SELECIONE CASEWHEN
(DAYOFYEAR ("Birthdate")> DAYOFYEAR (CURDATE ()),
DATEDIFF ('yy', "Birthdate", CURDATE ()) - 1,
DATEDIFF ('yy', "Birthdate", CURDATE ()))
AS "Age" FROM "Person"
Agora temos a idade atual correta em anos.
CASEWHEN também pode ser usado para fazer com que o texto Aniversário apareça em outro
campo, se DAYOFYEAR ("Data de Nascimento") = DAYOFYEAR (CURDATE ()) .
Uma objeção sutil poderia surgir agora: "E quanto a anos bissextos?". Para as pessoas nascidas depois de
28 Februa ry , haverá um erro de um dia. Não é um problema sério no uso diário, mas não devemos nos
esforçar para obter precisão?
CASEWHEN (
(MÊS ("Data de Nascimento")> MÊS (CURTO ())) OU
((MONTH ("Data de Nascimento") = MONTH (CURDATE ())) AND (DAY ("Data de
Nascimento")> DAY (CURDATE ()))),
DATEDIFF ('yy', "Birthdate", CURDATE ()) - 1,
DATEDIFF ('yy', "Birthdate", CURDATE ()))
O código acima atinge esse objetivo. Contanto que o mês da data de nascimento seja maior que o mês
atual, a função de diferença de ano subtrairá um ano. Igualmente, um ano será subtraído quando os dois
meses são os mesmos, mas o dia do mês para a data de nascimento é maior do que o dia da data atual.
Infelizmente esta fórmula não é compreensível para o GUI. Somente o 'Direct SQL-Command' tratará
essa consulta com sucesso e isso evitará que nossa consulta seja editada. Mas a consulta precisa ser
editável, então aqui i é como enganar a GUI:
CASO
QUANDO MÊS ("Data de Nascimento")> MÊS (CURTO ()
THEN DATEDIFF ('yy', "Birthdate", CURDATE ()) - 1
QUANDO (MÊS ("Data de Nascimento") = MÊS (CURMAR ()) E DIA ("Data de
Nascimento")> DIA (CURTO ()))
THEN DATEDIFF ('yy', "Birthdate", CURDATE ()) - 1
ELSE DATEDIFF ('yy', "Birthdate", CURDATE ())
FIM
Com essa formulação, a GUI não reage mais com uma mensagem de erro. A idade agora é dada com
precisão mesmo em anos bissextos e a consulta ainda permanece editável.

Obtendo um saldo em execução por categorias


Em vez de usar um livro doméstico, um banco de dados em um PC pode simplificar o trabalho cansativo
de somar despesas com alimentos, roupas, transporte e assim por diante. W e quer a maioria desses
detalhes para ser imediatamente visíveis no banco de dados, s o nosso exemplo assume que receitas e
despesas serão armazenados como valores assinados em um campo chamado Valor. Em princípio, a
coisa toda pode ser expandida para cobrir campos separados e um somatório relevante para cada um.
SELECT "ID", "Quantidade", (SELECT SUM ("Amount") FROM "Cash" ONDE "ID" <=
"a". "ID") AS "Saldo" FROM "Cash" AS "a" ORDER BY " ID "ASC
Essa consulta faz com que cada novo registro seja um cálculo direto do saldo atual da conta. Ao mesmo
tempo, a consulta permanece editável porque o campo "Equilíbrio" é criado por meio de uma subconsulta
correlacionada. A consulta depende da chave primária "ID" criada automaticamente para calcular o estado
da conta. No entanto, os saldos são geralmente calculados diariamente. Então, precisamos de uma
consulta de data.
SELECIONE "ID", "Data", "Valor", (SELECT SUM ("Valor") DE "Dinheiro" ONDE
"Data" <= "a". "Data") AS "Saldo" DE "Dinheiro" AS "a "ORDEM POR" Data ","
ID "ASC
As despesas agora aparecem classificadas e somadas por data. Resta ainda a questão da categoria, pois
queremos saldos correspondentes para as categorias individuais de despesa.
SELECIONE "ID", "Data", "Valor", "Acct_ID",
(SELECT "Acct" FROM "Acct" onde "ID" = "a". "Acct_ID") AS "Acct_name",
(SELECT SUM ("Amount") FROM "Cash" ONDE "Date" <= "a". "Date" E "Acct_ID" =
"a". "Acct_ID") AS "Saldo",
(SELECT SUM ("Amount") FROM "Cash" ONDE "Date" <= "a". "Date") AS
"Total_balance"
FROM "Cash" AS "a" ORDER BY "Data", "ID" ASC
Isso cria uma consulta editável na qual, além dos campos de entrada (Data, Valor, Acct_ID), o nome da
conta, o saldo relevante e o saldo total aparecem juntos. Como as subconsultas correlacionadas são
parcialmente baseadas em entradas anteriores ("Data" <= "a". "Data"), somente novas entradas passarão
sem problemas. Alterações em um registro anterior são inicialmente detectáveis apenas nesse registro. A
consulta deve ser atualizada se cálculos posteriores dependentes dela forem realizados.

Numeração de linhas
Os campos de incremento automático estão bem. No entanto, eles não informam definitivamente quantos
registros estão presentes no banco de dados ou estão realmente disponíveis para serem consultados.
Frequentemente, os registros são excluídos e muitos usuários tentam em vão determinar quais números
não estão mais presentes para que o número em execução seja compatível.
SELECT "ID", (SELECT COUNT ("ID") FROM "Tabela" WHERE "ID" <= "a". "ID") AS
"Nr." FROM "Table" COMO "a"
O campo ID é lido e o segundo campo é determinado por uma subconsulta correlacionada, que procura
determinar quantos valores de campo na ID são menores ou iguais ao valor do campo atual. A partir disso,
um número de linha em execução é criado.
Cada registro ao qual você deseja aplicar essa consulta contém campos. Para aplicar essa consulta aos
registros, primeiro você deve adicionar esses campos à consulta. Você pode colocá-los na ordem que
desejar na cláusula SELECT . Se você tiver os registros em um formulário, precisará modificar o
formulário para que os dados do formulário sejam provenientes dessa consulta.
Por exemplo, o registro contém campo1, campo2 e campo3. A consulta completa seria:
SELECT "ID", " field1", "campo2", "campo3", (SELECT COUNT ("ID") FROM
"Tabela" WHERE "ID" <= "a". "ID") AS "Nr." FROM "Table" COMO "a"
Uma numeração para um agrupamento correspondente também é possível:
SELECT "ID", "Cálculo", (SELECT COUNT ("ID") FROM "Tabela" WHERE "ID" <=
"a". "ID" E "Cálculo" = "a". "Cálculo") AS "Nr " FROM "Tabela" COMO "a"
ORDER BY "ID" ASC, "Nr." ASC
Aqui, uma tabela contém números calculados diferentes. ("Cálculo"). Para cada número calculado,
"Nr." é expresso separadamente em ordem crescente após a classificação no campo ID. Isso
produz uma numeração de 1 para cima.
Se a ordem de classificação real na consulta for concordar com os números de linha, um tipo apropriado de
classificação deverá ser mapeado. Para isso, o campo de classificação deve ter um valor único em todos
os registros. Caso contrário, dois números de lugar terão o mesmo valor. Isso pode realmente ser útil se,
por exemplo, a ordem de lugar em uma competição for descrita, pois resultados idênticos levarão a uma
posição conjunta. Para que a ordem do lugar seja expressa de tal maneira que, no caso de posições
conjuntas, o próximo valor seja omitido, a consulta precisa ser construída de maneira um pouco diferente:
SELECT "ID", (SELECT COUNT ("ID") + 1 de "Tabela" WHERE "Tempo" <"a".
"Tempo") AS "Place" FROM "Tabela" AS "a"
Todas as entradas são avaliadas para as quais o campo "Hora" tem um valor menor. Isso abrange todos os
atletas que alcançaram o posto vencedor antes do atleta atual. Para este valor é adicionado o número 1.
Isso determina o local do atleta atual. Se a hora é idêntica à de outro atleta, eles são colocados juntos. Isso
possibilita fazer pedidos como 1º Lugar, 2º Lugar, 2º Lugar, 4º Lugar.
Seria mais problemático, se os números de linha fossem necessários, bem como uma ordem de lugar.
Isso pode ser útil se vários registros precisassem ser combinados em uma linha.
SELECIONE "ID", (SELECT COUNT ("ID") + 1 FROM "Tabela" WHERE "Hora" <"a". "Hora") AS
"Place",
CASO QUANDO
(SELECT COUNT ("ID") + 1 FROM "Tabela" WHERE "Tempo" = "a". "Tempo") = 1
THEN (SELECT COUNT ("ID") + 1 FROM "Tabela" WHERE "Hora" <"a". "Hora")
ELSE (SELECT (SELECT COUNT ("ID") + 1 FROM "Tabela" WHERE "Tempo" <"a". "Tempo") +
COUNT ("ID") FROM "Tabela" WHERE "Tempo" = "a". "Hora" "ID" <"a". "ID"
FIM
AS "LineNumber" FROM "Tabela" COMO "a"
A segunda coluna ainda dá a ordem do lugar. A terceira coluna verifica primeiro se apenas uma pessoa
cruzou a linha com este tempo. Nesse caso, a ordem do local é convertida diretamente em um número de
linha. Caso contrário, um valor adicional é adicionado à ordem do local. Para o mesmo tempo (
"Tempo" = "a". "Tempo" ) pelo menos 1 é adicionado, se houver mais uma pessoa com o ID da
chave primária, cuja chave primária é menor que a chave primária no registro atual ( " ID "<" a
"." ID " ). Essa consulta, portanto, produz valores idênticos para a ordem de lugar, desde que não
exista uma segunda pessoa com o mesmo tempo. Se uma segunda pessoa com o mesmo tempo existir, o
ID determina qual pessoa tem o menor número de linha.
Aliás, essa classificação por número de linha pode servir para qualquer finalidade que os usuários do banco
de dados desejarem. Por exemplo, se uma série de registros for classificada por nome, os registros com o
mesmo nome não serão classificados aleatoriamente, mas de acordo com sua chave primária, que é
obviamente exclusiva. Desta forma também, numeração pode levar a uma classificação de registros.
A numeração de linhas também é um bom prelúdio para a combinação de registros individuais em um
único registro. Se uma consulta de numeração de linhas for criada como visualização, uma consulta
adicional poderá ser aplicada sem criar nenhum problema. Como um exemplo simples aqui, mais uma vez
é a primeira consulta de numeração com um campo extra:
SELECT "ID", "Nome", (SELECT COUNT ("ID") FROM "Tabela" WHERE "ID" <= "a".
"ID") AS "Nr." FROM "Table" COMO "a"
Esta consulta é transformada na exibição " View1" . A consulta pode ser usada, por exemplo, para colocar
os três primeiros nomes juntos em uma linha:
SELECT "Name" AS "Name_1", (SELECT "Nome" FROM "View1" WHERE "Nr." = 2)
COMO "Name_2", (SELECT "Nome" FROM "View1" WHERE "Nr." = 3) AS " Name_3
"FROM" View1 "WHERE" Nr. " = 1
Desta forma, vários registros podem ser convertidos em campos adjacentes. Essa numeração
simplesmente é executada do primeiro ao último registro.
Se todos esses indivíduos tiverem o mesmo sobrenome, isso pode ser feito da seguinte maneira:
SELECT "ID", "Nome", "Sobrenome", (SELECT COUNT ( "ID") FROM "Tabela" ONDE
"ID" <= "a". "ID" e "Sobrenome" = "a". "Sobrenome" ) AS "Nr." FROM "Table"
COMO "a"
Agora que a vista foi criada, a família pode ser montada.
SELECT "Sobrenome", "Nome" AS "nome_1", (selecione "Nome" de "View1" ONDE
"Nr." = 2 e "Sobrenome" = "a". "Sobrenome") como "NAME_2", (SELECT " Nome"
de "View1" ONDE "Nr."= 3 e "Sobrenome"= "a". "Sobrenome") como "NAME_3"
FROM "View1" AS "a" ONDE "Nr." = 1
Dessa forma, em um catálogo de endereços, todos os membros de uma família ("Sobrenome") podem ser
coletados juntos para que cada endereço seja considerado apenas uma vez ao enviar uma carta, mas
todos que receberem a carta serão listados.
Precisamos ter cuidado aqui, pois não queremos uma função infinitamente loop. A consulta no exemplo
acima limita os registros paralelos que devem ser convertidos em campos para 3. Esse limite foi escolhido
deliberadamente. Nenhum outro nome aparecerá, mesmo que o valor de "Nr". é maior que 3.
Em alguns casos, tal limite é claramente compreensível. Por exemplo, se estamos criando um calendário,
as linhas podem representar as semanas do ano e as colunas os dias da semana. Como no calendário
original, apenas a data determina o conteúdo do campo, a numeração de linhas é usada para numerar os
dias de cada semana continuamente e, em seguida, as semanas do ano se tornam os registros. Isso exige
que a tabela contenha um campo de data com datas contínuas e um campo para os eventos. Além disso, a
data mais antiga sempre criará um "Nr." = 1. Portanto, se você quiser que o calendário comece na
segunda-feira, a data mais próxima deve ser na segunda-feira. A coluna 1 é então segunda-feira, coluna 2
terça-feira e assim por diante. A subconsulta termina em "Nr". = 7. Desta forma, todos os sete dias da
semana podem ser mostrados lado a lado e uma vista de calendário correspondente criada.

Obtendo uma quebra de linha através de uma consulta


Às vezes, é útil montar vários campos usando uma consulta e separá-los por quebras de linha, por
exemplo, ao ler um endereço completo em um relatório.
A quebra de linha dentro da consulta é representada por 'Char (13)' . Exemplo:
SELECIONE "Nome" || ' '|| "Apelido" || Char (13) || "Estrada" || Char (13)
|| "Cidade" FROM "Tabela"
Isso produz:
Nome Sobrenome
Road
Town
Essa consulta, com uma linha com até 3 números, permite imprimir etiquetas de endereço em três
colunas, criando um relatório. A numeração é necessária nesta conexão para que três endereços possam
ser colocados próximos um do outro em um registro. Essa é a única maneira pela qual eles permanecerão
próximos um do outro quando lidos no relatório.
Agrupando e resumindo
Para outros bancos de dados e para versões mais recentes do HSQLDB, o comando Group_Concat
() está disponível. Pode ser usado para agrupar campos individuais em um registro em um campo.
Assim, por exemplo, é possível armazenar nomes próprios e sobrenomes em uma tabela e, em seguida,
apresentar os dados de tal forma que um campo mostre os sobrenomes como nomes de família enquanto
um segundo campo contém todos os primeiros nomes relevantes sequencialmente, separados por
vírgulas.
Este exemplo é semelhante em muitos aspectos à numeração de linhas. O agrupamento em um campo
comum é um tipo de suplemento para isso.
Sobrenome Primeiro nome
Müller Karin
Schneider Gerd
Müller Egon
Schneider Volker
Müller Monika
Müller Rita

é convertido pela consulta para:


Sobrenome Primeiro nome
Müller Karin, Egon, Monika,
Rita
Schneider Gerd, Volker

Esse procedimento pode, dentro dos limites, ser expresso no HSQLDB. O exemplo a seguir refere-se a
uma tabela chamada Name com os campos ID, Firstname e Surname . A consulta a seguir é executada
pela primeira vez na tabela e salva como uma exibição chamada View_Group.
SELECT "Sobrenome", "Nome", (SELECT COUNT ("ID") FROM "Nome" WHERE "ID" <=
"a". "ID" AND "Sobrenome" = "a". "Sobrenome") AS "GroupNr "FROM" Name "AS"
a "
Você pode ler no capítulo Consultas como essa consulta acessa o conteúdo do campo na mesma linha de
consulta. Produz uma sequência numerada ascendente, agrupada por sobrenome . Essa numeração é
necessária para a consulta a seguir, de modo que, no exemplo, um máximo de 5 primeiros nomes seja
listado.
SELECIONAR "Sobrenome",
(SELECT "Nome" FROM "View_Group" WHERE "Apelido" = "a". "Apelido" E
"GroupNr" = 1) ||
IFNULL ((SELECT ',' || "Nome" FROM "View_Group" WHERE "Apelido" = "a".
"Sobrenome" AND "GroupNr" = 2), '') ||
IFNULL ((SELECT ',' || "Nome" FROM "View_Group" WHERE "Apelido" = "a".
"Sobrenome" AND "GroupNr" = 3), '') ||
IFNULL ((SELECT ',' || "Nome" FROM "View_Group" WHERE "Apelido" = "a".
"Sobrenome" AND "GroupNr" = 4), '') ||
IFNULL ((SELECT ',' || "Nome" FROM "View_Group" WHERE "Apelido" = "a".
"Sobrenome" AND "GroupNr" = 5), '')
COMO "Firstnames"
FROM "View_Group" COMO "a"
Usando subconsultas, os primeiros nomes dos membros do grupo são pesquisados um após o outro e
combinados. A partir da segunda subconsulta, você deve garantir que os valores 'NULL' não
definam a combinação inteira como 'NULL' . É por isso que um resultado de '' em vez de
'NULL' é mostrado.
Capítulo 9 Macros

Comentários gerais sobre macros


Em princípio, um banco de dados no Base pode gerenciar sem macros. Às vezes, no entanto, eles podem
se tornar necessários para:
•Prevenção mais eficaz de erros de entrada
•S implantar certas tarefas de processamento (mudar de uma forma para outra, atualizar dados após a
entrada em um formulário e assim por diante )
•A necessidade de certos comandos SQL serem chamados mais facilmente do que com o editor de SQL
separado.
Você deve decidir por sua sel f quão intensivamente y UO deseja usar macros na Base. As macros podem
melhorar a usabilidade, mas são sempre associado a pequenas reduções na velocidade do programa, e às
vezes com os maiores (quando codificado pobre ly). É sempre melhor começar por totalmente utili z ing as
possibilidades do banco de dados e as disposições para a configuração de formas antes de tentar fornecer
funcionalidade adicional com macros. As macros devem sempre ser testadas em bancos de dados
maiores para determinar seu efeito no desempenho .
As macros são criadas usando Ferramentas > Macros > Organizar macros > LibreOffice Basic .
Aparece uma janela que fornece acesso a todas as macros. Para Base, a área importante corresponde ao
nome do arquivo base.

O botão Novo na caixa de diálogo LibreOffice Basic Ma c ros abre a caixa de diálogo Novo Módulo , que
solicita o nome do módulo (a pasta na qual a macro será arquivada). O nome pode ser alterado mais tarde,
se desejado.
Assim que isso é fornecido, o editor de macro é exibido. A área de entrada já contém o início e o fim de
uma sub - rotina :
REM ***** BASIC *****
Sub Main
End Sub
Se as macros forem utilizáveis, as etapas a seguir são necessárias:
•Sob Ferramentas > Opções > Segurança > Segurança Macro o nível de segurança deve ser reduzida
para Médio. Se necessário, você também pode usar a guia Fontes confiáveis para definir o caminho para
seus próprios arquivos de macro para evitar consultas posteriores sobre a ativação de macros.
•O arquivo de banco de dados deve ser fechado e reaberto após a criação do primeiro módulo de macro.
Alguns princípios básicos para o uso do código básico no LibreOffice:
• Aslinhas não possuem números de linha e devem terminar com um retorno difícil.
•Funções, expressões reservadas e elementos semelhantes não diferenciam maiúsculas de minúsculas.
Então, "String" é o mesmo que "STRING" ou "string" ou qualquer outra combinação de letras maiúsculas e
minúsculas. Caso deve ser usado apenas para melhorar a legibilidade. Os nomes para constantes e
enumerações, no entanto, diferenciam maiúsculas e minúsculas na primeira vez que são vistos pelo
compilador de macros, portanto, é melhor sempre gravar os que usam o caso apropriado.
•Existe uma diferença básica entre sub-rotinas (começando com SUB) e funções (começando com
FUNCTION). Sub-rotinas são segmentos de programa sem valores de retorno. Funções retornam um
valor.
Para mais detalhes veja o Capítulo 13, Introdução ao Macros, no Getting Started guia.

As macros nas versões PDF e ODT deste capítulo são coloridas de acordo
com as regras do editor de macros do LibreOffice:
Designação de macro Comentário de macro Operador de macro
Expressão reservada de macro Número de macro Sequência de
Nota caracteres de macro

Melhorando a usabilidade
Para esta primeira categoria de uso macro, mostramos várias possibilidades para melhorar a usabilidade
dos formulários Base.

Atualização automática de formulários


Muitas vezes algo é alterado em um formulário e essa alteração é necessária para aparecer em um
segundo formulário na mesma página. O trecho de código a seguir chama o método de recarregamento no
segundo formulário, fazendo com que ele seja atualizado .
Atualização SUB
Primeiro a macro é nomeada. A designação padrão para uma macro é SUB . Isso pode ser escrito em
letras maiúsculas ou minúsculas. SUB permite que uma sub - rotina seja executada sem retornar um
valor. Mais abaixo, por contraste, é descrita uma função, que retorna um valor.
A macro tem o nome Atualizar . Você não precisa declarar variáveis porque o LibreOffice Basic cria
automaticamente variáveis quando elas são usadas. Infelizmente, se você digitar incorretamente uma
variável, o LibreOffice Basic cria silenciosamente uma nova variável sem reclamar. Use Option
Explicit para impedir que o LibreoOffice Basic crie variáveis automaticamente; isso é recomendado
pela maioria dos programadores .
Portanto, geralmente começamos declarando variáveis. Todas as variáveis declaradas aqui são objetos
(não números ou texto), então adicionamos AS OBJECT ao final da declaração. Para nos lembrar mais
tarde do tipo das variáveis, introduzimos seus nomes com um "o" . Em princípio, no entanto, você pode
escolher praticamente qualquer nome de variável que desejar.
DIM oDOC COMO OBJETO
DIM oDrawpage COMO OBJETO
DIM oForm COMO OBJETO
O formulário está no documento atualmente ativo. O contêiner, no qual todos os formulários são
armazenados, é chamado de empate . No navegador de formulários, esse é o conceito de nível
superior, ao qual todos os formulários são subsidiários.
Neste exemplo, o formulário a ser acessado é denominado Display . Display é o nome visível no
navegador de formulários. Assim, por exemplo, o primeiro formulário, por padrão, é chamado de Formulário
1.
oDoc = thisComponent
oDrawpage = oDoc.drawpage
oForm = oDrawpage.forms.getByName ( "Display" )
Como o formulário agora está acessível e o ponto em que ele pode ser acessado é salvo na variável
oForm , ele é agora recarregado (atualizado) com o comando reload () .
oForm.reload ()
END SUB
A sub-rotina começa com SUB, então deve terminar com END SUB .
Essa macro agora pode ser selecionada para ser executada quando outro formulário é salvo. Por exemplo,
em uma caixa registradora ( até ) , se o número total de itens vendidos e seus números de estoque (lidos
por um scanner de código de barras) forem inseridos em um formulário, outro formulário na mesma janela
aberta pode mostrar os nomes de todos os itens e o custo total, assim que o formulário for salvo.

Registros de Filtragem
O próprio filtro pode funcionar perfeitamente na forma descrita em C apítulo 8, D atabase t pergunta . A
variante mostrada abaixo substitui o S botão ave e lê os listboxes novamente, de modo que um filtro
escolhido a partir de uma caixa de listagem pode restringir as opções disponíveis na outra caixa de
listagem.
Filtro SUB
DIM oDOC COMO OBJETO
DIM oDrawpage COMO OBJETO
DIM oForm1 COMO OBJETO
DIM oForm2 COMO OBJETO
DIM oFieldList1 COMO OBJETO
DIM oFieldList2 COMO OBJETO
oDoc = thisComponent
oDrawpage = oDoc.drawpage
Primeiro, as variáveis são definidas e definidas para acessar o conjunto de formulários. Este conjunto
compreende os dois formulários "Filter" e "Display". As caixas de listagem estão no formulário "Filtro" e
possuem os nomes "List_1" e "List_2".
oForm1 = oDrawpage.forms.getByName ( "Filtro" )
oForm2 = oDrawpage.forms.getByName ( "Display" )
oFieldList1 = oForm1.getByName ( "List_1" )
oFieldList2 = oForm1.getByName ( "List_2" )
Primeiro, o conteúdo das listboxes é transferido para o formulário subjacente usando commit () . A
transferência é necessário, porque de outro modo a mudança de uma caixa de listagem não será reconhe z
ed quando poupança. A Commit () em struction só precisa de ser aplicada à caixa de
listagem que acaba de ser acessado. Depois disso, o registro é salvo usando updateRow () . Em
princípio, nossa tabela de filtros contém apenas um registro, que é escrito uma vez no início. Este registro é
então sobrescrito continuamente usando um comando de atualização.
oFieldList1.commit ()
oFieldList2.commit ()
oForm1.updateRow ()
As caixas de listagem servem para influenciar umas as outras. Por exemplo, se uma caixa de listagem for
usada para restringir a mídia exibida aos CDs, a outra caixa de listagem não deverá incluir todos os
gravadores de livros em sua lista de autores. Uma seleção na segunda caixa de listagem resultaria em um
filtro vazio. É por isso que os listboxes devem ser lidos novamente. Estritamente falando, o comando
refresh () só precisa ser executado na caixa de listagem que não foi acessada.
Depois disso, o form2, que deve exibir o conteúdo filtrado, é lido novamente.
oFieldList1.refresh ()
oFieldList2.refresh ()
oForm2.reload ()
END SUB
Caixas de listagem que devem ser influenciadas usando esse método podem ser fornecidas com conteúdo
usando várias consultas.
A variante mais simples é fazer com que a caixa de listagem leve seu conteúdo dos resultados do filtro. Em
seguida, um único filtro determina qual conteúdo de dados será filtrado posteriormente.
SELECIONE "Field_1" || '-' || "Contagem" AS "Display", "Field_1"
FROM (SELECT COUNT ("ID") como "Contagem", "Field_1" de
"Table_Filter_result" GROUP BY "Field_1")
ORDER BY "Field_1"
O conteúdo do campo e o número de ocorrências são exibidos. Para obter o número de ocorrências, uma
subconsulta é usada. Isso é necessário, caso contrário, apenas o número de ocorrências, sem mais
informações do campo, será mostrado na caixa de listagem.
A macro cria listboxes rapidamente por essa ação; eles são preenchidos com apenas um valor. Se uma
caixa de listagem não for NULL, ela será levada em conta pela filtragem. Após a ativação da segunda caixa
de listagem, somente os campos vazios e um valor exibido estarão disponíveis para ambas as caixas de
listagem. Isso pode parecer prático para uma pesquisa limitada. Mas, e se um catálogo da biblioteca
mostrar claramente a classificação de um item, mas não mostrar exclusivamente se é um livro, um CD ou
um DVD? Se a classificação for escolhida primeiro e a segunda caixa de listagem for definida como "CD",
ela deverá ser redefinida como NULL para realizar uma pesquisa subsequente que inclua livros. Seria mais
prático se a segunda caixa de listagem mostrasse diretamente os vários tipos de mídia disponíveis, com
as contagens de ocorrências correspondentes.
Para atingir este objetivo, é construída a seguinte consulta, que não é mais alimentada diretamente dos
resultados do filtro. O número de ocorrências deve ser obtido de maneira diferente.
SELECIONAR
IFNULL ("Field_1" || '-' || "Count", 'empty -' || "Contagem") AS "Display",
"Field_1"
A PARTIR DE
(SELECT COUNT ("ID") COMO "Contagem", "Campo_1" DA "Tabela" WHERE "ID" IN
(SELECT "Tabela". "ID" FROM "Filtro", "Tabela" WHERE "Tabela". "Campo_2" =
IFNULL ("Filtro". "Filtro_2", "Tabela". "Campo_2"))
GROUP BY "Field_1")
ORDER BY "Field_1"
Essa consulta muito complexa pode ser dividida. Na prática, é comum usar uma VIEW para a
subconsulta. A caixa de listagem recebe seu conteúdo a partir de uma consulta relativa ao thi s VIEW.
A consulta em detalhes: A consulta apresenta duas colunas. A primeira coluna contém a visualização vista
por uma pessoa que tenha o formulário aberto. Essa visualização mostra o conteúdo do campo e,
separados por um hífen, os hits desse conteúdo de campo. A segunda coluna transfere seu conteúdo para
a tabela subjacente do formulário. Aqui temos apenas o conteúdo do campo. As caixas de listagem, assim,
extraem seu conteúdo da consulta, que é apresentada como o resultado do filtro no formulário. Apenas
esses campos estão disponíveis para filtragem adicional.
A tabela da qual essa informação é desenhada é, na verdade, uma consulta. Nessa consulta, os campos
da chave primária são contados ( SELECT COUNT ("ID") AS "Count" ). Isso é então agrupado
pelo termo de pesquisa no campo ( GROUP BY "Field_1" ). Esta consulta apresenta o termo no
próprio campo como a segunda coluna. Essa consulta, por sua vez, é baseada em uma outra subconsulta:
SELECT "Table". "ID" FROM "Filtro", "Tabela" WHERE "Tabela". "Campo_2" =
IFNULL ("Filtro". "Filtro_2", "Tabela". "Campo_2")
Essa subconsulta lida com o outro campo a ser filtrado. Em princípio, esse outro campo também deve
corresponder à chave primária. Se houver outros filtros, essa consulta poderá ser estendida:
SELECT "Table". "ID" FROM "Filtro", "Tabela" ONDE
"Tabela". "Campo_2" = IFNULL ("Filtro". "Filtro_2", "Tabela". "Campo_2")
E
"Tabela". "Campo_3" = IFNULL ("Filtro". "Filtro_3", "Tabela". "Campo_3")
Isso permite que quaisquer campos adicionais que sejam filtrados controlem o que finalmente aparece na
caixa de listagem do primeiro campo, "Field_1".
Finalmente, toda a consulta é classificada pelo campo subjacente.
O que a consulta final subjacente ao formulário exibido, na verdade, parece, pode ser visto no Capítulo 8, o
Database T pergunta.
A macro a seguir pode controlar por meio de uma caixa de listagem quais caixas de listagem devem ser
salvas e quais devem ser lidas novamente.
A sub-rotina a seguir supõe que a propriedade “Informações adicionais” para cada caixa de listagem
contém uma lista separada por vírgulas de todos os nomes de caixas de listagem sem espaços. O
primeiro nome na lista deve ser o nome dessa caixa de listagem.
SUB Filter_more_info ( oEvent AS OBJECT )
DIM oDOC COMO OBJETO
DIM oDrawpage COMO OBJETO
DIM oForm1 COMO OBJETO
DIM oForm2 COMO OBJETO
DIM oFieldList1 COMO OBJETO
DIM oFieldList2 COMO OBJETO
DIM sTag AS String
sTag = oEvent.Source.Model.Tag
Uma matriz (uma coleção de dados acessíveis por meio de um número de índice) é estabelecida e
preenchida com os nomes dos campos das caixas de listagem. O primeiro nome na lista é o nome da
caixa de listagem vinculada ao evento.
aList () = Dividir ( sTag , "," )
oDoc = thisComponent
oDrawpage = oDoc.drawpage
oForm1 = oDrawpage.forms.getByName ( "Filtro" )
oForm2 = oDrawpage.forms.getByName ( "Display" )
A matriz é executada do limite inferior ( ' Lbound () ' ) até o limite superior ( '
Ubound () ' ) em um único loop. Todos os valores que foram separados por vírgulas nas
informações adicionais são agora transferidos sucessivamente.
PARA i = LBound ( aList ()) PARA UBound ( aList ())
SE i = 0 ENTÃO
A caixa de listagem que acionou a macro deve ser salva. É encontrado na variável aList (0) .
Primeiro, as informações da caixa de listagem são transportadas para a tabela subjacente e, em seguida, o
registro é salvo.
oForm1.getByName ( aList ( i )) .commit ()
oForm1.updateRow ()
OUTRO
As outras caixas de listagem devem ser atualizadas , pois agora elas contêm valores diferentes,
dependendo da primeira caixa de listagem.
oForm1.getByName ( aList ( i )) .refresh ()
FIM SE
PRÓXIMO
oForm2.reload ()
END SUB
As consultas para essa macro mais utilizável são naturalmente as mesmas que as apresentadas na seção
anterior.

Pesquisando registros de dados


Você pode pesquisar registros de banco de dados sem usar uma macro. No entanto, a consulta
correspondente que deve ser configurada pode ser muito complicada . Uma macro pode resolver esse
problema com um loop.
A sub-rotina a seguir lê os campos em uma tabela, cria uma consulta internamente e, finalmente, grava
uma lista de números de chave primária de registros na tabela que são recuperados por esse termo de
pesquisa. Na descrição a seguir, há uma tabela chamada Searchtmp, que consiste em um campo de
chave primária ( ID ) de incremento automático e um campo chamado Nr. que contém todas as chaves
primárias recuperadas da tabela que está sendo pesquisada. O nome da tabela é fornecido inicialmente
para a sub - rotina como uma variável.
Para obter um resultado correto, a tabela deve conter o conteúdo que você está procurando como texto e
não como chaves estrangeiras. Se necessário, você pode criar uma VIEW para a macro a ser usada .
Pesquisa SUB ( stTable AS STRING )
DIM oDataSource AS OBJECT
DIM oConnection COMO OBJETO
DIM oSQL_Statement COMO OBJETO
DIM stSql COMO STRING
DIM oQuery_Result AS OBJECT
DIM oDOC COMO OBJETO
DIM oDrawpage COMO OBJETO
DIM oForm COMO OBJETO
DIM oForm2 COMO OBJETO
DIM o campo como objeto
StContent DIM COMO STRING
DIM arContent () COMO STRING
DIM inI COMO INTEGER
DIM inK AS INTEGER
oDoc = thisComponent
oDrawpage = oDoc.drawpage
oForm = oDrawpage.forms.getByName ( "Searchform" )
oField = oForm.getByName ( "Searchtext" )
stContent = oField.getCurrentValue ()
stContent = LCase ( stContent )
O conteúdo do campo de texto de pesquisa é inicialmente convertido em minúsculas, para que a função de
pesquisa subseqüente precise comparar apenas as ortografias em minúsculas.
oDataSource = ThisComponent.Parent.DataSource
oConnection = oDataSource.GetConnection ( "" , "" )
oSQL_Statement = oConnection.createStatement ()
Primeiro, deve ser determinado se um termo de pesquisa foi realmente inserido. Se o campo estiver vazio,
será assumido que nenhuma pesquisa é necessária. Todos os registros serão exibidos sem mais
pesquisas.
Se um termo de pesquisa tiver sido inserido, os nomes das colunas serão lidos na tabela que está sendo
pesquisada, para que a consulta possa acessar os campos.
IF stContent <> "" ENTÃO
stSql = "SELECT" "COLUMN_NAME" "FROM" "INFORMATION_SCHEMA" "."
"SYSTEM_COLUMNS" "WHERE" "TABLE_NAME" "= '" + stTable + "' ORDER BY"
"ORDINAL_POSITION" ""
oQuery_Result = oSQL_Statement.executeQuery ( stSql )

As fórmulas SQL em macros devem primeiro ser colocadas entre aspas


duplas, como as cadeias de caracteres normais s . Nomes de campos e
tabelas já estão entre aspas duplas dentro da fórmula SQL. Para criar um
código final que transmita as aspas duplas corretamente, os nomes de
Nota campos e de tabelas devem receber dois conjuntos dessas citações.
stSql = "SELECT" "Nome" "FROM" "Tabela" ";"
torna-se, quando exibido com o comando msgbox stSql ,
SELECT "Name" FROM "Table"

O índice da matriz, na qual os nomes dos campos são gravados, é inicialmente definido como 0. Em
seguida, a consulta começa a ser lida. Como o tamanho do array é desconhecido, ele deve ser ajustado
continuamente. É por isso que o loop começa com ' ReDim Preserve arContent (inI)
' para definir o tamanho da matriz e, ao mesmo tempo, preservar seu conteúdo existente. Em
seguida, os campos são lidos e o índice da matriz é incrementado em 1. Em seguida, a matriz é
dimensionada novamente e um valor adicional pode ser armazenado.
InI = 0
IF NOT ISNULL ( oQuery_Result ) ENTÃO
QUANDO oQuery_result.next
ReDim Preservar arContent ( INI )
arContent ( INI ) = oQuery_Result.getString ( 1 )
inI = inI + 1
WEND
FIM SE
stSql = "DROP TABLE" "Searchtmp" "SE EXISTE"
oSQL_Statement.executeUpdate ( stSql )
Agora, a consulta é reunida em um loop e subsequentemente aplicada à tabela definida no início. Todas as
combinações de maiúsculas e minúsculas são permitidas, pois o conteúdo do campo na consulta é
convertido em minúsculas.
A consulta é construída de forma que os resultados acabem na tabela Searchtmp. Supõe-se que a chave
primária é o primeiro campo na tabela ( arContent (0) ).
stSql = "SELECT" "" + arContent ( 0 ) + "" "INTO" "Searchtmp" "FROM" "" +
stTable + "" "WHERE"

FOR inK = 0 TO ( inI - 1 )


stSql = stSql + "LCase (" "" + arContent ( inK ) + "" ") COMO '%" +
stContent + "%'"
IF inK <( inI - 1 ) ENTÃO
stSql = stSql + "OR"
FIM SE
PRÓXIMO
oSQL_Statement.executeQuery ( stSql )
OUTRO
stSql = "DELETE FROM" "Searchtmp" ""
oSQL_Statement.executeUpdate ( stSql )
FIM SE
O formulário de exibição deve ser recarregado. Sua fonte de dados é uma consulta, neste exemplo
Searchquery.
oForm2 = oDrawpage.forms.getByName ( "Display" )
oForm2.reload ()
End Sub
Isso cria uma tabela que deve ser avaliada pela consulta. Tanto quanto possível, a consulta deve ser
construída para que possa ser editada posteriormente. Uma consulta de amostra é mostrada:
SELECT * FROM "Searchtable" ONDE "Nr." IN (SELECT "Nr." FROM "Searchtmp")
OU "Nr." = CASO QUANDO (SELECT COUNT ("Nr.") FROM "Searchtmp")> 0 ENTÃO "0"
ELSE "Nr." FIM
Todos os elementos da tabela de pesquisa estão incluídos, incluindo a chave primária. Nenhuma
outra tabela aparece na consulta direta; portanto, nenhuma chave primária de outra tabela é necessária e o
resultado da consulta permanece editável.
A chave primária é salva neste exemplo sob o nome Nr. A macro lê precisamente esse campo. Há
uma verificação inicial para ver se o conteúdo do Nr. campo aparece na tabela Searchtmp .
O operador IN é compatível com vários valores. A subconsulta também pode gerar vários
registros.
Para quantidades maiores de dados, a correspondência de valor usando o operador IN diminui
rapidamente. Portanto, não é uma boa ideia usar um campo de pesquisa vazio simplesmente para
transferir todos os campos de chave primária de Searchtable para a tabela Searchtmp e, em
seguida, visualizar os dados da mesma maneira. Em vez disso, um campo de pesquisa vazio cria uma
tabela Searchtmp vazia , para que nenhum registro esteja disponível. Este é o objetivo da segunda
metade da condição:
OU "Nr." = CASO QUANDO (SELECT COUNT ("Nr.") FROM "Searchtmp")> 0 ENTÃO
'-1' ELSE "Nr." FIM
Se um registro for encontrado na tabela Searchtmp, isso significa que o resultado da primeira consulta é
maior que 0. Nesse caso: "Nr." = '-1' (aqui precisamos de um número que não pode ocorrer
como chave primária, então '-1' é um bom valor ). Se a consulta gerar precisamente 0 (o que
será o caso se nenhum registro estiver presente), então "Nr." = "Nr." . Isto irá listar cada registro
que tem um Nr. Como Nr. é a chave primária, isso significa todos os registros.

Comboboxes como listboxes com uma opção de entrada


Uma tabela com um único registro pode ser criada diretamente usando caixas de combinação e campos
numéricos invisíveis e a chave primária correspondente inserida em outra tabela.
Nas versões anteriores do L ibre O ffice ou O pen O ffice. o rg, era necessário tornar os campos numéricos
invisíveis usando uma macro. Isso não é mais necessário no LibreOffice, pois a propriedade 'visible' agora
está contida na GUI.
O controle Combobox trata campos de formulário para entrada combinada e escolha de valores (caixas de
combinação) como caixas de listagem com uma opção de entrada. Para esse propósito, além das caixas
de combinação no formulário, os valores de campo chave que devem ser transferidos para a tabela
subjacente são armazenados em campos numéricos separados. Estes campos, antes da O pen O ffice. o
rg 3.3, tinha que ter o conjunto de switch 'invisível', já que a função não era acessível a partir do design de
formulário. Este não é mais necessário no LibreOffice e O pen O ffice. o rg3.3. Campos agora podem ser
declarados como invisíveis. As chaves desses campos são lidas quando o formulário é carregado e a
caixa de combinação é definida para mostrar o conteúdo correspondente. Se o conteúdo da caixa de
combinação for alterado, ele será salvo e a nova chave primária será transferida para o campo numérico
correspondente a ser armazenado na tabela principal.
O original deste módulo está no banco de dados de exemplo, conforme expandido com macros.

Exibição de texto em comboboxes


Esta sub - rotina é mostrar o texto na caixa de combinação de acordo com o valor dos campos de chave
estrangeira invisíveis do formulário principal. Também pode ser usado para listboxes que se referem a duas
tabelas diferentes. Isso pode acontecer se, por exemplo, o código postal em um endereço postal for
armazenado separadamente da cidade. Nesse caso, o código postal pode ser lido de uma tabela que
contém apenas uma chave estrangeira para a cidade. A caixa de listagem deve mostrar o código postal e a
cidade juntos.
SUB TextDisplay ( NameForm AS STRING , NameSubform AS STRING , NameSubSubform AS
STRING , NameField AS STRING , NameIDField AS STRING , NameTableField1 AS STRING ,
NameTableField2 AS STRING , Fieldseparador AS STRING , NameTable1 AS STRING ,
OPCIONAL NameTable2 AS STRING , OPCIONAL NameTab12ID AS STRING , posição OPCIONAL
COMO INTEGER )
Essa macro deve estar vinculada aos seguintes eventos de formulário: 'Ao carregar' e 'Após a alteração do
registro'.
Os seguintes parâmetros são opcionais e não precisam ser fornecidos quando a sub - rotina é chamada.
Para evitar um erro de tempo de execução, os valores padrão devem ser predefinidos.
Se isMissing ( NameTable2 ) THEN NameTable2 = ""
Se isMissing ( NameTab12ID ) THEN NameTab12ID = ""
IF isMissing ( Position ) THEN Position = 2
A condição IF aqui é apenas uma linha, por isso não requer um END IF .
Depois disso, as variáveis são declaradas. Algumas variáveis já foram declaradas globalmente em um
módulo separado e não são declaradas aqui novamente.
DIM oForm COMO OBJETO
DIM oSubForm COMO OBJETO
DIM oSubSubForm COMO OBJETO
DIM o campo como objeto
DIM oFieldList COMO OBJETO
DIM stFieldValue AS STRING
DIM inID AS INTEGER
DIM oCtlView COMO OBJETO
oDoc = thisComponent
oDrawpage = oDoc.Drawpage
oForm = oDrawpage.forms.getByName ( NameForm )
A posição do campo na forma correspondente é determinada. Todos os formulários são mantidos no
Drawpage do documento atual thisComponent . Essa sub-rotina usa argumentos para cobrir a
possibilidade de que o campo esteja contido em um subformulário de um subformulário, ou seja, dois níveis
abaixo do formulário real. O campo que contém a chave estrangeira é denominado oField . A
combobox, que agora existe em vez de uma caixa de listagem, é denominada oFieldList .
IF NameSubform <> "" ENTÃO
oSubForm = oForm.getByName ( NameSubform )
IF NameSubSubform <> "" ENTÃO
oSubSubForm = oSubForm.getByName ( NameSubSubform )
oField = oSubSubForm.getByName ( NameIDField )
oFieldList = oSubSubForm.getByName ( NameField )
OUTRO
oField = oSubForm.getByName ( NameIDField )
oFieldList = oSubForm.getByName ( NameField )
FIM SE
OUTRO
oField = oForm.getByName ( NameIDField )
oFieldList = oForm.getByName ( NameField )
FIM SE
oFieldList.Refresh ()
A caixa de combinação é lida novamente usando Atualizar () . Pode ser que o conteúdo do campo
tenha sido alterado pela entrada de novos dados. Isso deve ser possível.
Depois disso, o valor da chave estrangeira é lido. Somente se um valor for inserido aqui, será feita uma
conexão com a fonte de dados.
IF NOT IsEmpty ( oField.getCurrentValue ()) ENTÃO
inID = oField.getCurrentValue ()
oDataSource = ThisComponent.Parent.CurrentController
IF NOT ( oDataSource.isConnected ()) então
oDataSource.connect ()
Fim se
oConnection = oDataSource.ActiveConnection ()
oSQL_Statement = oConnection.createStatement ()
A instrução SQL é formulada de acordo com os campos usados na caixa de combinação. Isso requer o
teste de várias combinações. O mais geral é que a caixa de combinação deve ser fornecida com uma
consulta que se refere a dois campos da tabela de tabelas diferentes. Esta sub - rotina não foi projetada
para outras possibilidades. O teste começa com essa possibilidade mais importante.
IF NameTableField2 <> "" ENTÃO
Se houver um segundo campo de tabela,
IF NameTable2 <> "" ENTÃO
... e se existir uma segunda tabela, o seguinte código SQL será produzido:
SE posição = 2 ENTÃO
stSql = "SELECT" "" + NameTable1 + "" "." "" + NameTableField1 + "" "|| '" +
Fieldseparator + "' ||" "" + NameTable2 + "" "." "" + NameTablenField2 + "" "FROM"
"" + NameTable1 + "" "," "" + NameTable2 + "" "WHERE" "ID" "= '"+ inID + "'AND" "" +
NameTable1 + "" "." "" + NameTab12ID + "" "=" "" + NameTable2 + "" "." "ID" ""
OUTRO
stSql = "SELECT" "" + NameTable2 + "" "." "" + NameTableField2 + "" "|| '" +
Fieldseparator + "' ||" "" + NameTable1 + "" "." "" + NameTableField1 + "" "FROM" ""
+ NameTable1 + "" "," "" + NameTable2 + "" "WHERE" "ID" "= '"+ inID + "'AND" "" +
NameTable1 + "" "." "" + NameTab12ID + "" "=" "" + NameTable2 + "" "." "ID" ""
FIM SE
Quando escrito na forma exigida pelo Basic, este comando SQL é bastante incompreensível. Cada campo
e cada nome de tabela deve ser escrito na entrada SQL com dois conjuntos de aspas duplas, conforme
mostrado acima. Como as aspas duplas são normalmente interpretadas pelo Basic como texto de
indicação, elas desaparecem quando o código é transferido. Somente quando um segundo conjunto de
aspas duplas é usado, os termos são transmitidos em cotações simples. "" ID "" significa, portanto,
que o campo "ID" (com um único conjunto de aspas para o relacionamento SQL) é acessado na
consulta. Uma simplificação parcial para esta sub - rotina é que todas as chaves primárias neste banco de
dados possuem o nome ID.
O código é ainda mais complicado pelo fato de que, além de exigir aspas duplas, alguns dos campos da
tabela incluídos são inseridos como variáveis. Estes não são texto; eles são simplesmente concatenados
com o texto anterior usando +. Mas essas variáveis também devem ser mascaradas. É por isso que
essas variáveis são mostradas acima com três conjuntos de aspas: "" "+ NameTable1 +" "".
"" "NameTableField1 +" "" se traduz na linguagem de consulta familiar "Table1".
"Field1" . Felizmente, quando criamos a macro, a coloração do código mostra se alguma aspas duplas
foram omitidas. As aspas mudam de cor imediatamente se não forem reconhecidas pela macro como
delimitadores de cadeia.
OUTRO
... e se a segunda tabela não existir, o seguinte código SQL será criado:
SE posição = 2 ENTÃO
stSql = "SELECT" "" + NameTableField1 + "" "|| '" + Fieldseparator +
"' ||" "" + NameTableField2 + "" "FROM" "" + NameTable1 + "" "WHERE" "ID" "= '" +
inID + "' "
OUTRO
stSql = "SELECT" "" + NameTableField2 + "" "|| '" + Fieldseparator +
"' ||" "" + NameTableField1 + "" "FROM" "" + NameTable1 + "" "WHERE" "ID" "= '" +
inID + "' "
FIM SE
FIM SE
OUTRO
Se um segundo campo de tabela não existir, pode haver apenas uma tabela. Isso produz a seguinte
consulta:
stSql = "SELECT" "" + NameTableField1 + "" "FROM" "" + NameTable1 + ""
"WHERE" "ID" "= '" + inID + "'"
FIM SE
A consulta armazenada na variável stSql agora é executada e o resultado da consulta é armazenado
na variável oQuery_result .
oQuery_result = oSQL_Statement.executeQuery ( stSql )
O resultado da consulta é lido em um loop. Aqui, como nas consultas da GUI, vários campos e registros
podem ser criados. Mas a construção dessa consulta produzirá apenas um resultado. Este resultado será
encontrado na primeira coluna (1) da consulta. É o registro que fornece o conteúdo que a caixa de
combinação deve exibir. O conteúdo é uma string de texto ( ' getString () ' ), então aqui
vemos ' oQuery_result.getString (1) ' .
IF NOT IsNull ( oQuery_result ) ENTÃO
QUANDO oQuery_result.next
stFieldValue = oQuery_result.getString ( 1 )
WEND
A caixa de combinação agora deve ser definida para os valores de texto resultantes da consulta. Isso
requer acesso ao controlador.
oDocCrl = ThisComponent.getCurrentController ()
oCtlView = oDocCrl.GetControl ( oFieldList )
oCtlView.setText ( stFieldValue )
FIM SE
FIM SE
Se não houver nenhum valor no campo para a chave estrangeira 'oField', isso significa que a consulta
falhou. A caixa de combinação é então definida para um display vazio.
IF IsEmpty ( oField.getCurrentValue ()) ENTÃO
oDocCrl = ThisComponent.getCurrentController ()
oCtlView = oDocCrl.GetControl ( oFieldList )
oCtlView.setText ( "" )
FIM SE
END SUB
Essa sub-rotina manipula o contato entre as chaves estrangeiras em um campo oculto e a caixa de
combinação. Isso é suficiente para a exibição dos valores corretos na caixa de combinação. Para
armazenar um novo valor, é necessária uma sub-rotina adicional .

Transferindo um valor de chave estrangeira de uma caixa de combinação para um campo


numérico
Se um novo valor for inserido na caixa de combinação (e, afinal, esse é o propósito para o qual essa macro
foi construída), a chave primária correspondente deve ser inserida na tabela subjacente do formulário como
uma chave estrangeira.
SUB TextChoiceValueSave ( NameForm AS STRING, NameSubform AS STRING, NameSubSubform
AS STRING, NameField AS STRING, NameIDField AS STRING, NameTableField1 AS STRING,
NameTableField2 AS STRING, FieldSeparator AS STRING , NameTable1 AS STRING, OPCIONAL
NameTable2 AS STRING, OPCIONAL NameTab12ID AS STRING, OPCIONAL Posição AS INTEGER )
Essa macro deve ser vinculada ao seguinte evento de formulário: 'Before record action'.
O início desta função corresponde, em princípio, à sub-rotina descrita anteriormente . Aqui também existem
variáveis opcionais .
Se isMissing ( NameTable2 ) THEN NameTable2 = ""
Se isMissing ( NameTab12ID ) THEN NameTab12ID = ""
IF isMissing ( Position ) THEN Position = 2
Depois disso, as outras variáveis são declaradas, aquelas que ainda não foram declaradas fora da sub -
rotina ou função. Em seguida, o formulário é carregado e os campos relevantes são alocados para
variáveis. O campo oField contém a chave estrangeira e o oFieldList mostra o texto
correspondente.
DIM oForm COMO OBJETO
DIM oSubForm COMO OBJETO
DIM oSubSubForm COMO OBJETO
DIM o campo como objeto
DIM oFieldList COMO OBJETO
StContent DIM COMO STRING
DIM stContentField2 COMO STRING
DIM a_stPart () COMO STRING
DIM stmsgbox1 COMO STRING
DIM stmsgbox2 COMO STRING
DIM inID1 AS INTEGER
DIM inID2 AS INTEGER
DIM Field1Length AS INTEGER
DIM Field2Length AS INTEGER
O comprimento máximo permitido para uma entrada é determinado usando a função Columnsize, descrita
abaixo. Apenas definir um limite no tamanho da caixa de combinação não é seguro aqui, pois precisamos
incluir a possibilidade de inserir dois campos juntos.
Field1Length = Columnsize ( NameTable1, NameTableField1 )
IF NameTableField2 <> "" ENTÃO
IF NameTable2 <> "" ENTÃO
Feld2Length = Columnsize ( NameTable2, NameTableField2 )
OUTRO
Feld2Length = Columnsize ( NameTable1, NameTableField2 )
END IF
OUTRO
Feld2Length = 0
END IF
O formulário é carregado e o comobox é lido.
oDoc = thisComponent
oDrawpage = oDoc.Drawpage
oForm = oDrawpage.Forms.getByName ( NameForm )
IF NameSubform <> "" ENTÃO
oSubForm = oForm.getByName ( NameSubform )
IF NameSubSubform < > "" ENTÃO
oSubSubForm = oSubForm.getByName ( NameSubSubform )
oField = oSubSubForm.getByName ( NameIDField )
oFieldList = oSubSubForm.getByName ( NameField )
OUTRO
oField = oSubForm.getByName ( NameIDField )
oFieldList = oSubForm.getByName ( NameField )
END IF
OUTRO
oField = oForm.getByName ( NameIDField )
oFieldList = oForm.getByName ( NameField )
END IF
stContent = oFieldList.getCurrentValue ()
O conteúdo exibido da caixa de combinação é lido. Espaços à esquerda e à direita e caracteres não
imprimíveis são removidos, se necessário.
StContent = Aparar ( stContent )
IF stContent <> "" ENTÃO
IF NameTableField2 <> "" ENTÃO
Se existir um segundo campo de tabela, o conteúdo da caixa de combinação deve ser dividido. Para
determinar onde a divisão deve ocorrer, usamos o separador de campo fornecido para a função como um
argumento.
a_stPart = Split ( stContent , FieldSeparator , 2 )
O último parâmetro significa que o número máximo de partes é 2.
Dependendo de qual entrada corresponde ao campo 1 e qual campo 2, o conteúdo da caixa de combinação
agora é alocado para as variáveis individuais. "Position = 2" serve aqui como um sinal de que a segunda
parte do conteúdo representa o campo 2.
SE posição = 2 ENTÃO
stConten t = Trim ( a_stPart ( 0 ))
IF UBound ( a_stPart ())> 0 ENTÃO
stContentField2 = Trim ( a_stPart ( 1 ))
OUTRO
stContentField2 = ""
FIM SE
stContentField2 = Trim ( a_stPart ( 1 ))
OUTRO
stContentField2 = Trim ( a_stPart ( 0 ))
IF UBound ( a_stPart ())> 0 ENTÃO
stContent = Trim ( a_stPart ( 1 ))
OUTRO
stContent = ""
FIM SE
stContent = Trim ( a_stPart ( 1 ))
END IF
END IF
Pode acontecer que, com dois conteúdos separáveis, o tamanho instalado da caixa de combinação
(comprimento do texto) não se encaixe nos campos da tabela a serem salvos. Para caixas de combinação
que representam um único campo, isso normalmente é tratado pela configuração adequada do controle de
formulário. Aqui, ao contrário, precisamos de algum meio de detectar esses erros. O comprimento máximo
permitido do campo relevante é verificado.
IF (Field1Length > 0 E Len (stContent) > Field1Length ) OU (Field2Length > 0
AND Len (stContentField2) > Field2Length ) ENTÃO
Se o tamanho do campo da primeira ou da segunda parte for muito grande, uma string padrão será
armazenada em uma das variáveis. O caractere CHR (13) é usado para colocar uma quebra de linha.
stmsgbox1 = "O campo" + NameTableField1 + " não deve exceder" +
Field1Length + "caracteres de comprimento." + CHR ( 13 )
stmsgbox2 = "O campo" + NameTableField2 + "não deve exceder" +
Field2Length + "caracteres de comprimento." + CHR ( 13 )
Se o conteúdo de ambos os campos for muito longo, os dois textos serão exibidos.
IF ( Field1Length > 0 E Len ( stContent ) > Field1Length ) E (
ComprimentoCampo2 > 0 E Len ( stContentField2 ) > ComprimentoCampo2 ) ENTÃO
msgbox ( "O texto digitado é muito longo." + CHR ( 13 ) +
stmsgbox1 + stmsgbox2 + "Por favor, encurte-o." , 64 , "Entrada inválida" )
O display usa a função msgbox () . Isso espera como primeiro argumento uma sequência de texto,
depois, opcionalmente, um número (que determina o tipo de caixa de mensagem exibida) e, finalmente,
uma sequência de texto opcional como um título para a janela. A janela terá, portanto, o título "Entrada
inválida" e o número "64" fornece uma caixa contendo o símbolo Informações.
O código a seguir cobre qualquer caso adicional de texto excessivamente longo que possa surgir.
ELSEIF ( Campo1Comprimento > 0 E Len ( stContent )> Fi eld1Length )
ENTÃO
msgbox ( "O texto digitado é muito longo." + CHR ( 13 ) +
stmsgbox1 + "Por favor, encurte-o." , 64 , "Entrada inválida" )
OUTRO
msgbox ( "O texto digitado é muito longo." + CHR ( 13 ) +
stmsgbox2 + "Por favor, encurte-o." , 64 , "Entrada inválida" )
END IF
OUTRO
Se não houver texto excessivamente longo, a função pode prosseguir. Caso contrário, sai aqui.
As primeiras variáveis são pré-alocadas, as quais podem ser subsequentemente alteradas pela consulta.
As variáveis inID1 e inID2 armazenam o conteúdo dos campos de chave primária das duas tabelas. Se
uma consulta não gerar resultados, Basic atribui a essa variável inteira um valor de 0. No entanto, esse
valor também pode indicar uma consulta bem-sucedida retornando um valor de chave primária de 0;
portanto, a variável é pré-configurada para -1. O HSQLDB não pode definir este valor para um campo de
autovalor.
Em seguida, a conexão com o banco de dados é configurada, se ainda não existir.
inID1 = -1
inID2 = -1
oDataSource = ThisComponent.Parent.CurrentController
Se NÃO ( oDataSource.isConnected ()) então
oDataSource.connect ()
End If
oConnection = oDataSource.ActiveConnection ()
oSQL_Statement = oConnection.createStatement ()
IF NameTableField2 <> "" E NÃO IsEmpty ( stContentField2 ) E
NameTable2 <> "" ENTÃO
Se existir um segundo campo de tabela, uma segunda dependência deve primeiro ser declarada.
stSql = "SELECT" "ID" "FROM" "" + NameTable2 + "" "WHERE" ""
+ NameTableField2 + "" "= '" + stContentField2 + "'"
oQuery_result = oSQL_Statement .executeQuery ( stSql )
IF NOT IsNull ( oQuery_result ) ENTÃO
QUANDO oQuery_result.next
inID2 = oQuery_result.getInt ( 1 )
WEND
END IF
IF inID2 = -1 DEPOIS
stSql = "INSERT INTO" "" + NameTable2 + "" "(" "" +
NameTableField2 + "" ") VALUES ('" + stContentField2 + "')"
oSQL_Statement.executeUpdate ( stSql )
stSql = "IDENTIDADE DE CHAMADA ()"
Se o conteúdo dentro da combobox não estiver presente na tabela correspondente, ele será inserido lá. O
valor da chave primária resultante é então lido. Se estiver presente, a chave primária existente é lida da
mesma maneira. A função usa os campos de chave primária gerados automaticamente ( IDENTITY ).
oQuery_result = oSQL_Statement.executeQuery ( stSql
)
IF NOT IsNull ( oQuery_result ) ENTÃO
QUANDO oQuery_result.next
inID2 = oQuery_result.getInt ( 1 )
WEND
END IF
END IF
A chave primária para o segundo valor é armazenada temporariamente na variável inID2 e depois
gravada como uma chave estrangeira na tabela correspondente ao primeiro valor. De acordo com a
disponibilidade do registro da primeira tabela, o conteúdo é salvo recentemente ( INSERT ) ou alterado (
UPDATE ):
IF inID1 = -1 DEPOIS
stSql = "INSERT INTO" "" + NameTable1 + "" "(" "" +
NameTableField1 + "" "," "" + NameTab12ID + "" ") VALORES ('" + stContent + "', '" +
inID2 + "')"
oSQL_Statement.executeUpdate ( stSql )
E o ID correspondente lido diretamente:
stSql = "IDENTIDADE DE CHAMADA ()"
oQuery_result = oSQL_Statement.executeQuery ( stSql
)
IF NOT IsNull ( oQuery_result ) ENTÃO
QUANDO oQuery_result.next
inID1 = oQuery_result.getInt ( 1 )
WEND
END IF
A chave primária da primeira tabela deve finalmente ser lida novamente para que possa ser transferida para
a tabela subjacente do formulário.
OUTRO
stSql = "ACTUALIZAÇÃO """ + NameTable1 + "" "SET """
+ NameTab12ID + "" "= '" + inID2 + "' ONDE """ + NameTableField1 + """= '" +
stContent + "'"
oSQL_Statement.executeUpdate ( stSql )
END IF
END IF
No caso em que ambos os campos subjacentes à caixa de combinação estão na mesma tabela (por
exemplo, Sobrenome e Nome na tabela Nome), é necessária uma consulta diferente:
IF NameTableField2 <> "" AND NameTable2 = "" ENTÃO
stSql = "SELECT" "ID" "FROM" "" + NameTable1 + "" "WHERE" ""
+ NameTableField1 + "" "= '" + stContent + "' AND" "" + NameTableField2 + "" "= '" +
stContentField2 + "'"
oQuery_result = oSQL_Statement.executeQuery ( stSql )
IF NOT IsNull ( oAbfrageergebnis ) ENTÃO
QUANDO oQuery_result.next
inID1 = oQuery_result.getInt ( 1 )
WEND
END IF
IF inID1 = -1 DEPOIS
... e uma segunda tabela não existe:
stSql = " INSERIR EM" "" + NameTable1 + "" "(" "" +
NameTableField1 + "" "," "" + NameTableField2 + "" ") VALUES ('" + stContent + "',
'" + stContentField2 + "')"
oSQL_Statement.executeUpdate ( stSql )
Em seguida, a chave primária é lida novamente.
stSql = "IDENTIDADE DE CHAMADA ()"
oquery_result = oSQL_Statement.executeQuery ( stSql )
IF NOT IsNull ( oQuery_result ) ENTÃO
QUANDO oQuery_result.next
inID1 = oQuery_result.getInt ( 1 )
WEND
END IF
END IF
END IF
IF NameTableField2 = "" ENTÃO
Agora consideramos o caso mais simples: O segundo campo da tabela não existe e a entrada ainda não
está presente na tabela. Em outras palavras, um único novo valor foi inserido na caixa de combinação.
stSql = "SELECT" "ID" "FROM" "" + NameTable1 + "" "WHERE" "" +
NameTableField1 + "" "= '" + stContent + "'"
oQuery_result = oSQL_Statement.executeQuery ( stSql )
IF NOT IsNull ( oQuery_result ) ENTÃO
QUANDO oQuery_result.next
inID1 = oQuery_result.getInt ( 1 )
WEND
END IF
IF inID1 = -1 DEPOIS
Se não houver um segundo campo, o conteúdo da caixa será inserido como um novo registro.
stSql = "INSERIR EM" "" + NameTable1 + "" "(" "" +
NameTableField1 + "" ") VALUES ('" + stContent + "')"
oSQL_Statement.executeUpdate ( stSql )
… E o ID resultante lido diretamente.
stSql = "IDENTIDADE DE CHAMADA ()"
oQuery_result = oSQL_Statement.executeQuery ( stSql )
SE NÃO ISNULL ( oQuery_result ) ENTÃO
QUANDO oQuery_result.next
inID1 = oQuery_result.getInt ( 1 )
WEND
END IF
END IF
END IF
O valor do campo da chave primária deve ser determinado, para que possa ser transferido para a parte
principal do formulário.
Em seguida, o valor da chave primária resultante de todos esses loops é transferido para o campo invisível
na tabela principal e no banco de dados subjacente. O campo de tabela vinculado ao campo de formulário é
atingido usando ' BoundField ' . ' updateInt ' coloca um número inteiro
(veja em definições de tipos numéricos) neste campo.
oField.BoundField.updateInt ( inID )
END IF
OUTRO
Se nenhuma chave primária for inserida, porque não havia entrada na caixa de combinação ou essa
entrada foi excluída, o conteúdo do campo invisível também deve ser excluído. updateNull () é
usado para preencher o campo com a expressão específica do banco de dados para um campo vazio,
NULL .
oField.BoundField.updateNull ()
END IF
END SUB

Função para medir o comprimento da entrada da combobox


A função a seguir fornece o número de caracteres na respectiva coluna da tabela, para que as entradas
que são muito longas não sejam apenas truncadas. Uma FUNÇÃO é escolhida aqui para fornecer
valores de retorno. Um SUB não tem valor de retorno que possa ser passado e processado em outro
lugar.
FUNCTION ColumnSize ( Nome do Tablete AS STRING , Nome do Campo COMO STRING ) COMO
INTEGER
oDataSource = ThisComponent.Parent.CurrentController
Se NÃO ( oDataSource.isConnected ()) então
oDataSource.connect ()
End If
oConnection = oDataSource.ActiveConnection ()
oSQL_Statement = oConnection.createStatement ()
stSql = "SELECT "" COLUMN_SIZE"" de "" INFORMATION_SCHEMA "". ""
SYSTEM_COLUMNS "" onde "" TABLE_NAME ""= ' " + Tablename + "' E "" COLUMN_NAME ""=
'" + Fieldname + "'"
oQuery_result = oSQL_Statement.executeQuery ( stSql )
IF NOT IsNull ( oQuery_result ) ENTÃO
QUANDO oQuery_result.next
i = oQuery_result.getInt ( 1 )
WEND
END IF
Tamanho da coluna = i
FUNÇÃO DE FIM

Chamando a sub - rotina para exibir textos


A sub-rotina para criação da caixa de combinação é chamada toda vez que um registro é alterado. O
exemplo a seguir mostra isso para o banco de dados de amostra .
SUB Form_Reader_Input_Load
REM TextDisplay (NameForm AS STRING, NameSubForm AS STRING, NameSubSubForm
AS STRING, NameField COMO STRING, NameIDField AS STRING, NameTableField1 (da Tabela
1) AS STRING, NameTableField2 (da Tabela 1 ou da Tabela 2) AS STRING, FieldSeparator
AS STRING, NameTable1 AS STRING, OPTIONAL NameTable2 AS STRING, OPCIONAL
NameIDFromTable2InTable1 AS STRING, OPTIONAL Field Position da tabela2 no Combobox
AS INTEGER [1 ou 2])
TextDisplay ( "Filtro" , "Formulário" , "Endereço" , "comStr" , "numStrID" ,
"Rua" , "" , "" , "Rua" )
TextDisplay ( "Filtro" , "Formulário" , "Endereço" , "comPlcTown" ,
"numPlcTownID" , "Código Postal" , "Cidade" , "" , "Código Postal" , "Cidade" ,
"Town_ID" , 2 )
END SUB
As linhas de comentário mostram a lista de parâmetros que precisam ser fornecidos para a sub - rotina .
Um parâmetro vazio é representado por um par de aspas duplas. Os últimos três parâmetros são
opcionais, pois são cobertos, quando necessário, por valores padrão na sub - rotina .
A sub - rotina TextDisplay é chamada. O formulário que contém os campos é Filter >
Form > Address . Estamos, portanto, lidando com o subformulário de um subformulário.

A primeira caixa de combinação, na qual a rua é inserida, é chamada comStr , o campo de chave
estrangeira oculto na tabela subjacente ao formulário é chamado numStrID . Neste primeiro combobox
o campo Rua é exibido. A tabela, que conterá as entradas da caixa de combinação, também é
chamada St reet .
A cidade e o código postal são inseridos na segunda caixa de combinação. Isso é chamado
comPlcTown . O campo de chave estrangeira oculto é chamado numPlcTownID . Esta segunda
caixa de combinação contém o código postal e a cidade , separados por um espaço (
"" ). A primeira tabela tem o nome Postcode , a segunda tabela o nome Town . Na primeira
tabela, a chave estrangeira para a segunda tabela é chamada Town_ID . O campo da segunda tabela
é o segundo elemento da caixa de combinação, que é a posição 2 .

Chamando a sub - rotina para armazenamento de texto


Para armazenar a entrada, usamos a sub - rotina TextChoiceValueSave.
SUB Form_Reader_Output_Save
REM TextChoiceValueSave (NameForm AS STRING, NameSubForm AS STRING,
NameSubSubForm ASString, NameField ASString, NameIDField ASString, NameTableField1
(da Tabela 1) AS STRING, NameTableField2 (da tabela 1 ou tabela 2) AS STRING,
FieldSeparator AS STRING, NameTable1 AS STRING, OPTIONAL NameTable2 AS STRING,
OPCIONAL NameIDFromTable2InTable1 AS STRING, OPTIONAL Posição do campo de Table2 no
Combobox AS INTEGER [1 ou 2])
O comentário é semelhante ao da sub-rotina anterior . As variáveis que estão sendo passadas também são
as mesmas.
TextChoiceValueSave ( "Filtro" , "Formulário" , "Endereço" , "comStr" ,
"numStrID" , "Rua" , "" , "" , "Rua" , "" , "" ))
TextChoiceValueSave ( "Filtro" , "Formulário" , "Endereço" , "comPlcTown" ,
"numPlcTownID" , "Código Postal" , "Cidade" , "" , "Código Postal" , "Cidade" ,
"Town_ID" , 2 )
END SUB
Para armazenar com segurança o valor, o formulário deve ser informado sobre as alterações. Na medida
em que o usuário está preocupado, a alteração ocorre apenas para o texto dentro da caixa de combinação
para o qual o formulário não tem conexão adicional. Em vez disso, é o campo numérico que contém a
chave estrangeira que é o link para o banco de dados. Assim, a chave estrangeira é simplesmente
atribuída ao valor -1, que um campo de autovalor não pode legalmente ter. Isso garante uma mudança no
conteúdo do campo. Esse conteúdo de campo é então copiado pela operação normal da caixa de listagem.
SUB RecordAction_produce ( oEvent COMO OBJECTO )
Essa macro deve ser vinculada ao seguinte evento para a caixa de listagem: 'Em foco'. É necessário que a
operação de salvamento ocorra em todos os casos em que o conteúdo da caixa de listagem é alterado.
Sem essa macro, não haverá alteração na tabela, que o Base possa reconhecer, já que a caixa de
combinação não está vinculada ao formulário.
DIM oForm COMO OBJETO
DIM oSubForm COMO OBJETO
DIM oSubSubForm COMO OBJETO
DIM o campo como objeto
DIM stTag AS String
stTag = oEvent.Source.Model.Tag
aForms () = Dividir ( stTag , "," )
Uma matriz é preenchida ; o nome do campo vem primeiro e, em seguida, os nomes dos formulários, com
o formulário principal precedendo o subformulário.
oDoc = thisComponent
oDrawpage = oDoc.Drawpage
oForm = oDrawpage.Forms.getByName ( aForms ( 1 ))
IF UBound ( aForms ())> 1 ENTÃO
oForm = oForm.getByName ( aForms ( 2 ))
SE UBound ( aForms ())> 2 ENTÃO
oForm = oForm.getByName ( aForms ( 3 ))
END IF
END IF
oField = oForm.getByName ( aForms ( 0 ))
oField.BoundField.updateInt ( -1 )
END SUB

Navegação de um formulário para outro


Um formulário deve ser aberto quando um evento específico ocorre.
Nas propriedades de controle de formulário, na linha "Informações adicionais" (tag), insira o nome do
formulário. Mais informações também podem ser inseridas aqui e, posteriormente, separadas usando a
função Split () .
SUB From_form_to_form ( oEvent como objeto )
DIM stTag AS String
stTag = oEvent.Source.Model.Tag
aForm () = Dividir ( stTag , "," )
A matriz é declarada e preenchida com os nomes dos formulários, primeiro o formulário a ser aberto e, em
segundo lugar, o formulário atual, que será fechado depois que o outro for aberto.
ThisDatabaseDocument.FormDocuments.getByName ( Trim ( aForm ( 0 ))) .abaixo
ThisDatabaseDocument.FormDocuments.getByName ( Trim ( aForm ( 1 ))) .close
END SUB
Se, em vez disso, o outro formulário for aberto apenas quando o atual estiver fechado, por exemplo, onde
existe um formulário principal e todos os outros formulários são controlados usando botões, a macro a
seguir deve ser vinculada ao formulário com Ferramentas > Personalizar > Eventos > Documento
fechado :
SUB Mainform_open
ThisDatabaseDocument.FormDocuments.getByName ( "Mainform" ) .open
END SUB
Se os documentos de formulário são classificados dentro do arquivo ODB em diretórios, a macro para
alterar o formulário precisa ser mais extensa:
SUB From_form_to_form_with_folders ( oEvent como objeto )
REM O formulário a ser aberto é dado primeiro.
REM Se um formulário estiver em uma pasta, use "/" para definir o relacionamento
REM para que a subpasta possa ser encontrada.
STATUS DIM COMO STRING
stTag = oEvent.Source.Model.Tag 'Tag é inserido na informação adicional
aForms () = Split ( stTag , "," ) 'Aqui, o nome do formulário para o novo
formulário vem primeiro, depois o do formulário antigo
aForms1 () = Split ( aForms ( 0 ), "/" )
aForms2 () = Dividir ( aForms ( 1 ), "/" )
IF UBound ( aForms1 ()) = 0 ENTÃO
ThisDatabaseDocument.FormDocuments.getByName ( Trim ( aForms1 ( 0 ))) .open
OUTRO
ThisDatabaseDocument.FormDocuments.getByName ( Trim ( aForms1 ( 0 ))).
getByName ( Trim ( aForms1 ( 1 ))) .abaixo
END IF
IF UBound ( aForms2 ()) = 0 ENTÃO
ThisDatabaseDocument.FormDocuments.getByName ( Trim ( aForms2 ( 0 ))) .close
OUTRO
ThisDatabaseDocument.FormDocuments.getByName ( Trim ( aForms2 ( 0 ))).
getByName ( Trim ( aForms2 ( 1 ))) .close
END IF
END SUB
Os documentos de formulário que estão em um diretório são inseridos no campo Informações Adicionais
como diretório / formulário. Isso deve ser convertido para:
... getByName ("Directory"). getByName ("Form") .

Removendo elementos de distração de formulários


Barras de ferramentas não têm nenhuma função em formulários. Eles são mais propensos a irritar o
usuário normal, pois o formulário não está sendo editado enquanto os dados são inseridos. Essas macros
permitem que as barras de ferramentas sejam removidas e subsequentemente restabelecidas. No entanto,
dependendo da versão do Libre Office, barras de menu em forma de texto só podem ser removidas
temporariamente e reaparecer.
Sub Toolbar_remove
DIM oframe como objeto
DIM oLayoutMng COMO OBJETO
oFrame = thisComponent.CurrentController.Frame
oLayoutMng = oFrame.LayoutManager
oLayoutMng.visible = false
oLayoutMng.showElement ( "private: Resource / menubar / menubar" )
End Sub
Sub Toolbar_restore
DIM oframe como objeto
DIM oLayoutMng COMO OBJETO
oFrame = thisComponent.CurrentController.Frame
oLayoutMng = oFrame.LayoutManager
oLayoutMng.visible = true
End Sub
Quando uma barra de ferramentas é removida, todas as barras são afetadas. No entanto, assim que um
controle de formulário é clicado, a barra de menu reaparece. Esta é uma precaução de segurança para que
o usuário não acabe em um atolamento. Para evitar a alternância constante, a barra de menu reaparece.

Tarefas de banco de dados expandidas usando macros

Fazendo uma conexão com um banco de dados


oDataSource = ThisComponent.Parent.DataSource
IF NOT oDataSource.IsPasswordRequired ENTÃO
oConnection = oDataSource.GetConnection ( "" , "" )
Aqui seria possível fornecer um nome de usuário e uma senha, se necessário. Nesse caso, os colchetes
conteriam ("Nome de usuário", "Senha"). Em vez de incluir o nome de usuário e uma senha em texto não
criptografado, o diálogo para proteção por senha é chamado:
OUTRO
oAuthentication = createUnoService ( "com.sun.star.sdb.InteractionHandler" )
oConnection = oDataSource.ConnectWithCompletion ( oAuthentication )
END IF
Se, no entanto, um formulário dentro do mesmo arquivo Base estiver acessando o banco de dados, você
precisará apenas:
oDataSource = ThisComponent.Parent.CurrentController
IF NOT ( oDataSource.isConnected ()) então
oDataSource.connect ()
Fim se
oConnection = oDataSource.ActiveConnection ()
Aqui o banco de dados é conhecido, portanto, um nome de usuário e uma senha não são necessários, pois
eles já estão desativados na configuração básica do HSQLDB para a versão interna.
Para formulários fora do Base, a conexão é feita através do primeiro formulário:
oDataSource = Thiscomponent.Drawpage.Forms ( 0 )
oConnection = oDataSource.activeConnection

Protegendo seu banco de dados


Às vezes pode acontecer, especialmente quando um banco de dados está sendo criado, que o arquivo
ODB é truncado inesperadamente. A economia freqüente após a edição é, portanto, útil, especialmente ao
usar o módulo Relatórios.
Quando o banco de dados está em uso, ele pode ser danificado pela falha do sistema operacional, se isso
ocorrer apenas quando o arquivo Base estiver sendo finalizado. É quando o conteúdo do banco de dados
está sendo gravado no arquivo.
Além disso, há os suspeitos usuais de arquivos que de repente se recusam a abrir, como falha no disco
rígido. Não faz mal, portanto, ter uma cópia de backup que seja a mais atualizada possível. O estado dos
dados não muda desde que o arquivo ODB permaneça aberto. Por esse motivo, as sub-rotinas de
segurança podem ser diretamente ligadas à abertura do arquivo. Você simplesmente copia o arquivo
usando o caminho de backup fornecido em Ferramentas > Opções > LibreOffice > Caminhos . Esta
macro começa a substituir a versão mais antiga depois de cinco cópias terem sido feitas.
SUB Databasebackup
REM O arquivo de banco de dados * .odb é copiado no diretório Backup.
REM O número máximo de cópias é definido como 5. Depois disso, a cópia mais
antiga é substituída.
REM Este método não cobre:
REM - entrada de dados em um banco de dados que já está aberto, pois os
dados são gravados no arquivo * .odb somente quando ele é fechado.
DIM o caminho como objeto
DIM oDOC COMO OBJETO
DIM sTitle AS STRING
DIM sUrl_end COMO STRING
DIM sUrl_start COMO STRING
DIM i COMO INTEGER
DIM k AS INTEGER
oDoc = ThisComponent
sTitle = oDoc.Title
sUrl_start = oDoc.URL
oPath = createUnoService ( "com.sun.star.util.PathSettings" )
PARA i = 1 TO 6
SE NÃO FileExists ( oPath.Backup & "/" & i & "_" & sTitle ) ENTÃO
SE eu > 5 DEPOIS
PARA k = 1 PARA quatro
IF FileDateTime ( oPath.Backup & "/" & k & "_" & sTitle ) <=
FileDateTime ( oPath.Backup & "/" & k + 1 & "_" & sTitle ) ENTÃO
i = k
SAÍDA PARA
END IF
PRÓXIMO
FIM SE
SAÍDA PARA
FIM SE
PRÓXIMO
sUrl_end = oPath.Backup & "/" & i & "_" & sTitle
FileCopy ( sUrl_start , sUrl_end )
END SUB
Você também pode fazer um backup enquanto o Base estiver em execução, desde que os dados possam
ser gravados de volta do cache no arquivo antes que a sub - rotina Databasebackup seja executada. Pode
ser útil fazer isso, talvez após um tempo decorrido específico ou quando um botão na tela for pressionado.
Essa limpeza de cache é tratada pela seguinte sub - rotina :
SUB Write_data_out_of_cache
REM Grava os dados da tabela diretamente no disco enquanto o Base está em
execução.
DIM oData COMO OBJETO
DIM oDataSource AS OBJECT
oData = ThisDatabaseDocument . CurrentController
SE NÃO ( oData.isConnected ()) ENTÃO oData . conectar ()
oDataSource = oData.DataSource
oDataSource . rubor
END SUB

Compactação de banco de dados


Isso é simplesmente um comando SQL ( SHUTDOWN COMPACT ), que deve ser executado de vez em
quando, especialmente depois que muitos dados foram excluídos. O banco de dados armazena novos
dados, mas ainda reserva o espaço para os dados excluídos. Nos casos em que os dados foram
substancialmente alterados, você precisa compactar o banco de dados.
Depois que a compactação é realizada, as tabelas não estão mais acessíveis. O arquivo deve ser
reaberto. Portanto, essa macro fecha o formulário do qual ela é chamada. Infelizmente você não pode
fechar o documento sem causar uma recuperação quando for aberto novamente. Portanto esta função está
comentada.
SUB Database_compaction
DIM stMessage AS STRING
oDataSource = ThisComponent.Parent.CurrentController 'Acessível a partir do
formulário
IF NOT ( oDataSource.isConnected ()) ENTÃO
oDataSource.connect ()
END IF
oConnection = oDataSource.ActiveConnection ()
oSQL_Statement = oConnection.createStatement ()
stSql = "SHUTDOWN COMPACT" 'O banco de dados está sendo compactado e
encerrado
oSQL_Statement.executeQuery ( stSql )
stMessage = "O banco de dados está sendo compactado." + CHR ( 13 ) + "O
formulário será fechado agora."
stMessage = stMessage + CHR ( 13 ) + "Após isso, o arquivo de banco de dados
deve ser fechado."
stMessage = stMessage + CHR ( 13 ) + "O banco de dados só pode ser acessado
após a reabertura do arquivo de banco de dados."
msgbox stMessage
ThisDatabaseDocument.FormDocuments.getByName ("Maintenance") .close
REM O fechamento do arquivo do banco de dados provoca uma operação de
recuperação quando você o abre novamente.
'ThisDatabaseDocument.close (True)
END SUB

Diminuindo o índice da tabela para campos de autovalor


Se muitos dados forem excluídos de uma tabela, os usuários geralmente se preocupam com o fato de que
a sequência de chaves primárias geradas automaticamente simplesmente continua aumentando, em vez
de recomeçar no valor atual mais alto da chave. A sub-rotina a seguir lê o valor atualmente mais alto do
campo "ID" em uma tabela e define o próximo valor de chave inicial 1 maior que esse máximo.
Se o campo da chave primária não for chamado de ID, a macro deverá ser editada de acordo.
SUB Table_index_down ( stTable AS STRING )
REM Esta sub-rotina define o campo de chave primária de incremento
automático com o nome predefinido de "ID" para o menor valor possível.
DIM inCount AS INTEGER
DIM inSequence_Value AS INTEGER
oDataSource = ThisComponent.Parent.CurrentController 'Acessível através do
formulário
IF NOT ( oDataSource.isConnected ()) ENTÃO
oDataSource.connect ()
FIM SE
oConnection = oDataSource.ActiveConnection ()
oSQL_Statement = oConnection.createStatement ()
stSql = "SELECT MAX (" "ID" ") FROM" "" + stTable + "" "" 'O valor mais alto
em "ID" é determinado
oQuery_result = oSQL_Statement.executeQuery ( stSql ) 'A consulta é
iniciada e o valor de retorno é armazenado na variável oQuery_result
IF NOT ISNULL ( oQuery_result ) ENTÃO
QUANDO oQuery_result.next
inCount = oQuery_result.getInt ( 1 ) 'Primeiro campo de dados
é lido
Próximo registro de WEND , neste caso nenhum, pois existe apenas um
registro
IF inCount = "" THEN 'Se o valor mais alto não for um valor, o que
significa que a tabela está vazia, o maior valor é definido como -1
inCount = -1
FIM SE
inSequence_Value = inCount +1 'O maior valor é aumentado em 1
REM Um novo comando é preparado para o banco de dados. O ID iniciará
novamente a partir de inCount + 1.
REM Esta declaração não tem valor de retorno, já que nenhum registro
está sendo lido
oSQL_statement = oConnection.createStatement ()
oSQL_statement.executeQuery ( "ALTER TABLE" "" + stTable + "" "ALTER
COLUMN" "ID" "REINICIAR COM" + inSequence_Value + "" )
FIM SE
END SUB

Diálogos
Os erros de entrada nos campos geralmente só são percebidos posteriormente. Geralmente, é necessário
modificar entradas idênticas em vários registros ao mesmo tempo. É desajeitado ter que fazer isso na
visualização de tabela normal, especialmente quando vários registros devem ser editados, já que cada
registro requer que uma entrada individual seja feita.
Formulários podem usar macros para fazer esse tipo de coisa, mas para fazer isso em várias tabelas,
você precisaria de formulários construídos de forma idêntica. Diálogos podem fazer o trabalho. Um diálogo
pode ser fornecido no início com os dados necessários para tabelas apropriadas e pode ser chamado por
várias formas diferentes.

As caixas de diálogo são salvas junto com os módulos para macros. Sua criação é semelhante à de uma
forma. Campos de controle muito semelhantes estão disponíveis. Apenas o controle de tabela de
formulários está ausente como uma possibilidade especial de entrada.

A aparência dos controles de diálogo é determinada pelas configurações da interface gráfica do usuário.
A caixa de diálogo mostrada acima serve no banco de dados de exemplo para editar tabelas que não são
usadas diretamente como a base de um formulário. Assim, por exemplo, o tipo de mídia é acessível
apenas por meio de uma caixa de listagem (na versão de macro, ela se torna uma caixa de combinação).
Na versão macro, o conteúdo do campo pode ser expandida por ne w conteúdo, mas uma alteração do
conteúdo existente não é possível. Na versão sem macros, as alterações são realizadas usando um
controle de tabela separado.
Embora as alterações neste caso sejam fáceis de executar sem macros, é muito difícil alterar o tipo de
mídia de várias mídias de uma só vez. Suponha que os seguintes tipos estão disponíveis: "Book,
obrigado", "Book, capa dura", "Paperback" um nd "Ringfile". Agora, depois que o banco de dados está em
uso há muito tempo, os contemporâneos mais ativos previram tipos de mídia adicionais semelhantes para
trabalhos impressos. A tarefa de diferenciá-los tornou-se excessiva. Queremos, portanto, reduzi-los, de
preferência a um único termo. Sem macros, os registros dotabela de mídia teria que ser encontrada
(usando um filtro) e alterada individualmente. Se você conhece SQL, pode fazê-lo muito melhor usando um
comando SQL. Você pode alterar todos os registros na tabela Mídia com uma única entrada. Um segundo
comando SQL remove os tipos de mídia agora excedentes que não têm mais nenhum link para a tabela
Mídia. Precisamente este método é aplicado usando Substituir deste diálogo W caixa om - apenas o
comando SQL é primeiro adaptado à mídia T mesa ipo usando uma macro que também pode editar outras
tabelas.
Muitas vezes, as entradas aparecem em uma tabela que, em retrospectiva, pode ser alterada na forma e,
portanto, não são mais necessárias. Não faz mal simplesmente excluir tais entradas órfãs, mas elas são
muito difíceis de encontrar usando a interface gráfica do usuário. Aqui, novamente, um comando SQL
adequado é útil, juntamente com uma instrução de exclusão. Este comando para tabelas afetadas é
incluído na caixa de diálogo em Excluir todas as entradas supérfluas .
Se a caixa de diálogo for usada para realizar várias alterações, isso é indicado pela caixa de seleção Editar
vários registros . Então a caixa de diálogo não terminará simplesmente quando o botão OK for clicado.
O código de macro para este diálogo pode ser visto integralmente no banco de dados de exemplo. Apenas
trechos são explicados abaixo.
SUB Table_purge ( oEvent AS OBJECT )
A macro deve ser lançada entrando na seção Informações adicionais para os botões relevantes:
0: Form, 1: Subformulário, 2: SubSubform, 3: Combobox ou controle de tabela, 4:
Campo de chave estrangeira em um formulário, vazio para um controle de tabela, 5:
Nome da tabela da tabela auxiliar, 6: Table field1 of table auxiliar, 7: Tabela
campo2 da tabela auxiliar ou 8: Nome da tabela da tabela auxiliar para a tabela
campo2
As entradas nesta área são listadas no início da macro como comentários. Os números ligados a eles são
transferidos e a entrada relevante é lida de uma matriz. A macro pode editar listboxes, que possuem duas
entradas, separadas por ">" . Essas duas entradas também podem vir de diferentes tabelas e serem
reunidas usando uma consulta, como por exemplo na tabela Código postal, que possui apenas o campo de
chave estrangeira Town_ID para a cidade, exigindo que a tabela Town exiba os nomes das cidades.
DIM aForeignTable ( 0 , 0 a 1 )
DIM aForeignTable2 ( 0 , 0 a 1 )
Entre as variáveis definidas no início, estão duas matrizes. Enquanto matrizes normais pode ser criado
pelo Split () de comando durante a execução do sub-rotina , as matrizes bidimensionais m u r ser
definidos previamente. Arrays bidimensionais são necessários para armazenar vários registros de uma
consulta quando a própria consulta se refere a mais de um campo. Os dois arrays declarados acima
devem ser capazes de interpretar consultas que se referem a dois campos de tabela. Portanto, eles são
definidos para dois conteúdos diferentes usando 0 a 1 para a segunda dimensão.
stTag = oEvent.Source.Model.Tag
aTable () = Dividir ( stTag , "," )
PARA i = LBound ( aTabela ()) PARA UBound ( aTabela ())
tabela (i) = trim ( tabela ( i ))
PRÓXIMO
As variáveis fornecidas são lidas. A sequência é aquela configurada no comentário acima. Há um máximo
de nove entradas, e você precisa declarar se um eigh th entrada para o field2 mesa e uma de nove entrada
th f o r uma segunda tabela existe.
Se os valores devem ser removidos de uma tabela, é necessário primeiro verificar se eles não existem
como chaves estrangeiras em alguma outra tabela. Em estruturas de tabela simples, uma determinada
tabela terá apenas uma conexão de chave estrangeira para outra tabela. No entanto, no banco de dados de
exemplo fornecido, há uma tabela Town que é usada para o local de publicação da mídia e a cidade para os
endereços. Assim, a chave primária da tabela Town é inserida duas vezes em tabelas diferentes. Estas
tabelas e nomes de chave estrangeira pode, naturalmente, também ser inserido usando Adicional I
nformação campo. Seria melhor se pudessem ser fornecidos universalmente para todos os casos. Isso
pode ser feito usando a seguinte consulta.
stSql = "SELECT" "FKTABLE_NAME" "," "FKCOLUMN_NAME" "FROM"
"INFORMATION_SCHEMA" "." "SYSTEM_CROSSREFERENCE" "ONDE" "PKTABLE_NAME" "= '" +
aTable (5) + "'"
No banco de dados, a área INFORMATION_SCHEMA contém todas as informações sobre as tabelas do
banco de dados, incluindo informações sobre chaves estrangeiras. As tabelas que contêm esta informação
podem ser acessadas usando "INFORMATION_SCHEMA". "SYSTEM_CROSSREFERENCE".
KTABLE_NAME "fornece a tabela que fornece sua chave primária para a conexão. FKTABLE_NAME
fornece a tabela que usa essa chave primária como uma chave estrangeira. Por fim, FKCOLUMN_NAME
informa o nome do campo da chave estrangeira.
A tabela que fornece sua chave primária para uso como uma chave estrangeira está na matriz criada
anteriormente na posição 6. A contagem começa com 0, o valor é lido da matriz usando aTable (5)
.
inCount = 0
stForeignIDTab1Tab2 = "ID"
stForeignIDTab2Tab1 = "ID"
stAuxiltable = aTabela (5)
Antes da leitura dos arrays começar, alguns valores padrão devem ser definidos. Estes são o índice para o
array no qual os valores da tabela auxiliar serão gravados, a chave primária padrão se não precisarmos da
chave estrangeira para uma segunda tabela e a tabela auxiliar padrão, vinculada à tabela principal, para o
código postal e cidade, a tabela de código postal.
Quando dois campos são vinculados para exibição em uma caixa de listagem, eles podem, conforme
descrito acima, vir de duas tabelas diferentes. Para a exibição de CEP e cidade, a consulta é:
SELECIONAR "Código postal". "Código postal" || '>' || "Town". "Town" FROM "CEP", "Town" ONDE
"Postcode". "Town_ID" = "Cidade". "ID"
A tabela do primeiro campo (CEP) está vinculada à segunda tabela por uma chave estrangeira. Somente
as informações dessas duas tabelas e os campos Código postal e Cidade são passados para a macro.
Todas as chaves primárias são, por padrão, chamadas de ID no banco de dados de exemplo. Portanto, a
chave estrangeira de Town in Postcode deve ser determinada usando a macro.
Da mesma forma, a macro deve acessar cada tabela com a qual o conteúdo da caixa de listagem é
conectado por uma chave estrangeira.
oQuery_result = oSQL_Statement.executeQuery ( stSql )
IF NOT ISNULL ( oQuery_result ) ENTÃO
QUANDO oQuery_result. Próximo
ReDim Preserve aForeignTable ( inCount , 0 a 1 )
A matriz deve ser recém dimensionada a cada vez. Para preservar o conteúdo existente, o backup é feito
usando (Preservar).
aForeignTables ( inCount , 0 ) = oQuery_result.getString ( 1
)
Lendo o primeiro campo com o nome da tabela que contém a chave estrangeira. O resultado para a tabela
Código Postal i s tabela de endereços.
aForeignTables ( inCount , 1 ) = oQuery_result.getString ( 2
)
Lendo o segundo campo com o nome do campo de chave estrangeira. O resultado da tabela Postcode é o
campo Postcode _ ID na tabela Address.
Nos casos em que uma chamada para a sub - rotina inclui o nome de uma segunda tabela, o loop a seguir
é executado. Somente quando o nome da segunda tabela ocorre como a tabela de chave estrangeira para
a primeira tabela é a entrada padrão alterada. Em nosso caso, isso não ocorre, pois a tabela Town não
possui chave estrangeira na tabela Postcode. A entrada padrão para a tabela auxiliar, portanto, permanece
como CEP; finalmente, a combinação de código postal e cidade é uma base para a tabela Endereço, que
contém uma chave estrangeira da tabela Código postal.
SE UBound ( aTable ()) = 8 ENTÃO
SE (a ) Tabela ( 8 ) = aForeignTable ( inCount , 0 )
ENTÃO
stForeignIDTab2Tab1 = aForeignTable (
inCount , 1 )
stAuxiltable = aTabela ( 8 )
FIM SE
FIM SE
inCount = inCount + 1
Como valores adicionais podem precisar ser lidos, o índice é incrementado para redimensionar as
matrizes. Então o loop termina.
WEND
FIM SE
Se, quando a sub - rotina for chamada, existir um segundo nome de tabela, a mesma consulta será iniciada
para esta tabela:
SE UBound ( aTable ()) = 8 ENTÃO
Ele é executado de forma idêntica, exceto que o loop testa se talvez o primeiro nome da tabela ocorre
como um nome de tabela de chave estrangeira. Esse é o caso aqui: a tabela Código Postal c ontains o f
Cidade chave oreign _ ID da tabela Town. Esta chave estrangeira é agora atribuída à variável
stForeignIDTab1Tab2, para que a relação entre as tabelas possa ser definida.
SE aTabela ( 5 ) = aForeignTable2 ( inCount , 0 )
THEN
stForeignIDTab1Tab2 = aForeignTable2 (
inCount , 1 )
END IF
Depois de algumas configurações adicionais para garantir um retorno ao formulário correto depois de
executar o diálogo (determinando o número da linha do formulário, para que possamos retornar ao número
da linha após uma nova leitura), o loop começa, o que recria o diálogo quando a primeira ação é concluída,
mas é necessário que o diálogo seja mantido aberto para outras ações. A configuração para repetição
ocorre usando a caixa de seleção correspondente
FAZ
Antes de o diálogo ser iniciado, o conteúdo das caixas de listagem é determinado primeiro. Deve-se tomar
cuidado se as caixas de listagem representam dois campos de tabela e talvez estejam relacionadas a duas
tabelas diferentes.
SE UBound ( tabela ()) = 6 ENTÃO
A caixa de listagem está relacionada a apenas uma tabela e um campo, conforme a matriz de argumentos
termina em Tablefield1 da tabela auxiliar.
stSql = "SELECT """ + aTabela ( 6 ) + "" "de """ + aTabela (
5 ) + "" "PEDIDO PELO """ + aTabela ( 6 ) + "" ""
ELSEIF UBound ( Tabela ()) = 7 ENTÃO
A caixa de listagem está relacionada a dois campos de tabela, mas apenas a uma tabela, conforme a
matriz de argumentos termina em Tablefield2 da tabela auxiliar.
stSql = "SELECT """ + aTabela ( 6 ) + "" "||' > '|| "" " +
aTable ( 7 ) + " "" FROM "" " + aTable ( 5 ) + " "" ORDER BY "" " + aTable ( 6 ) + "
"" "
OUTRO
A caixa de listagem é baseada em dois campos de tabela de duas tabelas. Esta consulta corresponde ao
exemplo com o código postal e a cidade.
stSql = "SELECT" "" + aTable ( 5 ) + "" "." "" + aTable ( 6
) + "" "|| ' > '|| "" " + aTabela ( 8 ) + """. "" " + ATabela ( 7 ) + """ de "" " +
aTabela ( 5 ) + """, """ + aTabela ( 8 ) + "" "ONDE" """" "=" "" + aTable ( 5 ) + ""
"." "" + stForeignIDTab1Tab2 + "" "ORDER BY" "" + aTable ( 6 ) + "" ""
FIM SE
Aqui temos a primeira avaliação para determinar as chaves estrangeiras. As variáveis
stForeignIDTab2Tab1 e stForeignIDTab1Tab2 começam com o valor ID. Para stForeignIDTab1Tab2, a
avaliação da consulta anterior produz um valor diferente, ou seja, o valor de To wn _ ID. Desta forma, a
construção da consulta anterior produz exatamente o conteúdo já formulado para código postal e cidade -
apenas aprimorado pela classificação.
Agora precisamos entrar em contato com as caixas de listagem para fornecer o conteúdo retornado pelas
consultas. Essas caixas de listagem ainda não existem, pois o diálogo em si ainda não foi criado. Essa
caixa de diálogo é criada primeiro na memória, usando as linhas a seguir, antes de ser realmente
desenhada na tela.
DialogLibraries.LoadLibrary ( "Standard" )
oDlg = CreateUnoDialog ( DialogLibraries.Standard.Dialog_Table_purge
)
Em seguida vêm as configurações para os campos da caixa de diálogo. Aqui, por exemplo, é a caixa de
listagem que deve ser fornecida com os resultados da consulta acima:
oCtlList1 = oDlg.GetControl ( "ListBox1" )
oCtlList1.addItems ( aContent (), 0 )
O acesso aos campos da caixa de diálogo é realizado usando GetControl com o nome apropriado.
Nas caixas de diálogo, não é possível que dois campos usem o mesmo nome, pois isso criaria problemas
ao avaliar a caixa de diálogo.
A caixa de listagem é fornecida com o conteúdo da consulta, que foi armazenado no array aContent (). A
caixa de listagem contém apenas o conteúdo a ser exibido como um campo, portanto, somente a posição 0
é preenchida.
Depois que todos os campos com o conteúdo desejado tiverem sido preenchidos, o diálogo será iniciado.
Selecione o caso oDlg.Execute ()
Caso 1 'Caso 1 significa que o botão "OK" foi clicado
Caso 0 'Se fosse o botão "Cancelar"
inRepetition = 0
Selecionar final
LOOP WHILE inRepetition = 1
A caixa de diálogo é executada repetidamente desde que o valor de "inRepetition" seja 1. Isso é definido
pela caixa de seleção correspondente.
Aqui, em resumo, é o conteúdo depois que o botão "OK" é clicado:
Caso 1
stInhalt1 = oCtlList1.getSelectedItem () 'Ler valor de Listbox1 ...
REM ... e determine o valor de ID correspondente.
O valor de ID da primeira caixa de listagem é armazenado na variável "inLB1".
stText = oCtlText.Text 'Leia o valor do campo.
Se o campo de texto não estiver vazio, a entrada no campo de texto será tratada. Nem a caixa de listagem
para um valor de substituição nem a caixa de seleção para excluir todos os registros órfãos são
consideradas. Isso fica claro pelo fato de que a entrada de texto define esses outros campos como
inativos.
SE stText <> "" ENTÃO
Se o campo de texto não estiver vazio, o novo valor será gravado no lugar do antigo, usando o campo de
ID lido anteriormente na tabela. Existe a possibilidade de duas entradas, como também é o caso na caixa
de listagem. O separador é > . Para duas entradas em tabelas diferentes, dois comandos UPDATE devem
ser iniciados, que são criados aqui simultaneamente e encaminhados, separados por um ponto-e-vírgula.
ELSEIF oCtlList2.getSelectedItem () <> "" ENTÃO
Se o campo de texto estiver vazio e a caixa de listagem 2 contiver um valor, o valor da caixa de listagem 1
deverá ser substituído pelo valor da caixa de listagem 2. Isso significa que todos os registros nas tabelas
para os quais os registros nas caixas de listagem são chaves estrangeiras devem ser verificados e, se
necessário, escrito com uma chave estrangeira alterada.
stInhalt2 = oCtlList2.getSelectedItem ()
Valor de leitura REM da caixa de listagem.
REM Determine o ID do valor da caixa de listagem.
O valor de ID da segunda caixa de listagem é armazenado na variável inLB2. Aqui também, as coisas se
desenvolvem diferentemente dependendo se um ou dois campos estão contidos na caixa de listagem, e
também se uma ou duas tabelas são a base do conteúdo da caixa de listagem.
O processo de substituição depende de qual tabela é definida como a tabela que fornece a chave
estrangeira para a tabela principal. Para o exemplo obove, esta é a tabela Postcode, já que o Postcode_ID
é a chave estrangeira que é encaminhada através do Listbox 1 e do Listbox 2.
IF ESTAMULÁVEL = ATADO ( 5 ) ENTÃO
PARA i = LBound ( aForeignTables ()) PARA UBound ( aForeignTables
())
Substituir o antigo valor de ID pelo novo valor de ID torna-se problemático em relacionamentos n: m, já que
nesses casos, o mesmo valor pode ser atribuído duas vezes. Isso pode ser o que você deseja, mas deve
ser evitado quando a chave estrangeira faz parte da chave primária. Portanto, na tabela rel _ Media _
Author, um meio não pode ter o mesmo autor duas vezes, porque a chave primária é construída a partir de
Media _ ID e Author _ ID. Na consulta, são pesquisados todos os campos-chave que, coletivamente, têm a
propriedade UNIQUE ou foram definidos como chaves estrangeiras com a propriedade UNIQUE usando
um índice.
Então, se a chave estrangeira tem a propriedade única e i s já representava lá com o futuro desejado inLB2,
essa chave não pode ser substituído.
stSql = "SELECT" "COLUMN_NAME" "FROM" "INFORMATION_SCHEMA" "." "SYSTEM_INDEXINFO"
"WHERE" "TABLE_NAME" "= '" + aForeignTables ( i , 0 ) + "' AND" "NON_UNIQUE" "=
Falso AND" "INDEX_NAME" "= (SELECT" "INDEX_NAME" "FROM" "INFORMATION_SCHEMA" "."
"SYSTEM_INDEXINFO" "WHERE" "TABLE_NAME" "= '" + aForeignTables ( i , 0 ) + "' AND"
"COLUMN_NAME" "= '"+ aForeignTables ( i , 1 ) + "')"
' "NON_UNIQUE" = False ' fornece os nomes das colunas que são UNIQUE. No entanto,
nem todos os nomes de colunas são necessários, mas apenas aqueles que formam um índice com o
campo de chave estrangeira. Isso é tratado pelo Subselect com os mesmos nomes de tabela (que contêm
a chave estrangeira) e os nomes dos campos de chave estrangeira.
Se agora a chave estrangeira estiver presente no conjunto, o valor da chave só poderá ser substituído se
outros campos forem usados para definir o índice correspondente como UNIQUE. Você deve tomar
cuidado ao realizar substituições que a exclusividade da combinação de índice não seja comprometida.
IF aForeignTables ( i , 1 ) = stFieldname ENTÃO
inUnique = 1
OUTRO
ReDim Preserve aColumns ( inCount )
aColumns ( inCount ) = oQuery_result.getString ( 1 )
inCount = inCount + 1
END IF
Todos os nomes de coluna, além dos nomes de coluna conhecidos para campos de chave estrangeira
como Índice com a propriedade UNIQUE, são armazenados na matriz. Como o nome da coluna do campo
de chave estrangeira também pertence ao grupo, ele pode ser usado para determinar se a exclusividade
deve ser verificada durante a modificação de dados.
SE inUnique = 1 ENTÃO
stSql = "UPDATE" "" + aForeignTables ( i , 0 ) + "" "AS" "a" "SET" "" +
aForeignTables ( i , 1 ) + "" "= '" + inLB2 + "' WHERE" " " + aForeignTables ( i , 1
) + " "" '' ' + inLB1 + ' 'E (SELECT COUNT (*) FROM "" " + aForeignTables ( i ,0 ) +
"" "ONDE" "" + aForeignTables (i,1 ) + "" "= '" + inLB2 + "')"
IF inCount > 0 ENTÃO
stFieldgroup = Join ( aColumns (), "" "|| ||" "" )
Se houver vários campos, além do campo de chave estrangeira, que juntos formam um índice 'UNIQUE',
eles são combinados aqui para um agrupamento de SQL. Caso contrário, apenas "aColumns (0)" aparece
como "stFieldgroup".
stFieldname = ""
PARA tinta = LBound ( aColumns ()) PARA LimiteSup ( aColumns ())
stFieldname = stFieldname + "E """ + aColumns ( tinta ) + ""
"= "" a "". """ + aColumns ( tinta ) + """"
As partes SQL são combinadas para uma subconsulta correlacionada.
PRÓXIMO
stSql = Esquerda ( stSql , Len ( stSql ) - 1 )
A consulta anterior termina com um colchete. Agora, mais conteúdo deve ser adicionado à subconsulta,
portanto, esse fechamento deve ser removido novamente. Depois disso, a consulta é expandida com as
condições adicionais.
stSql = stSql + stFeldbezeichnung + "GROUP BY (" "" + stFeldgruppe + "" ")) <1"
FIM SE
Se a chave estrangeira não tiver conexão com a chave primária ou com um índice UNIQUE, não importa
se o conteúdo é duplicado.
OUTRO
stSql = "UPDATE" "" + aForeignTables ( i , 0 ) + "" "SET" "" +
aForeignTables ( i , 1 ) + "" "= '" + inLB2 + "' ONDE" "" + aForeignTables ( i , 1 )
+ "" "= '" + inLB1 + "'"
FIM SE
oSQL_Statement.executeQuery ( stSql )
PRÓXIMO
A atualização é realizada enquanto existirem conexões diferentes com outras tabelas; isto é, desde que a
tabela atual seja a origem de uma chave estrangeira em outra tabela. Esse é o caso duas vezes para a
tabela Town: na tabela Mídia e na tabela Código postal.
Posteriormente, o valor antigo pode ser excluído da caixa de listagem 1, já que não tem mais nenhuma
conexão com outras tabelas.
stSql = "DELETE FROM" "" + aTable ( 5 ) + "" "WHERE" "ID" "= '" + inLB1 + "'"
oSQL_Statement.executeQuery ( stSql )
Em alguns casos, o mesmo método agora deve ser executado para uma segunda tabela que forneceu
dados para as caixas de listagem. Em nosso exemplo, a primeira tabela é a tabela Código postal e a
segunda é a tabela Cidade.
Se o campo de texto estiver vazio e a caixa de listagem 2 também não contiver nada, verificaremos se a
caixa de seleção relevante indica que todas as entradas excedentes devem ser excluídas. Isso significa as
entradas que não estão vinculadas a outras tabelas por uma chave estrangeira.
ELSEIF oCtlCheck1 . Estado = 1 ENTÃO
stCondition = ""
IF ESTAMULÁVEL = ATADO ( 5 ) ENTÃO
PARA i = LBound ( aForeignTables ()) PARA UBound ( aForeignTables
())
stCondition = stCondition + "" "ID" "NOT IN (SELECT" "" +
aForeignTables ( i , 1 ) + "" "FROM" "" + aForeignTables ( i , 0 ) + "" ") E"
PRÓXIMO
OUTRO
PARA i = LBound ( aForeignTables2 ()) PARA UBound ( aForeignTables2
())
stCondition = stCondition + "" "ID" "NOT IN (SELECT" "" +
aForeignTables2 ( i , 1 ) + "" "FROM" "" + aForeignTables2 ( i , 0 ) + "" ") AND"
PRÓXIMO
END IF
A última e devem ser removidos, pois caso contrário a instrução de exclusão acabaria w om E.
stCondition = Esquerda ( stCondition , Len ( stCondition ) - 4 ) '
stSql = "DELETE FROM" "" + stAuxilTable + "" "WHERE" + stCondition + ""
oSQL_Statement.executeQuery ( stSql )
Como a tabela já foi purgada uma vez, o índice da tabela pode ser verificado e, opcionalmente, corrigido
para baixo. Veja a sub - rotina descrita em uma das seções anteriores .
Table_index_down ( stAuxilTable )
Posteriormente, se necessário, a caixa de listagem no formulário do qual a caixa de diálogo Table_purge foi
chamada pode ser atualizada. Em alguns casos, todo o formulário precisa ser relido. Para esse propósito, o
registro atual é determinado no início da sub - rotina para que, após a atualização do formulário, o registro
atual possa ser restabelecido.
oDlg.endExecute () 'Finalizar diálogo ...
oDlg.Dispose () '... e remova do armazenamento
END SUB
As caixas de diálogo são finalizadas com o comando endExecute () e completamente removidas da
memória com Dispose ().

Capítulo 10 Manutenção do banco


de dados
Comentários gerais sobre manutenção de bancos de dados
A alteração freqüente dos dados em um banco de dados, em particular muitas exclusões, tem dois efeitos.
Primeiro, o banco de dados cresce de forma constante, embora na verdade não contenha mais dados. Em
segundo lugar, a chave primária criada automaticamente continua aumentando independentemente de qual
valor da próxima chave é realmente necessário. Manutenção importante é descrita neste capítulo.

Compactando um banco de dados


O comportamento do HSQLDB é preservar o espaço de armazenamento dos registros excluídos. Bancos
de dados que são preenchidos com dados de teste, especialmente se isso incluir imagens, mantêm o
mesmo tamanho, mesmo se todos esses registros forem excluídos posteriormente.
Para liberar esse espaço de armazenamento, os registros do banco de dados devem ser reescritos
(tabelas, descrições de tabela, etc).
Na interface Base principal, usando Ferramentas > SQL , você pode inserir diretamente um comando
simples (que nos bancos de dados do servidor está disponível apenas para o administrador do sistema):
SHUTDOWN COMPACT
O banco de dados é desativado e liberado de todo o espaço desperdiçado acumulado . Depois disso, o
Base deve ser reiniciado para acessar o banco de dados.

Repor autovalores
Um banco de dados é criado, todas as funções possíveis testadas com exemplos e correções feitas até
que tudo funcione. A essa altura, em média, muitos valores de chave primária terão aumentado para mais
de 100. Má sorte se a chave primária tiver sido configurada para incremento automático, como é comum!
Se as tabelas forem esvaziadas em preparação para uso normal ou antes de entregar o banco de dados
para outra pessoa, a chave primária continuará a incrementar a partir de sua posição atual em vez de se
redefinir para zero.
O seguinte comando SQL, novamente inserido usando Ferramentas > SQL , permite redefinir o valor
inicial:
ALTER TABLE "Table_name" ALTER COLUMN "ID" RESTART WITH 'Novo valor'
Isso pressupõe que o campo da chave primária tenha o nome "ID" e tenha sido definido como um campo
de autovalor. O novo valor deve ser aquele que você deseja criar automaticamente para o próximo novo
registro. Portanto, por exemplo, se os registros atuais forem até 4, o novo valor deverá ser 5.

Consultando as propriedades do banco de dados


Todas as informações nas tabelas do banco de dados são armazenadas em forma de tabela em uma parte
separada do HSQLDB. Esta área separada pode ser alcançada usando o nome
"INFORMATION_SCHEMA".
A consulta a seguir pode ser usada para descobrir nomes de campo, tipos de campo, tamanhos de coluna
e valores padrão. Aqui um exemplo é dado para uma tabela denominada Searchtable.
SELECIONE "COLUMN_NAME", "TYPE_NAME", "COLUMN_SIZE", "COLUMN_DEF" COMO "Valor
padrão" DE "INFORMATION_SCHEMA". "SYSTEM_COLUMNS" ONDE "TABLE_NAME" = 'Tabela de
pesquisa' ORDER BY "ORDINAL_POSITION"
Todas as tabelas especiais no HSQLDB estão descritas no apêndice deste manual. Informações sobre o
conteúdo dessas tabelas são mais facilmente obtidas por consultas diretas:
SELECT * FROM "INFORMATION_SCHEMA". "SYSTEM_PRIMARYKEYS"
O asterisco garante que todas as colunas disponíveis da tabela sejam mostradas. A tabela pesquisada
acima fornece informações essenciais sobre as chaves primárias das várias tabelas.
Esta informação é útil sobretudo para macros. Em vez de fornecer informações detalhadas sobre cada
tabela ou banco de dados recém-criado, os procedimentos são escritos para buscar essas informações
diretamente do banco de dados e, portanto, são universalmente aplicáveis. O banco de dados de exemplo
mostra isso, entre outras coisas, em um dos módulos de manutenção, onde chaves estrangeiras são
determinadas.

Tabelas de teste para entradas desnecessárias


Um banco de dados consiste em uma ou mais tabelas principais, que contêm chaves estrangeiras de
outras tabelas. No banco de dados de exemplo, essas são as tabelas de mídia e endereço. Na tabela de
endereços, a chave primária do código postal ocorre como uma chave estrangeira. Se uma pessoa se
mudar para casa, o endereço será alterado. O resultado pode ser que nenhuma chave estrangeira
Postcode_ID correspondente a este código postal exista por mais tempo. Em princípio, portanto, o próprio
código postal pode ser excluído. No entanto, não é aparente durante o uso normal que o registro não é mais
necessário. Existem várias maneiras de evitar esse tipo de problema.

Testando entradas usando a definição de relacionamento


A integridade dos dados pode ser assegurada ao definir relacionamentos. Em outras palavras, você pode
impedir que a exclusão ou alteração de chaves leve a erros no banco de dados.
O diálogo a seguir é acessível através de Ferramentas > Relações , seguido de um direito - clique no
conector entre duas tabelas.

Aqui as tabelas Endereço e Rua são consideradas. Todas as ações especificadas se aplicam à tabela
Address , que contém a chave estrangeira Street _ ID. As opções de atualização referem-se a uma
atualização do campo ID na tabela Street. Se a chave numérica no campo " Rua ". " ID " for alterada,
"Nenhuma ação" significa que o banco de dados resiste a essa alteração se uma " Rua ". " ID " com esse
número de chave ocorre como uma chave estrangeira na tabela Endereço .
" Atualização em cascata " significa que o número da chave é simplesmente transferido. Se a rua 'Burgring'
na tabela Street tiver o ID '3' e também estiver representada em " Endereço ". " Street _ ID " , o ID pode ser
alterado com segurança , por exemplo, para '67' - o " Endereço " correspondente "" Rua _ ID " valores
serão automaticamente ser alterado para '67'.
Se Set null for escolhido, a alteração do ID torna "Address". "Street_ID" um campo vazio.
As opções de exclusão são tratadas de forma semelhante.
Para ambas as opções, a GUI atualmente não permite a possibilidade Definir o padrão , já que as
configurações padrão da GUI são diferentes daquelas do banco de dados. Veja C apítulo 3, T ables.
A definição de relacionamentos ajuda a manter os relacionamentos limpos, mas não remove registros
desnecessários que fornecem sua chave primária como uma chave estrangeira no relacionamento. Pode
haver qualquer número de ruas sem endereços correspondentes.

Edição de entradas usando formulários e subformulários


Em princípio, toda a inter-relação entre as tabelas pode ser exibida nas formas. Isso é mais fácil, é claro,
quando uma tabela está relacionada a apenas uma outra tabela. Assim, no exemplo a seguir, a chave
primária do autor se torna a chave estrangeira na tabela rel_Media_Author; r el_Media_Author também
contém uma chave estrangeira da Mídia, de modo que a seguinte organização mostra um relacionamento
m: com três formas. Cada um é apresentado através de uma tabela.
A primeira figura mostra que o título que eu ouço você bater pertence ao autor Dave Edmunds . Portanto,
Dave Edmunds não deve ser excluído - caso contrário, as informações necessárias para a medi a ouvi-lo
bater serão perdidas . No entanto, a caixa de listagem permite que você escolha um registro diferente em
vez de Dave Edmunds .

No formulário, há um filtro interno cuja ativação pode informar quais categorias não são necessárias na
tabela Mídia. No caso descrito, quase todos os exemplos de autores estão em uso. Apenas o registro Erich
Kästner pode ser excluído sem quaisquer consequências para qualquer outro registro na mídia .
O filtro é dura bacalhau ed neste caso. É encontrado nas propriedades do formulário. Esse filtro é ativado
automaticamente quando o formulário é iniciado. Pode ser desligado e ligado. Se for excluído, pode ser
acessado novamente por um recarregamento completo do formulário. Isso significa mais do que apenas
atualizar os dados; todo o documento do formulário deve ser fechado e reaberto.

Consultas para encontrar entradas órfãs


O filtro acima é parte de uma consulta que pode ser usada para localizar entradas órfãs.
SELECT "Sobrenome", "Nome" FROM "Autor" WHERE "ID" NÃO IN (SELECT "Author_ID" FROM
"rel_Media_Author")
Se uma tabela contiver chaves estrangeiras de várias outras tabelas, a consulta precisará ser estendida de
acordo. Isso afeta, por exemplo, a tabela Town, que possui chaves estrangeiras na tabela Mídia e na tabela
Código postal. Portanto, r ecords na tabela Town que devem ser excluídos não devem ser referenciados
em nenhuma dessas tabelas. Isso é determinado pela seguinte consulta:
SELECT "Town" FROM "Cidade" ONDE "ID" NÃO IN (SELECT "Town_ID" FROM "Media") E "ID" NÃO
IN (SELECT "Town_ID" FROM "Postcode")
As entradas órfãs podem ser excluídas selecionando todas as entradas que passam pelo filtro definido e
usando a opção Excluir no menu de contexto do ponteiro do registro, chamado clicando com o botão direito
do mouse.

Velocidade de pesquisa de banco de dados

Efeito de consultas
São apenas essas consultas, usadas na seção anterior para filtrar dados, que se mostram insatisfatórias
em relação à velocidade máxima de pesquisa de um banco de dados. O problema é que, em grandes
bancos de dados, a subconsulta recupera uma quantidade correspondentemente grande de dados com os
quais cada registro exibível individual deve ser comparado. Somente comparações com o relacionamento
IN tornam possível comparar um único valor com um conjunto de valores. A pergunta
… ONDE "ID" NÃO ESTÁ (SELECIONE "Author_ID" DE "rel_Media_Author")
pode conter um grande número de possíveis chaves estrangeiras da tabela rel_Media_Author, que deve
primeiro ser comparada com as chaves primárias na tabela Autores de cada registro nessa tabela. Essa
consulta, portanto, não é adequada para uso diário, mas pode ser necessária para manutenção do banco
de dados . Para o uso diário, as funções de pesquisa precisam ser construídas de forma diferente, para
que a pesquisa de dados não seja excessivamente longa e não danifique o trabalho diário com o banco de
dados.

Efeito de listboxes e comboboxes


Quanto mais listboxes que são construídos em uma forma, e quanto mais eles contêm, quanto mais tempo
a forma leva para carregar, uma vez que estes listboxes deve ser criado.
Quanto melhor o programa Base configurar a interface gráfica e inicialmente ler o conteúdo da caixa de
listagem apenas parcialmente, menos atraso haverá.
Caixas de listagem são criadas usando consultas, e essas consultas devem ser executadas quando o
formulário é carregado para cada caixa de listagem.
A mesma estrutura de consulta para mais listboxes é melhor feita usando um modo de exibição comum,
em vez de criar repetidamente campos com a mesma sintaxe usando os comandos SQL armazenados
nas caixas de listagem. As visualizações são, acima de tudo, preferíveis para sistemas de banco de dados
externos, já que aqui o servidor é executado de maneira significativamente mais rápida do que uma
consulta que deve ser reunida pela GUI e recém colocada no servidor. O servidor trata as exibições como
consultas locais completas.
Apêndice

Códigos de barra
Para poder usar a função de impressão de código de barras, a fonte ean13.ttf deve estar instalada.
Esta fonte está disponível gratuitamente.
Códigos de barras EAN13 podem ser criados usando ean13.ttf da seguinte forma:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Número Maiúsculas, A = 0 B = 1 etc. * Minúsculas, a = 0 b = 1 etc. +

Veja também a consulta Barcode_EAN13_ttf_command no banco de dados de exemplo


Media_without_Macros.

Tipos de dados para o editor de tabelas

Inteiros
Tipo Opção HSQLDB Alcance Espaço de
armazenamento
8
Inteiro TINYINT TINYINT 1 byte
2 = 256 | - 128
minúsculo
a + 127
16
Pequeno SMALLINT SMALLINT 2 bytes
2 = 65536 | -
Integer
32768 bis +
32767
32
Inteiro INTEGER INTEGER | INT 4 bytes
2 =
4294967296 | -
2147483648 bis
+ 2147483647
64
BigInt BIGINT BIGINT 8 bytes
2

Números de ponto flutuante


Tipo Opção HSQLDB Alcance Espaço de
armazenamento

Decimal DECIMAL DECIMAL Ilimitado, até 50 variável


lugares na GUI,
ponto decimal
fixo, precisão
perfeita

Número NUMÉRICO NUMÉRICO Ilimitado, até 50 variável


lugares na GUI,
ponto decimal
fixo, precisão
perfeita

Flutuador FLUTUADOR (DUPLO usado


em vez disso)

Real REAL REAL

Duplo DUPLO DUPLO Ajustável, não 8 bytes


[PRECISÃO] | exato, máximo
FLUTUADOR de 15 casas
decimais

Texto
Tipo Opção HSQLDB Alcance Espaço de
armazenamento

Texto VARCHAR VARCHAR Ajustável variável

Texto VARCHAR_ VARCHAR_ Faixa ajustável variável


IGNORECASE IGNORECASE afeta a
classificação

Texto CARACTERES CHAR | Ajustável, fixo


(correção) PERSONAGEM resto do texto
real substituído
por espaços

Memorando LONGVARCHAR LONGVARCHAR variável

Tempo
Tipo Opção HSQLDB Alcance Espaço de
armazenamento

Encontro ENCONTRO ENCONTRO 4 bytes

Tempo TEMPO TEMPO 4 bytes

Data hora TIMESTAMP TIMESTAMP | Ajustável (0,6 - 8 bytes


DATA HORA 6 significa com
milissegundos)

De outros
Tipo Opção HSQLDB Alcance Espaço de
armazenamento

Sim não BOLEANO BOOLEAN |


POUCO

Binário BINÁRIO BINÁRIO Como o inteiro fixo


(correção)

Campo VARBINÁRIO VARBINÁRIO Como o inteiro variável


binário

Imagem LONGVARBINARY LONGVARBINARY Como o inteiro variável,


destinado a
imagens
maiores

DE DE OUTROS OUTRAS |
OUTROS OBJETO

Funções integradas e procedimentos armazenados

Numérico

Como estamos lidando aqui com números de ponto flutuante, certifique -se de cuidar das
configurações dos campos nas consultas. Principalmente a exibição de casas decimais é
restrita, de modo que, em alguns casos, pode haver resultados inesperados. Por exemplo, a
coluna 1 pode mostrar 0.00, mas na verdade contém 0,001 e a coluna 2, 1000. Se a coluna 3
estiver definida para mostrar a Coluna 1 * Coluna 2, ela realmente mostrará 1.

ABS (d) Retorna o valor absoluto de um número, removendo um sinal


de menos quando necessário.

ACOS (d) Retorna o arco-cosseno.

ASIN (d) Retorna o arco senoidal.

ATAN (d) Retorna o arco tangente.

ATAN2 (a, b) Retorna a tangente do arco usando coordenadas. a é o valor


do eixo x, b o valor do eixo y

BITAND (a, b) Tanto a forma binária de a quanto a forma binária de b devem


ter 1 na mesma posição para produzir 1 no resultado.
BITAND (3,5) produz 1; 0011 AND 0101 = 0001

BITOR (a, b) A forma binária de a ou a forma binária de b deve ter 1 na


mesma posição para gerar 1 no resultado.
BITAND (3,5) produz 7; 0011 OU 0101 = 0111

TETO (d) Retorna o menor número inteiro que não é menor que d.

COS (d) Retorna o cosseno.

COT (d) Retorna a cotangente.

GRAUS (d) Converte radianos em graus.

EXP (d) d
Retorna e (e: (2.718 ...)).

PISO (d) Retorna o maior número inteiro que não é maior que d.

LOG (d) Retorna o logaritmo natural para a base e.

LOG10 (d) Retorna o logaritmo para a base 10.

MOD (a, b) Retorna o restante como um número inteiro, na divisão de 2


números inteiros.
MOD (11,3) ergibt 2, weil 3 * 3 + 2 = 11

PI () Retorna π (3,1415 ...) .

POTÊNCIA (a, b) b 3
a , POWER (2,3) = 8, desde 2 =8

RADIANOS (d) Converte graus em radianos.

RAND () Retorna um número aleatório maior ou igual a 0,0 e menor


que 1,0.

ROUND (a, b) Arredonda de a a b casas decimais.

ROUNDMAGIC (d) Resolve problemas de arredondamento, que surgem do uso


de números de ponto flutuante. 3.11-3.1-0.01 não é
exatamente 0, mas é mostrado como 0 na GUI.
ROUNDMAGIC torna um valor zero real.

SINAL (d) Retorna - 1, se d for menor que 0, 0 se d == 0 e 1 se d for


maior que 0.

SIN (A) Retorna o seno de um ângulo em radianos.

SQRT (d) Retorna a raiz quadrada.

TAN (A) Retorna a tangente de um ângulo em radianos.

TRUNCATE (a, b) Trunca um a b casas decimais.


TRUNCATE (2,37456,2) = 2,37

Texto

ASCII (s) Retorna o código ASCII da primeira letra da string.


BIT_LENGTH (str) Retorna o comprimento da string de texto str em bits.

CHAR (c) Retorna a letra correspondente ao código ASCII c.

CHAR_LENGTH (str) Retorna o tamanho do texto em caracteres.

CONCAT (str1, str2) C oncatenados str1 e str2.

'str1' || 'str2' || 'str3' ou 'str1' Concatena str1 + str2 + str3, alternativa mais simples ao
+ 'str2' + 'str3' CONCAT.

DIFERENÇA (s1, s2) Retorna a diferença de som entre s1 e s2. Apenas um


número inteiro é produzido. 0 meio de th e Y têm o mesmo
som. So 'para' e 'four' rendimento 0, ' rei' um nd 'asa' de
rendimento 1, ' ver' e ' mar' de rendimento 0.

HEXTORAW (s1) Traduz código hexadecimal para outros caracteres.

INSERIR (s, iniciar, len, s2) Retorna uma string de texto, com parte do texto substituído.
Começando com o início, um comprimento len é recortado
dos textos e substituído pelo texto s2.
INSERT (Bundesbahn, 3, 4, mmel) converte Bundesbahn em
Bummelbahn, onde o comprimento do texto inserido pode ser
maior que o do texto excluído sem causar nenhum problema.
Então INSERT (Bundesbahn, 3, 5, s und B) produz 'Bus und
Bahn'.

LCASE (s) Converte uma string em minúscula.

ESQUERDA (s, contagem) Retorna os primeiros caracteres de contagem do começo do


texto s.

COMPRIMENTO (S) Retorna o tamanho do texto em caracteres.

LOCATE (pesquisa, s, Retorna a primeira correspondência para o termo pesquisa no


[iniciar]) texto s. A correspondência é dada como um número de
offset: (1 = esquerda, 0 = não encontrada)
Definir um ponto inicial dentro da string de texto é opcional.

LTRIM (s) Remove os espaços iniciais e os caracteres não imprimíveis


do início de uma cadeia de texto.

OCTET_LENGTH (str) Retorna o tamanho de uma string de texto em bytes. Isso


corresponde ao dobro do comprimento em caracteres.

RAWTOHEX (s1) Converte em hexadecimais, inverta de HEXTORAW ().

REPETIR (s, contagem) Repete os tempos de contagem da cadeia de texto.

SUBSTITUIR (s, substituir, Substitui todas as ocorrências existentes de substituir na


s2) cadeia de texto s pelo texto s2.

DIREITA (s, contagem) Oposto da esquerda; r eturns o último c o caracteres UNT no


final de uma cadeia de texto.

RTRIM (s) Remove todos os espaços e caracteres não imprimíveis do


final de uma cadeia de texto.

SOUNDEX (s) Retorna um código de 4 caracteres, correspondente ao som


de s - corresponde à função DIFFERENCE ().

ESPAÇO (contagem) Retorna espaços de contagem.

SUBSTR (s, inicie [, len]) Abrev iation para SUBSTRING.

SUBSTRING (s, inicie [, Retorna o texto s da posição inicial (1 = esquerda). Se length


len]) for omitido, toda a string será retornada.

UCASE (s) Converte uma string para maiúscula.

LOWER (s) Como LCASE (s)

UPPER (s) Como UCASE (s)

Data hora

CURDATE () Retorna a data atual.


CURTIME () Retorna a hora atual.

DATEDIFF (string, Diferença de data entre duas datas - compara valores de data
datetime1, datetime2) / hora.
A entrada em string determina as unidades nas quais a
diferença é retornada: ms = milissegundo, ss = segundo, mi =
minuto, hh = hora, dd = dia, mm = mês, yy = ano.
Tanto as formas longas quanto as curtas podem ser usadas
para string.

DIA (data) Retorna o dia do mês (1-31).

DAYNAME (data) Retorna o nome em inglês do dia.

DAYOFMONTH (data) Retorna o dia do mês (1-31). Sinônimo para DAY ()

DAYOFWEEK (data) Retorna o dia da semana como um número (1 representa o


domingo).

DAYOFYEAR (data) Retorna o dia do ano (1-366).

HORA (tempo) Retorna a hora (0 a 23).

MINUTO (tempo) Retorna o minuto (0 a 59).

Data do mês) Retorna o mês (1-12).

MONTHNAME (data) Retorna o nome em inglês do mês.

AGORA() Retorna a data atual e a hora atual juntas como um registro de


data e hora. Alternativamente, CURRENT_TIMESTAMP pode
ser usado.

TRIMESTRE (data) Retorna o trimestre do ano (1-4).

Segundo tempo) Retorna a parte dos segundos do tempo (0 a 59).

SEMANA (data) Retorna a semana do ano (1-53).

ANO (data) Retorna a parte do ano de uma entrada de data.


DATA ATUAL Sinônimo para CURDATE (), SQL-Standard, Base fornece a
mensagem: Acesso negado.
HORA ATUAL Sinônimo para CURTIME (), SQL-Standard.
CURRENT_TIMESTAMP Sinônimo para NOW (), SQL-Standard.

Conexão de banco de dados


Exceto para IDENTITY (), que não tem significado no Base, tudo isso pode ser feito usando o
Comando SQL Direto .

BASE DE DADOS() Retorna o nome do banco de dados ao qual esta conexão


pertence.

DO UTILIZADOR() Retorna o nome de usuário desta conexão.

USUÁRIO ATUAL Função padrão SQL, o nome de usuário ().

IDENTIDADE() Retorna o último valor para um campo de autovalor, que foi


criado na conexão atual. Isso é usado na codificação de
macro para transferir uma chave primária em uma tabela para
se tornar uma chave estrangeira para outra tabela.

Sistema

IFNULL (exp, valor) Se exp for NULL, o valor será retornado, caso contrário, exp.
Como alternativa, uma extensão COALESCE () pode ser
usada. Exp e valor devem ter o mesmo tipo de dados.

CASEWHEN (exp, v1, v2) Se exp for true, v1 será retornado, caso contrário, v2.
Alternativamente CASE WHEN pode ser usado. CASE
WHEN funciona melhor com a GUI.

CONVERT (termo, tipo) Converte termo em outro tipo de dados.

CAST (termo como tipo) Sinônimo para CONVERT ().


COALESCE (expr1, expr2, Se expr1 não for NULL, retornará expr1, caso contrário, expr2
expr3, ...) será verificado, expr3 e assim por diante.

NULLIF (v1, v2) Se v1 é igual a v2, NULL é retornado, caso contrário, v1.

CASO v1 QUANDO v2 Se v1 é igual a v2, v3 é retornado. Caso contrário, v4 é


ENTÃO v3 [ELSE v4] END retornado ou NULL, se não houver cláusula ELSE.

CASO QUANDO expr1 Se expr1 for true, v1 será retornado [opcionalmente, outras
ENTÃO v1 [QUANDO condições podem ser definidas]. Caso contrário, a v4 é
expr2 THEN v2] [ELSE v4] retornada ou NULL se não houver nenhuma condição ELSE.
END

EXTRACTO ({ANO | MÊS | Pode substituir muitas das funções de data e hora. Retorna o
DIA | HORA | MINUTO | ano, o mês, o dia, etc. a partir de um valor de data ou data /
SEGUNDO} DE < d at e ou hora.
hora >)

POSITION (<expressão de Se a primeira cadeia estiver contida na segunda, o


string> IN <expressão de deslocamento da primeira cadeia será dado, caso contrário, 0
string>) será retornado.

SUBSTRING (<expressão Fornece parte de uma string de texto da posição especificada


de string> FROM em FROM, opcionalmente até o comprimento dado em FOR.
<expressão numérica>
[FOR <expressão
numérica>])

TRIM ([{LEADING | Os caracteres especiais e espaços não impressos são


TRAILING | BOTH}] DE removidos.
<expressão de string>)

Tabelas de informação para HSQLDB


Dentro de um banco de dados, as informações sobre todas as propriedades da tabela e suas conexões
entre si são armazenadas na área INFORMATION_SCHEMA . Esta informação permite criar macros Base
que requerem poucos argumentos para seus procedimentos. Uma aplicação pode ser encontrada na base
de dados de exemplo na manutenção de módulo t ele Table_purge procedimento para o controlo de
diálogos.
Em uma consulta, informações individuais e todos os campos que pertencem podem ser fornecidos da
seguinte maneira:
SELECT * FROM ″ INFORMATION_SCHEMA ″. ″ SYSTEM_ALIASES ″
Ao contrário de uma tabela normal, é necessário usar aqui INFORMATION_SCHEMA como um prefixo
para o nome apropriado da lista a seguir:
SYSTEM_ALIASES
SYSTEM_ALLTYPEINFO
SYSTEM_BESTROWIDENTIFIER
SYSTEM_CACHEINFO
SYSTEM_CATALOGS
SYSTEM_CHECK_COLUMN_USAGE
SYSTEM_CHECK_CONSTRAINTS
SYSTEM_CHECK_ROUTINE_USAGE
SYSTEM_CHECK_TABLE_USAGE
SYSTEM_CLASSPRIVILEGES
SYSTEM_COLUMNPRIVILEGES
SYSTEM_COLUMNS
SYSTEM_CROSSREFERENCE
SYSTEM_INDEXINFO
SYSTEM_PRIMARYKEYS
SYSTEM_PROCEDURECOLUMNS
SYSTEM_PROCEDURES
PROPRIEDADES DO SISTEMA
SYSTEM_SCHEMAS
SYSTEM_SEQUENCES
SYSTEM_SESSIONINFO
SYSTEM_SESSIONS
SYSTEM_SUPERTABLES
SYSTEM_SUPERTYPES
SYSTEM_TABLEPRIVILEGES
SYSTEM_TABLES
SYSTEM_TABLETYPES
SYSTEM_TABLE_CONSTRAINTS
SYSTEM_TEXTTABLES
SYSTEM_TRIGGERCOLUMNS
SYSTEM_TRIGGERS
SYSTEM_TYPEINFO
SYSTEM_UDTATTRIBUTES
SYSTEM_UDTS
SYSTEM_USAGE_PRIVILEGES
SYSTEM_USERS
SYSTEM_VERSIONCOLUMNS
SYSTEM_VIEWS
SYSTEM_VIEW_COLUMN_USAGE
SYSTEM_VIEW_ROUTINE_USAGE
SYSTEM_VIEW_TABLE_USAGE

Reparo de banco de dados para arquivos * .odb


O backup regular de dados deve ser uma prática padrão ao usar um PC. As cópias de backup são a
maneira mais simples de retornar a um estado atual até meio caminho para seus dados. No entanto, na
prática, isso é muitas vezes falta.
No caso de travamentos súbitos do PC, pode acontecer que bancos de dados abertos (bancos de dados
HSQLDB internos) não possam mais ser abertos no L ibre O ffice . Em vez disso, quando você tenta abrir
o banco de dados, é solicitado um filtro correspondente ao formato.
O problema aqui é que parte dos dados em um banco de dados aberto está contida na memória de trabalho
e é copiada apenas temporariamente para armazenamento intermediário. Somente quando o arquivo é
fechado, todo o banco de dados é gravado de volta no arquivo e reempacotado.
Para obter acesso novamente aos seus dados, você pode achar útil o seguinte procedimento:
1.Crie uma cópia do seu banco de dados para as etapas a seguir.
2.Tente abrir a cópia com um programa de arquivamento. No caso dos arquivos * .odb, estamos lidando
com um formato compactado, um arquivo Zip. Se o arquivo não puder ser aberto diretamente, tente
renomeá-lo de * .odb para * .zip. Se isso não for aberto, seu banco de dados estará salvando.
3.As seguintes pastas serão sempre vistas depois de abrir um arquivo de banco de dados em um
programa de arquivamento:

4.O arquivo de banco de dados deve ser descompactado. As informações mais importantes, na medida
em que os dados estão em causa, estão na subpasta de banco de dados no arquivo de dados
e roteiro .
5.Pode ser necessário examinar o arquivo de script e testá-lo em busca de contradições. Esta etapa
pode, no entanto, ser deixada para o estágio de teste. O arquivo de script contém, acima de tudo, a
descrição da estrutura da tabela.
6.Crie um novo arquivo de banco de dados vazio e abra esse arquivo com o programa de arquivamento.
7.Substitua os arquivos de dados e script no novo arquivo de banco de dados pelos arquivos
descompactados no step 4 .
8.Feche o programa de arquivamento. Se fosse necessário renomear o arquivo para * .zip antes de abri-lo
no programa de arquivamento (isso depende do seu sistema operacional), agora renomeie-o novamente
para * .odb.
9.Abra o arquivo de banco de dados em L ibre O ffice . Y OU deve ser capaz de acessar suas tabelas
novamente.
10.Até que ponto suas consultas, formulários e relatórios podem ser recuperados de maneira semelhante
devem ser objeto de testes adicionais.
Veja também: http://forum.openoffice.org/en/forum/viewtopic.php?f=83&t=17125
Se, conforme descrito nas páginas a seguir, você estiver usando o HSQLDB externo, pode haver um
problema adicional com o arquivo * .odb conectado a algumas versões do L ibreOffice . Se HSQLDB
externo for usado, a maneira mais segura é através do hsqldb.jar-archive, que é fornecido com o L
ibreOffice . Se um arquivo diferente for usado, isso pode levar a que o banco de dados interno fique
repentinamente inacessível. Isso ocorre porque o ibreOffice 3.x tem dificuldade em distinguir entre
HSQLDB interno e externo e produz avisos de incompatibilidade entre as versões.
Se bancos de dados internos não puderem mais ser abertos, você deverá utilizar como banco de dados
externo o arquivo hsqldb.jar fornecido . Além disso, você deve extrair do arquivo * .odb a pasta do
banco de dados . O arquivo de propriedades, nesse caso, possui uma entrada que leva ao erro
acima no L ibre O ffice :
versão = 1.8.1 na linha 11
Esta linha deve ser alterada para:
versão = 1.8.0
Posteriormente, a pasta do banco de dados é colocada de volta no pacote * .odb e o banco de dados pode
mais uma vez ser aberto no L ibre O ffice .

Conectando um banco de dados a um HSQLDB externo


O HSQLDB interno é indistinguível da variante externa. Se, como na descrição a seguir, o acesso inicial ao
banco de dados for externo, nenhuma função do servidor será necessária. Você só precisa do programa de
arquivamento que é fornecido com o L ibre O ffice . Você o encontrará no caminho em
/program/classes/hsqldb.jar . O uso deste arquivo é a solução mais segura, pois você não terá
problemas de versão.
O HSQLDB externo está disponível gratuitamente para download em http://hsqldb.org/ . Quando o banco de
dados é instalado, as seguintes etapas devem ser executadas no L ibreOffice :

Se o driver do banco de dados não estiver no caminho do Java-Runtime, ele deve ser inserido como um
caminho de classe em Ferramentas > Opções > Java .
A conexão com o banco de dados externo usa o JDBC. O arquivo de banco de dados deve ser
armazenado em um diretório específico. Este diretório pode ser escolhido livremente. No exemplo a seguir,
ele está na pasta inicial. O restante do caminho do diretório e o nome do banco de dados não são
fornecidos aqui.
É importante, se os dados no banco de dados forem gravados usando a GUI, que, ao lado do nome do
banco de dados, as palavras " ; default_schema = true" sejam escritas.
Assim:
jdbc: hsqldb: arquivo: / home / PathToDatabase / Databasename;
default_schema = true
Na pasta você encontrará os arquivos:
Databasename.backup
Databasename.data
Databasename.properties
Databasename.script
Databasename.log
O próximo passo é dar ao usuário padrão, se nada na configuração HSQLDB for alterado:

Isso cria a conexão e o banco de dados se torna acessível.

Se uma base de dados externa é editado com uma versão de HSQLDB 2. x ,


que já não pode ser convertido em um banco de dados interno sob
Cuidado LibreOffice. Isto é devido a funções adicionais que não estão presentes na
versão 1.8. x . Isso encerra a chamada no caso da versão 1.8. x enquanto o
arquivo de script do banco de dados está sendo lido.
Da mesma forma, um banco de dados externo que tenha sido editado com
uma versão da segunda série não pode mais ser editado com a versão 1.8. x ,
compatível com o LibreOffice.

Alterando a conexão do banco de dados para o HSQLDB externo


Bancos de dados HSQL internos têm a desvantagem de que o armazenamento de dados envolve um
arquivo compactado. Somente na compactação são todos os dados finalmente escritos. Isso pode levar
mais facilmente à perda de dados do que ao trabalhar com um banco de dados externo. A seção a seguir
mostra as etapas necessárias para alterar com êxito um banco de dados existente de um arquivo * .odb
para uma versão externa no HSQL.
A partir de uma cópia do banco de dados existente, extraia o diretório do banco de dados . Copie o
conteúdo em um diretório arbitrário, conforme descrito acima. Adicione o nome do banco de dados aos
nomes de arquivos resultantes:
Databasename.backup
Databasename.data
Databasename.properties
Databasename.script
Databasename.log
Agora, o arquivo content.xml deve ser extraído do arquivo * .odb. Use qualquer editor de texto
simples para encontrar as seguintes linhas:
<db: connection-data> <db: conexão-recurso xlink: href = "sdbc: integrado:
hsqldb" /> <db: login db: é-senha-requerida = "false" /> </ db: connection-
data > <db: driver-settings />
Essas linhas devem ser substituídas por uma conexão com um banco de dados externo, neste caso, uma
conexão com um banco de dados com o nome Union , no diretório hsqldb_data .
<db: connection-data> <db: conexão-recurso xlink: href = "jdbc: hsqldb:
arquivo: / home / robby / documentos / bancos de dados / hsqldb_data /
Union; default_schema = true" /> <db: login db: usuário -name = "sa" db: é-
senha-requerida = "false" /> </ db: connection-data> <db: db do driver-
settings: java-driver-class = "org.hsqldb.jdbcDriver" />
Se, conforme descrito acima, a configuração básica do HSQLDB não estiver danificada, o nome de usuário
e a senha opcional também devem ser concordados.
Depois de alterar o código, content.xml deve ser colocado de volta no arquivo * .odb. O diretório do
banco de dados no arquivo agora é excedente aos requisitos. Os dados serão, no futuro, acessados
através do banco de dados externo.

Alterando a conexão do banco de dados para acesso multiusuário


Para acesso multiusuário, o HSQLDB deve ser disponibilizado em um servidor. Como a instalação do
servidor é realizada varia dependendo do seu sistema operacional. Para o OpenSuSE, é necessário
apenas baixar o pacote apropriado e iniciar o servidor centralmente usando o YAST (configuração de nível
de execução). Os usuários de outros sistemas operacionais e outras distribuições Linux podem lik ely
encontrar aconselhamento adequado na Internet.
No diretório inicial do servidor (em SuSE, / var / lib / hsqldb ), você encontrará, entre outras coisas, um
diretório chamado data , no qual o banco de dados deve ser arquivado, e um arquivo chamado
server.properties , que controla o acesso aos bancos de dados nesse diretório.
As linhas a seguir reproduzem o conteúdo completo desse arquivo no meu computador. Ele controla o
acesso a duas bases de dados, nam e ly banco de dados original padrão (que pode ser usado como um
novo banco de dados) e banco de dados que foi extraído do arquivo * .odb.
# Arquivo cfg do Servidor Hsqldb.
# Veja o capítulo Tópicos Avançados do Guia do Usuário Hsqldb.

arquivo server.database.0: data / db0


server.dbname.0 firstdb
server.urlid.0 db0-url
arquivo server.database.1: data / union
união server.dbname.1
server.urlid.1 union-url

server.silent true
server.trace false

server.port 9001
server.no_system_exit true

O banco de dados 0 é endereçado com o nome firstdb , embora os arquivos individuais no diretório
de dados comecem com db0 . Eu adicionei meu próprio banco de dados como Banco de Dados
1 . Aqui, o nome e o arquivo do banco de dados começam de forma idêntica.
Os dois bancos de dados são abordados da seguinte maneira:
jdbc: hsqldb: hsql: // localhost / firstdb; default_schema = verdadeiro
nome de usuário sa
senha
jdbc: hsqldb: hsql: // localhost / union; default_schema = verdadeiro
nome de usuário sa
senha
O sufixo ; default_schema = true para o URL, que é necessário para acesso de gravação
usando a interface gráfica com o usuário do L ibreOffice , é incluído permanentemente.
Se você realmente precisa trabalhar no servidor, convém considerar se o banco de dados precisa ser
protegido por senha por motivos de segurança.
Agora você pode se conectar ao servidor usando o L ibreOffice.
Com esses dados de acesso, o servidor pode ser carregado em seu próprio computador. Em uma rede
com outros computadores, você deve fornecer o nome do host ou o endereço IP ao servidor, que neste
caso está sendo executado em meu computador.
Exemplo: Meu computador tem o IP 192.168.0.20 e é conhecido na rede pelo nome lin_serv . Agora,
suponha que haja outro computador a ser inserido para conexão com o banco de dados:
jdbc: hsqldb: hsql: //192.168.0.20/union; default_schema = true
ou :
jdbc: hsqldb: hsql: // lin_serv / união; default_schema = true
O banco de dados agora está conectado e podemos escrever nele. Rapidamente, no entanto, um problema
adicional aparece. Os valores anteriormente gerados automaticamente não são mais incrementados de
repente. Para isso, precisamos de uma configuração adicional.

Valores de incremento automático com HSQLDB externo


Para utilizar autovalores, são necessários diferentes procedimentos para a configuração da tabela, de
acordo com a versão do L ibreOffice . Comum a todos eles é a seguinte entrada em Editar > Banco de
dados > Configurações avançadas :
A adição de GENERATED BY DEFAULT AS IDENTITY (START WITH 0) faz com que a função dos
valores de incremento automático da chave primária seja definida. A GUI em L ibreOffice assume este
comando, mas infelizmente prefacia a instrução com NOT NULL , para que a sequência de comandos
para HSQLDB não seja legível. Aqui você deve assegurar que o HSQLDB receba o comando acima para
que o campo correspondente contenha a chave primária.

No L ibreOffice, a entrada de autovalores usando a GUI não é possível por esse


motivo. Os usuários dessas versões devem primeiro criar uma tabela com um
campo de chave primária que não faça o incremento automático e, em seguida,
insira diretamente usando Ferramentas > SQL :
Nota
ALTER TABLE "Table_name" ALTER COLUMN "ID" INT GERADO POR
PADRÃO COMO IDENTIDADE (INICIAR COM 0)
Isso pressupõe que o campo da chave primária tenha o ID de nome.

Vous aimerez peut-être aussi