3. Introdução à linguagem SQL
Nesta seção do capítulo, apresentamos os primeiros comandos SQL que permitem criar e utilizar uma única tabela. Em geral, apresentamos uma versão simplificada deles. Sua sintaxe completa está disponível nos guias de referência do Firebird (ver parágrafo 2.2).
Um banco de dados é utilizado por pessoas com diferentes competências:
- o administrador do banco de dados é, em geral, alguém que domina a linguagem SQL e os bancos de dados. É ele quem cria as tabelas, pois essa operação geralmente é realizada apenas uma vez. Com o tempo, ele pode precisar modificar a estrutura delas. Um banco de dados é um conjunto de tabelas interligadas por relações. É o administrador do banco de dados que definirá essas relações. É também ele quem concederá direitos aos diferentes usuários do banco de dados. Assim, ele indicará que determinado usuário tem o direito de visualizar o conteúdo de uma tabela, mas não de modificá-la.
- O usuário do banco de dados é quem dá vida aos dados. De acordo com os direitos concedidos pelo administrador do banco de dados, ele irá adicionar, modificar e excluir dados nas diferentes tabelas do banco. Ele também irá explorá-los para extrair informações úteis para o bom funcionamento da empresa, da administração, etc.
No parágrafo 2.6, apresentamos o editor SQL da ferramenta [IB-Expert]. É essa ferramenta que vamos utilizar. Vamos relembrar alguns pontos:
- O editor SQL é acessado por meio da opção de menu [Tools/SQL Editor] ou pela tecla [F12]

Assim, é exibida uma janela [SQL Editor], na qual podemos digitar um comando SQL:

A captura de tela acima costuma ser representada pelo texto a seguir:
3.1. Os tipos de dados do Firebird
Ao criar uma tabela, é necessário indicar o tipo de dados que uma coluna da tabela pode conter. Apresentamos aqui os tipos de dados mais comuns do Firebird. Vale ressaltar que esses tipos de dados podem variar de um SGBD para outro.
número inteiro no intervalo [-32768, 32767]: 4 | |
número inteiro no domínio [–2 147 483 648, 2 147 483 647]: -100 | |
número real com n dígitos, dos quais m após a vírgula NUMERIC(5,2): -100,23, +027,30 | |
número real aproximado com 7 algarismos significativos: 10,4 | |
número real aproximado com 15 algarismos significativos: -100.89 | |
cadeia de exatamente N caracteres. Se a cadeia armazenada tiver menos de N caracteres, ela será preenchida com espaços. CHAR(10): 'ANGERS ' (4 espaços no final) | |
cadeia de, no máximo, N caracteres VARCHAR(10): 'ANGERS' | |
uma data: '2006-01-09' (formato YYYY-MM-DD) | |
uma hora: '16:43:00' (formato HH:MM:SS) | |
data e hora juntas: '2006-01-09 16:43:00' (formato YYYY-MM-DD HH:MM:SS) |
A função CAST() permite converter de um tipo para outro quando necessário. Para converter um valor V declarado como sendo do tipo T1 para o tipo T2, escreve-se: CAST(V,T2). É possível realizar as seguintes conversões de tipo:
- número para cadeia de caracteres. Essa mudança de tipo ocorre implicitamente e não requer o uso da função CAST. Assim, a operação 1 + '3' não requer a conversão do caractere '3'. Seu resultado é o número 4.
- DATE, TIME, TIMESTAMP para cadeias de caracteres e vice-versa. Assim,
- TIMESTAMP para TIME ou DATE e vice-versa
Em uma tabela, uma linha pode conter colunas sem valor. Diz-se que o valor da coluna é a constante NULL. É possível verificar a presença desse valor por meio dos operadores
IS NULL / IS NOT NULL
3.2. Criação de uma tabela
Para descobrir como criar uma tabela, começamos criando uma no modo [Design] com IBExpert. Para isso, seguimos o método descrito no parágrafo 2.3. Assim, criamos a seguinte tabela:

Essa tabela servirá para registrar os livros adquiridos por uma biblioteca. O significado dos campos é o seguinte:
Name | Tipo | Restrição | Significado |
Esta tabela, que foi criada com a ferramenta IBEXPERT como assistente, poderia ter sido criada diretamente por meio das ordens SQL. Para conhecê-las, basta consultar a aba [DDL] da tabela:

