Transact-SQL - Básico: DDL
Data Definition Languagem (DDL)
significa Linguagem de Definição de Dados. É um dos segmentos da linguagem SQL
que define como os dados serão armazenados. Em linguagem técnica mais simples,
representa a criação, alteração e exclusão de tabelas (tables), rotinas (Store
Procedures), disparos (triggers) e visões (views) dentro de um Database.
Iniciando pela forma mais prática de
trabalho, o desenvolvedor deve a princípio conhecer a criação de tabelas.
Procure não se incomodar com os termos mais técnicos descritos acima, como
trigger ou view. No decorrer da apostila, estes termos serão esclarecidos.
Existem três tipos básicos de tabelas:
físicas, temporárias e de memória. Independente do tipo, todas são compostas
por colunas (campos) definidas pelo desenvolvedor a fim de armazenar um
determinado conteúdo.
Existe uma variedade de tipos de
campos que podem ser criados. Para simplificar o aprendizado e ser mais direto
no desenvolvimento, estaremos especificando os tipos de campos mais comuns utilizados
pelos desenvolvedores.
Tipo |
Função |
Int |
Suporta números inteiros |
Decimal(total dígitos, casas decimais) |
Suporta números com
até o total de dígitos especificados, sendo o segundo parâmetro o total de
casas decimais. Um padrão a ser sugerido é Decimal(16,4) que
significa: número decimal com 16 dígitos sendo 4 para as casas decimais. No Delphi, este formato corresponde a um tipo Currency. |
Char(total caracteres) |
Aloca espaço para receber caracteres
limitados ao número especificado no parâmetro. Exemplo: Char(30). |
Varchar(total caracteres) |
Demonstra que o
campo irá receber caracteres limitados ao número especificado no parâmetro. A
diferença entre Char e Varchar é que este último não reserva espaço em branco
dentro do banco de dados. Exemplo: Varchar(30). |
SmallDateTime |
Campo definido para
receber data e hora. Existe um outro tipo definido como DateTime, que aloca
mais espaço no banco de dados para armazenar segundos e milissegundos também. |
Além dos tipos que o SGBD nos oferece,
que vão além do quadro apresentado, existem ainda, os chamados UDDT’s (User
Defined Data Type – Tipo de dado definido pelo usuário). Assim, pode-se criar,
por exemplo, um tipo chamado “Data” que substitui a declaração “SmallDateTime”,
simplesmente para facilitar a leitura de criação de campos.
Porém, antes que apresentar a notação
que criará os campos dentro de uma tabela deve-se ter em mente como é efetuada
a criação da própria tabela. Independente do objeto criado, os comandos de
construção são, em parte, iguais a qualquer um. Entenda-se por objeto, qualquer
tabela, Store Procedure (SP), função, trigger ou view.
Segue quadro sintetizando cada comando
da classe DDL:
Função |
Cláusula para
sintaxe |
Criar |
CREATE |
Alterar |
ALTER |
Excluir |
DROP |
A próxima etapa é determinar o tipo de
objeto a ser criado. Observe o quadro a seguir e relacione o tipo de objeto com
o qual se deseja projetar:
Tipo |
Cláusula para
sintaxe |
Tabela |
TABLE |
Store Procedure (SP) |
PROCEDURE |
Função |
FUNCTION |
Trigger |
TRIGGER |
View |
VIEW |
O último termo da sintaxe é o nome que
pretendemos associar ao objeto. Logo, uma sintaxe de criação de tabela
ficaria da seguinte forma:
CREATE TABLE dbo.Swd_Parametros (...)
Uma alteração desta tabela
para, por exemplo, acrescentar mais campos:
ALTER TABLE dbo.Swd_Parametros (...)
A exclusão da tabela:
DROP TABLE dbo.Swd_Parametros
Entretanto, a única das três sintaxes
acima que está completa, sem necessitar de mais comandos, é a exclusão (DROP).
As sintaxes de criação (CREATE) e alteração (ALTER) são sempre seguidas de
complementos para a definição final do comando.
Atente-se para um detalhe ao criar,
alterar ou excluir o objeto: foi acrescentado o prefixo “dbo.”. Este prefixo
especifica o proprietário do objeto. No caso, dbo será de propriedade do
“database owner” e será visível a todos os usuários criados no SQL Server. Não
trataremos a criação de usuários no SQL Server por ora, mas vale realçar
que se existir outros logins o objeto criado como dbo., seja tabela, stored
procedure, function, trigger ou view será visível a todos. Se não for especificado, o SQL
Server assumirá o login atual como proprietário. Assim, um usuário do sistema
não enxergará a tabela criada por outro login que não seja o dele. Por isso, em
todos os objetos, acrescentaremos dbo. Para consultas DQL e algumas rotinas
internas do SQL Server não especificaremos o dbo.
Quando criamos uma tabela,
necessitamos declarar quais os campos que a compõe. Associando esta ideia aos
quadros informativos demonstrados acima, criaremos agora um cadastro de cursos
oferecidos por uma instituição.
Que campos existiriam em uma tabela
como esta? Analisemos: um código, uma descrição, o nível do módulo (1 –
iniciantes, 2 – intermediário e 3 – avançado) e uma média de aprovação.
Consideremos o “código” e a
“descrição” para armazenar caracteres; “nível” como campo inteiro; e “média”
como campo decimal. A sua criação de acordo com a DDL seria:
CREATE TABLE dbo.Cad_Curso (
Codigo char(6) NOT NULL,
Descricao
char(30) NULL,
Nivel
int NULL,
Media
decimal(16,4) NULL
)
Perceba que foram criados campos que
podem ser NULL, ou seja, sem valor nenhum, e um NOT NULL, que deve sempre ter
algum valor informado em cada registro. Entenda-se registro cada linha de
valores correspondentes a cada campo da tabela. Registro em termos técnicos
também é chamado “tupla”.
Toda tabela, seguindo os métodos de
estruturação e normalização voltados para a implementação em banco de dados,
deve possuir o que chamamos de chave primária (PK, de Primary Key). A chave
primária nada mais é do que um ou mais campos dentro de uma tabela, que identifica
um único registro entre todos os lançamentos efetuados. Além disso, os campos
que compõem a chave primária servirão para efetuar o relacionamento entre
outras tabelas.
No exemplo acima, o cadastro de curso
poderia disponibilizar o campo código para ser a chave primária, pois a ideia é
que tenhamos cursos iguais com níveis diferentes. Para cada curso lançado como
registro, haverá um código diferente.
Detalhe importante: os campos que
compõem a chave primária sempre deverão ser definidos como NOT NULL, sendo
obrigado o usuário digitar algum valor.
A criação da chave primária segue na
sintaxe abaixo. Lembre-se que estamos falando apenas de criação da tabela, se o
comando de criação acima já foi rodado, poderíamos apagar a tabela (DROP) ou
alterá-la (ALTER). Cuidado ao pensar em apagar uma tabela, ela pode ter sido já
utilizada para guardar alguns registros.
CREATE TABLE dbo.Cad_Curso
(
Codigo char(6) NOT NULL,
Descricao char(30) NULL,
Nivel
int NULL,
Media
decimal(16,4) NULL,
CONSTRAINT PK_Cad_Curso PRIMARY KEY (Codigo)
)
A cláusula PRIMARY KEY serve para
carregar o campo código como sendo a chave primária. A cláusula CONSTRAINT
serve para especificarmos que estamos criando uma referência chamada PK_Cad_Curso
(veja que foram colocadas as iniciais PK_ seguida do nome da tabela Cad_Curso),
que é do tipo chave primária.
Suponhamos agora que cada curso
precise de uma aprovação de um órgão regulamentador para que a instituição
possa oferecê-lo. Ela já tinha vários cursos, mas nem todos estão aprovados.
Como saber quais estão e quais não estão aprovados? Criando-se um campo que
indique seu status. Tecnicamente, este campo é conhecido como “flag”, pois é um
campo que comporta um simples caracter de controle, geralmente, “S” para sim ou
“N” para não.
Veja como fica a sintaxe da inclusão
do campo na tabela do curso:
ALTER TABLE dbo.Cad_Curso ADD Aprovado char(1) NULL
A tabela Cad_Curso está sendo alterada para a inclusão de um novo campo (ADD) chamado “Aprovado”. Após todo este procedimento de criação e alteração, pode-se analisar como a tabela ficou estruturada através de uma Store Procedure do SGBD chamada SP_Help. Para executá-la, digite:
SP_Help Cad_Curso
Não esqueça de trocar o database de
“master” para algum outro de utilização pública. Observar também que para
executar o sp_help não devemos especificar o dbo. da tabela. O SQL Server já
reconhecerá a tabela criada.
Figura 1: Utilizando o Management Studio para executar comandos DDL
Store Procedure é o próprio sinônimo
de rotina para um banco de dados. Da mesma forma como criamos rotinas no Delphi
(ou em qualquer outra linguagem de programação), também podemos criar uma
“procedure” em SQL.
E qual o motivo de criarmos tais
rotinas? Simplesmente economia de código. Para se criar uma Store
Procedure, siga o quadro acima, da mesma forma como foi seguido para criar
a tabela:
CREATE PROCEDURE dbo.SP_Atualiza_Cursos
AS BEGIN
(...)
END
Uma SP pode ser alterada apagando a
antiga (DROP) e criando-se a nova pelo comando acima. Veja como ficaria a
sintaxe:
DROP PROCEDURE dbo.SP_Atualiza_Cursos
GO
CREATE
PROCEDURE dbo.SP_Atualiza_Cursos
(...)
Também poderia ser alterada pelo
comando ALTER:
ALTER
PROCEDURE dbo.SP_Atualiza_Cursos
(...)
O que executaríamos numa SP? Qualquer
comando DML/DQL exposto no próximo tópico. Este é o motivo pelo qual não
implementarmos uma Store Procedure neste exato momento.
Entretanto, um último ponto deve ser
analisado na Store Procedure: a passagem de parâmetros. Tal como uma rotina
pode ser implementada com parâmetros em qualquer linguagem, também é possível
numa Store Procedure. A declaração de parâmetros segue a mesma definição de
campos em uma tabela:
CREATE PROCEDURE dbo.SP_Atualiza_Cursos (
@A char(2),
@B int,
@c char(5)
)
AS BEGIN
(...)
END
Observe que as variáveis precedem por
um símbolo de arroba (@). Esta é uma convenção da linguagem SQL para
identificarmos as variáveis declaradas na rotina. Para executarmos esta SP,
utilizamos o comando EXEC juntamente com o nome do objeto criado seguido de
seus parâmetros (sem parênteses):
EXEC SP_Atualiza_Cursos ‘AA’, 2,
‘CCCCC’
Não precisa especificar o dbo.
Outro tipo de objeto dentro de um
database são as triggers. A tradução para trigger é “gatilho” ou "disparo". A definição é
simples, a cada inserção, alteração ou exclusão de um ou mais registros dentro
de uma tabela uma série de ações podem ser “disparadas” através das triggers.
Uma trigger não deixa de ser uma
rotina, igual uma Store Procedure. Contudo ela é executada nas situações
especiais citadas acima. Quando se cria uma trigger, determina-se se ela será
executada durante a inserção (INSERT), alteração (UPDATE) ou exclusão (DELETE)
de registros de uma determinada tabela.
Com base nestas informações, podemos
montar o comando DDL para criarmos uma trigger agregada à tabela Cad_Curso:
CREATE TRIGGER dbo.TG_INSUPT_Cad_Curso
ON Cad_Curso FOR
INSERT, UPDATE
AS BEGIN
(...)
END
Observe que uma trigger chamada TG_INSUPT_Cad_Curso
foi criada na tabela Cad_Curso para ser executada quando inserirmos (INSERT) ou
alterarmos (UPDATE) quaisquer registros nesta tabela.
O que executaríamos numa trigger? A
resposta é igual a uma Store Procedure: qualquer comando DML/DQL.
Para excluir uma trigger:
DROP TRIGGER dbo.TG_INSUPT_Cad_Curso
Para finalizar a discussão acerca da
DDL, definiremos o que é uma view: quer dizer visão. É a transformação de uma
consulta DQL em uma estrutura simplificada de modo que esta pode ser associada
a outras tabelas e visões formando consultas mais complexas. Temos que a view,
pode proporcionar um aproveitamento de código para a consulta se tornar mais
organizada.
Um exemplo de aplicação: o
desenvolvedor poderá implementar uma view para resumir um comando DQL para
somar as baixas de uma duplicata. Isso lhe proporcionará um reaproveitamento de
código para comparar com o valor inicial da duplicata. Ao invés de refazer a
soma das baixas toda vez que precisar, poderá utilizar a view das baixas como
se fosse uma simples tabela do sistema. Uma vez mais, estamos falando em
economia de tempo.
Para se criar uma view,
basta novamente seguir os quadros descritos acima:
CREATE VIEW dbo.Vw_Cad_Curso
AS (...)
Para se excluir uma view:
DROP VIEW dbo.Vw_Cad_Curso
Após um treinamento em DML/DQL,
estaremos aptos a implementar uma Store Procedure, trigger ou uma view. Por ora, não tratarei sobre as functions, mas basta lembrar que a sua criação, alteração e exclusão segue a mesma sintaxe de CREATE, ALTER ou DROP FUNCTION.