O código SQL, que permitiu criar a tabela [BIBLIO], é o seguinte:
- linha 1: proprietário Firebird — indica o nível do dialeto SQL utilizado
- linha 2: proprietário Firebird — indica a família de caracteres utilizada
- linhas 6 a 14: padrão SQL: cria a tabela BIBLIO, definindo o nome e o tipo de cada uma de suas colunas.
- linha 16: padrão SQL: cria uma restrição indicando que a coluna TITRE não permite duplicatas
- linha 17: padrão SQL: indica que a coluna [ID] é a chave primária da tabela. Isso significa que duas linhas da tabela não podem ter o mesmo valor para ID. Estamos aqui próximos da restrição [UNIQUE NOT NULL] da coluna [TITRE] e, de fato, a coluna TITRE poderia ter servido como chave primária. A tendência atual é utilizar chaves primárias que não tenham significado e que sejam geradas pelo SGBD.
A sintaxe do comando [CREATE TABLE] é a seguinte:
CREATE TABLE tabela (nom_colonne1 type_colonne1 contrainte_colonne1, nom_colonne2 type_colonne2 contrainte_colonne2, ..., nom_colonnen type_colonnen contrainte_colonnen, outras restrições) | |||||||||
cria a tabela table com as colunas indicadas
|
A tabela [BIBLIO] também poderia ter sido criada com a seguinte ordem SQL:
Vamos demonstrar isso. Retomemos essa ordem em um editor SQL (F12) para criar uma tabela que chamaremos de [BIBLIO2]:

Após a execução, é necessário confirmar a transação para visualizar o resultado no banco de dados:

Feito isso, a tabela aparece no banco de dados:

Ao clicar duas vezes em seu nome, é possível acessar sua estrutura:

Podemos ver que a definição que criamos para a tabela [BIBLIO2] está correta
3.3. Exclusão de uma tabela
A ordem SQL para excluir uma tabela é a seguinte:
DROP TABLE table | |
Supprime [table] |
Para excluir a tabela [BIBLIO2] que acabamos de criar, executamos agora o seguinte comando SQL:

e a validamos com [Commit]. A tabela [BIBLIO2] é excluída:

3.4. Preenchimento de uma tabela
Inserimos uma linha na tabela [BIBLIO] que acabamos de criar:

Validamos a adição da linha por meio de [Commit] e, em seguida, clicamos com o botão direito do mouse na linha adicionada:

e solicitemos, conforme mostrado acima, que a linha inserida seja copiada para a área de transferência na forma de um comando SQL INSERT. Em seguida, abramos qualquer editor de texto e colemos (Colar / Paste) o que acabamos de copiar. Obtemos o seguinte código SQL:
INSERT INTO BIBLIO (ID,TITRE,AUTEUR,GENRE,ACHAT,PRIX,DISPONIBLE) VALUES (1,'Candide','Voltaire','Essai','18-OCT-1985',140,'o');
A sintaxe de um comando de inserção SQL é a seguinte:
insert into table [(colonne1, colonne2, ..)] values (valor1, valor2, ....) | |
adiciona uma linha (valor1, valor2, ..) à tabela table. Esses valores são atribuídos às tabelas colonne1, colonne2, ... caso existam; caso contrário, às colunas da tabela na ordem em que foram definidas. |
Para inserir novas linhas na tabela [BIBLIO], digite os seguintes comandos INSERT no editor SQL. Essas ordens serão executadas e validadas uma a uma. Utilize o botão para passar para a próxima ordem.
Após validar as diferentes ordens SQL, obtemos a tabela a seguir:
![]() |
3.5. Consulta de uma tabela
3.5.1. Introdução
No editor SQL, digitemos o seguinte comando:

e executá-lo. Obtemos o seguinte resultado:

O comando SELECT permite consultar o conteúdo das tabelas do banco de dados. Esse comando possui uma sintaxe bastante abrangente. Apresentamos aqui apenas a sintaxe que permite consultar uma única tabela. Abordaremos posteriormente a consulta simultânea de várias tabelas. A sintaxe do comando SQL [SELECT] é a seguinte:
SELECT [ALL|DISTINCT] [*|expression1 alias1, expression2 alias2, ...] FROM table | |
exibe os valores de expressioni para todas as linhas da tabela. expressioni pode ser uma coluna ou uma expressão mais complexa. O símbolo * designa o conjunto de colunas. Por padrão, todas as linhas da tabela (ALL) são exibidas. Se DISTINCT estiver presente, as linhas idênticas selecionadas são exibidas apenas uma vez. Os valores de expressioni são exibidos em uma coluna com o título expressioni ou aliasi, caso este tenha sido utilizado. |
Exemplos:



Acima, associamos aliases (TITRE_DU_LIVRE, PRIX_ACHAT) às colunas solicitadas.
3.5.2. Exibição das linhas que atendem a uma condição
SELECT .... WHERE condition | |
somente as linhas que atendem à condição condition são exibidas |
Exemplos


Um dos livros tem o gênero “romance” e não “Romance”. Utilizamos a função upper, que transforma uma sequência de caracteres em maiúsculas para obter todos os romances.

Podemos combinar condições por meio de operadores lógicos
ET logique | |
OU logique | |
Negação lógica |



![]()

![]() |

3.5.3. Exibição das linhas em uma ordem determinada
Às sintaxes anteriores, é possível adicionar uma cláusula ORDER BY indicando a ordem de exibição desejada:
SELECT .... ORDER BY expression1 [asc|desc], expression2 [asc|dec], ... | |
As linhas resultantes da seleção são exibidas na ordem de 1: ordem crescente (asc / ascending, que é o valor padrão) ou decrescente (desc / descending) de expression1 2: em caso de igualdade de expression1, a exibição é feita de acordo com os valores de expression2 etc. |
Exemplos:





3.6. Exclusão de linhas em uma tabela
DELETE FROM table [WHERE condition] | |
elimina as linhas de table verificando condition. Se esta última estiver ausente, todas as linhas são excluídas. |
Exemplos:

Os dois comandos abaixo são executados um após o outro:

3.7. Alteração do conteúdo de uma tabela
update table set coluna1 = expressão1, coluna2 = expressão2, ... [where condition] | |
Para as linhas de table que verificam condition (todas as linhas, se não houver condição), colonnei recebe o valor de expressioni. |
Exemplos:
Colocamos todos os gêneros em maiúsculas:

Verificamos:
![]()
Exibimos os preços:

O preço dos romances aumenta em 5%:
Verificamos:

3.8. Atualização definitiva de uma tabela
Quando são feitas alterações em uma tabela, o Firebird, na verdade, as gera em uma cópia da tabela. Elas podem então ser tornadas definitivas ou canceladas pelos comandos COMMIT e ROLLBACK.
COMMIT | |
torna definitivas as atualizações feitas nas tabelas desde a última execução do COMMIT. |
ROLLBACK | |
anula todas as modificações feitas nas tabelas desde a última execução do COMMIT. |
Um COMMIT é executado implicitamente nos seguintes momentos: a) Ao desconectar-se do Firebird b) Após cada comando que afete a estrutura das tabelas: CREATE, ALTER, DROP. |
Exemplos
No editor SQL, coloca-se o banco de dados em um estado conhecido, validando todas as operações realizadas desde o último COMMIT ou ROLLBACK:
Solicita-se a lista de títulos:

Exclusão de um título:
Verificação:

O título foi excluído com sucesso. Agora, invalidamos todas as alterações feitas desde o último COMMIT / ROLLBACK:
Verificação:

O título excluído aparece novamente. Agora, vamos solicitar a lista de preços:
![]()
Suponhamos que todos os preços tenham sido zerados.
Vamos verificar os preços:
![]()
Vamos reverter as alterações feitas na base:
e vamos verificar os preços novamente:
![]()
Recuperamos os preços originais.
3.9. Adicionando linhas de uma tabela a outra
É possível adicionar linhas de uma tabela a outra quando suas estruturas são compatíveis. Para demonstrar isso, vamos começar criando uma tabela [BIBLIO2] com a mesma estrutura que a [BIBLIO].
No explorador de bancos de dados de IBExpert, cliquemos duas vezes na tabela [BIBLIO] para acessar a guia [DDL]:

Nessa guia, encontramos a lista de ordens SQL que permitem gerar a tabela [BIBLIO]. Copie todo esse código para a área de transferência (CTRL-A, CTRL-C). Em seguida, vamos chamar uma ferramenta chamada [Script Executive], que permite executar uma lista de ordens SQL:

Aparece um editor de texto, no qual podemos colar (CTRL-V) o texto que colocamos anteriormente na área de transferência:

Costuma-se chamar de script SQL uma lista de comandos SQL. O [Script Executive] nos permitirá executar esse tipo de script, enquanto o editor SQL permitia a execução de apenas um comando por vez. O script SQL atual permite criar a tabela [BIBLIO]. Vamos fazer com que ele crie uma tabela chamada [BIBLIO2]. Para isso, basta alterar [BIBLIO] para [BIBLIO2]:
Vamos executar esse script usando o botão [Run Script] abaixo:

O script é executado:

e podemos ver a nova tabela no explorador de bancos de dados:

Se clicarmos duas vezes em [BIBLIO2] para verificar seu conteúdo, descobriremos que ela está vazia, o que é normal:

Uma variante do comando SQL INSERT permite inserir em uma tabela linhas provenientes de outra tabela:
INSERT INTO table1 [(colonne1, colonne2, ...)] SELECT colunaA, colunaB, ... FROM table2 WHERE condition | |
As linhas de table2 que verificam condition são adicionadas a table1. As colunas colonnea, colonneb, ... de table2 são atribuídas, nessa ordem, às colunas colonne1, colonne2, ... de table1 e, portanto, devem ser de tipo compatível. |
Voltemos ao editor SQL:

e emitamos o comando SQL a seguir:
que insere no [BIBLIO2] todas as linhas do [BIBLIO] correspondentes a um romance. Após a execução da ordem SQL, vamos validá-la com um [Commit]:
Feito isso, consultemos os dados da tabela [BIBLIO2]:

3.10. Exclusão de uma tabela
DROP TABLE table | |
supprime table |
Exemplo: exclui-se a tabela BIBLIO2
Confirmamos a alteração:
No explorador de bancos de dados, atualiza-se a exibição das tabelas:

Verifica-se que a tabela [BIBLIO2] foi excluída:

3.11. Alteração da estrutura de uma tabela
ALTER TABLE table [ ADD nom_colonne1 type_colonne1 contrainte_colonne1] [ALTER nom_colonne2 TYPE type_colonne2] [DROP nom_colonne3] [ADD contrainte] [DROP CONSTRAINT nom_contrainte] | |
permite adicionar (ADD), modificar (ALTER) e excluir (DROP) colunas da tabela. A sintaxe nom_colonnei type_colonnei contrainte_colonnei é a mesma do CREATE TABLE. Também é possível adicionar/excluir restrições de tabela. |
Exemplo: Executemos sucessivamente os dois comandos SQL a seguir no editor SQL
No explorador de bancos de dados, vamos verificar a estrutura da tabela [BIBLIO]:

As alterações foram aplicadas. Vamos ver como o conteúdo da tabela mudou:

A nova coluna [NB_PAGES] foi criada, mas não possui nenhum valor. Vamos excluir essa coluna:
Vamos verificar a nova estrutura da tabela [BIBLIO]:

A coluna [NB_PAGES] foi removida corretamente.
3.12. As visões
É possível ter uma visão parcial de uma tabela ou de várias tabelas. Uma visão funciona como uma tabela, mas não contém dados. Seus dados são extraídos de outras tabelas ou visões. Uma visão apresenta várias vantagens:
- Um usuário pode estar interessado apenas em determinadas colunas e linhas de uma determinada tabela. A visão permite que ele veja apenas essas linhas e colunas.
- O proprietário de uma tabela pode desejar autorizar apenas um acesso limitado a outros usuários. A visão permite que ele faça isso. Os usuários que ele autorizar terão acesso apenas à visão que ele definiu.
3.12.1. Criação de uma vista
CREATE VIEW nom_vue AS SELECT coluna1, coluna2, ... FROM table WHERE condition [ WITH CHECK OPTION ] | |
cria a visualização nom_vue. Essa é uma tabela cuja estrutura é composta pelas colunas coluna1, coluna2, ... de table e, como linhas, as linhas de table que atendem à condição de condition (todas as linhas, caso não haja condição) | |
Esta cláusula opcional indica que as inserções e atualizações na visão não devem criar linhas que a visão não possa selecionar. |
Observação A sintaxe de CREATE VIEW é, na verdade, mais complexa do que a apresentada acima e permite, em particular, criar uma visualização a partir de várias tabelas. Para isso, basta que a consulta SELECT abranja várias tabelas (ver capítulo seguinte).
Exemplos
A partir da tabela biblio, cria-se uma visualização que inclua apenas os romances (seleção de linhas) e apenas as colunas título, autor e preço (seleção de colunas):
No explorador de bancos de dados, atualizamos a visualização (F5). Aparece uma visualização:

É possível identificar a ordem SQL associada à visualização. Para isso, clique duas vezes na visualização [ROMANS]:

Uma visão é como uma tabela. Ela possui uma estrutura:

e um conteúdo:

Uma visualização é usada como uma tabela. É possível fazer consultas SQL nela. Aqui estão alguns exemplos para testar no editor SQL:

O novo romance está visível na visualização [ROMANS]?

Vamos adicionar algo além de um romance à tabela [BIBLIO]:
SQL> insert into biblio(id,titre,auteur,genre,achat,prix,disponible) values (11,'Poèmes saturniens','Verlaine','Poème','02-sep-92',200,'o');
Vamos verificar a tabela [BIBLIO]:

Vamos verificar a visualização [ROMANS]:

O livro adicionado não está na visualização [ROMANS] porque não possuía upper(gênero)='ROMAN'.
3.12.2. Atualização de uma visão
É possível atualizar uma visão da mesma forma que se faz com uma tabela. Todas as tabelas das quais os dados da visão são extraídos são afetadas por essa atualização. Aqui estão alguns exemplos:
SQL> insert into biblio(id,titre,auteur,genre,achat,prix,disponible) values (13,'Le Rouge et le Noir','Stendhal','Roman','03-oct-92',110,'o')


Elimina-se uma linha da visualização [ROMANS]:


A linha excluída da visão [ROMANS] também foi excluída da tabela [BIBLIO]. Agora, aumentamos o preço dos livros da visão [ROMANS]:
Verificamos na [ROMANS]:

Qual foi o impacto na tabela [BIBLIO]?

Os romances também tiveram um aumento de 5% na tabela [BIBLIO].
3.12.3. Excluir uma visualização
DROP VIEW nom_vue | |
exclui a visualização chamada |
Exemplo
No explorador de bancos de dados, é possível atualizar a visualização (F5) para verificar que a visualização [ROMANS] desapareceu:

3.13. Uso de funções de grupos
Existem funções que, em vez de atuarem em cada linha de uma tabela, atuam em grupos de linhas. Trata-se, essencialmente, de funções estatísticas que nos permitem calcular a média, o desvio-padrão etc. dos dados de uma coluna.
SELECT f1, f2, .., fn FROM table [ WHERE condition ] | |
calcula as funções estatísticas fi em todas as linhas da tabela, verificando a eventual condition. |
SELECT f1, f2, .., fn FROM table [ WHERE condition ] [ GROUP BY expr1, expr2, ..] | |
A palavra-chave GROUP BY tem como efeito dividir as linhas da tabela em grupos. Cada grupo contém as linhas para as quais as expressões expr1, expr2, ... têm o mesmo valor. Exemplo: GROUP BY gênero coloca em um mesmo grupo os livros com o mesmo gênero. A cláusula GROUP BY autor,gênero colocaria no mesmo grupo os livros com o mesmo autor e o mesmo gênero. A cláusula WHERE condição elimina primeiro da tabela as linhas que não atendem à condição. Em seguida, os grupos são formados pela cláusula GROUP BY. As funções fi são então calculadas para cada grupo de linhas. |
SELECT f1, f2, .., fn FROM table [ WHERE condition ] [ GROUP BY expression] [ HAVING condition_de_groupe] | |
A cláusula HAVING filtra os grupos formados pela cláusula GROUP BY. Portanto, ela está sempre vinculada à presença dessas cláusulas: GROUP e BY. Exemplo: GROUP BY gênero HAVING gênero!='ROMAN' |
As funções estatísticas fi disponíveis são as seguintes:
média da expressão | |
número de linhas nas quais a expressão tem um valor | |
número total de linhas na tabela | |
valor máximo da expressão | |
mínimo de expressão | |
soma da expressão |
Exemplos
![]()
Preço médio? Preço máximo? Preço mínimo?
![]()

Preço médio de um romance? Preço máximo?
![]()
Quantos BD?
![]()
Quantos romances custam menos de 100 F?
![]()

Quantos livros e qual é o preço médio por livro para livros do mesmo gênero?
SQL> select upper(genre) GENRE,avg(prix) PRIX_MOYEN,count(*) NOMBRE from biblio group by upper(genre)

A mesma pergunta, mas apenas para livros que não sejam romances:
SQL>
select upper(genre) GENRE,avg(prix) PRIX_MOYEN,count(*) NOMBRE
from biblio
group by upper(genre)
having upper(GENRE)!='ROMAN'
![]()
A mesma pergunta, mas apenas para livros com preço inferior a 150 F:
SQL>
select upper(genre) GENRE,avg(prix) PRIX_MOYEN,count(*) NOMBRE
from biblio
where prix<150
group by upper(genre)
having upper(GENRE)!='ROMAN'
![]()
A mesma questão, mas consideramos apenas os grupos com preço médio por livro >100 F
SQL>
select upper(genre) GENRE, avg(prix) PRIX_MOYEN,count(*) NOMBRE
from biblio
group by upper(genre)
having avg(prix)>100
![]()
3.14. Criar o script SQL “ ” a partir de uma tabela
A linguagem SQL é uma linguagem padrão que pode ser utilizada com diversos SGBD. Para poder passar de um SGBD para outro, é recomendável exportar um banco de dados ou apenas alguns elementos dele na forma de um script SQL que, quando executado em outro SGBD, será capaz de recriar os elementos exportados no script.
Vamos, neste caso, exportar a tabela [BIBLIO]. Vamos escolher a opção [Extract Metadata]:

Observe-se acima que é necessário estar na base da qual se deseja exportar os elementos. A opção inicia um assistente:
![]() |
onde gerar o script SQL:
| |
nome do arquivo se a opção [File] for selecionada | |
o que exportar | |
botões para selecionar (->) ou desmarcar (<-) os objetos a serem exportados |
Se quiséssemos exportar toda a base de dados, marcaríamos a opção [Extract All] acima. Queremos apenas exportar a tabela BIBLIO. Para isso, com [4], selecionamos a tabela [BIBLIO] e, com [2], indicamos um arquivo:

Se pararmos por aqui, apenas a estrutura da tabela [BIBLIO] será exportada. Para exportar seu conteúdo, precisamos usar a aba [Data Tables]:
![]() |
Vamos usar [1] para selecionar a tabela [BIBLIO]:
![]() |
Usemos [2] para gerar o script SQL:

Aceitemos a oferta. Isso nos permite ver o script que foi gerado no arquivo [biblio.sql]:
- as linhas 1 a 3 são comentários
- as linhas 5 a 12 são do SQL, de propriedade do Firebird
- as demais linhas são do SQL padrão, que devem poder ser executadas novamente em um SGBD que teria os tipos de dados declarados na tabela BIBLIO.
Vamos executar novamente esse script no Firebird para criar uma tabela BIBLIO2, que será um clone da tabela BIBLIO. Para isso, vamos usar o [Script Executive] (Ctrl-F12):

Vamos carregar o script [biblio.sql] que acabamos de gerar:

Vamos modificá-lo para manter apenas a parte referente à criação da tabela e à inserção de linhas. A tabela é renomeada como [BIBLIO2]:
CREATE TABLE BIBLIO2 (
ID INTEGER NOT NULL,
TITRE VARCHAR(30) NOT NULL,
AUTEUR VARCHAR(20) NOT NULL,
GENRE VARCHAR(30) NOT NULL,
ACHAT DATE NOT NULL,
PRIX NUMERIC(6,2) DEFAULT 10 NOT NULL,
DISPONIBLE CHAR(1) NOT NULL
);
INSERT INTO BIBLIO2 (ID, TITRE, AUTEUR, GENRE, ACHAT, PRIX, DISPONIBLE) VALUES (2, 'Les fleurs du mal', 'Baudelaire', 'POèME', '1978-01-01', 120, 'n');
...
COMMIT WORK;
Vamos executar este script:
![]() | ![]() |
Podemos verificar no explorador de bancos de dados se a tabela [BIBLIO2] foi realmente criada e se possui a estrutura e o conteúdo esperados:
![]() | ![]() |








