A frase..

"A bondade tornou feliz minha vida."



domingo, 29 de julho de 2012

Right Join - Para que me será útil?

Right Join
Para que me será útil?

Um videozinho só para quebrar o gelo... (ah gente... esse é meu blog, tenho que estar feliz ao postar algo)

You Are The One - HIM

A verdade é que em casos pequenos pouco se usa right join (ou Right Outer Join), mas sua aplicação é válida. Digamos que você possui uma lista com números telefônicos, numerados, mas apenas os números e outra com os nomes dos donos desses números telefônicos, mais ou menos assim:



Ok, um exemplo até ridículo, afinal ninguém escreve em duas páginas e ainda por cima colocando os nomes (principal referência de consulta em uma agenda telefônica) em segundo plano. Mas isso é um exemplo... Por isso peço paciência é para que possam compreender bem antes de passar pro código SQL. Vou tentar variar as linguagens de SGBD, vamos ver se consigo. Garanto SQLServer e MySQL. Acreditem não tem muita diferença.
Voltando ao exemplo. Você deseja listar os números telefônicos, mas mais do que isso você quer todos os nomes de todos os seus amigos, para então saber quem tem ou não número telefônico. Você pensaria (ou não): "Vou pegar todos os números telefônicos e ligá-los com seus respectivos donos, acompanhado o código e os nomes que sobraram vou copiar também mas com um tracinho pra depois pegar os números desses caras antissociais..." 
Tá isso é bem historinha mesmo. Seria meio assim se visto como um algoritmo:

Selecionar os nomes da lista de nomes e os telefones da lista de telefones, ligando tudo pelo código trazendo tudo da lista da direita na sequência "lista de telefones" e "lista de nomes"

Vamos simular uma ideia muito mais complexa...
Crie um banco, juntamente com suas tabelas. Se preferir temos algumas linhas de código se achar interessante seguir tal linha de raciocínio:

CREATE DATABASE ListaTelefone
USE ListaTelefone

CREATE TABLE Disciplina(
cd_Disciplina INTEGER NOT NULL,
nm_Disciplina VARCHAR(20) NOT NULL
PRIMARY KEY (cd_Disciplina)
);

CREATE TABLE Professor(
cd_Professor INTEGER NOT NULL,
cd_Disciplina INTEGER NULL,
nm_professor VARCHAR (30),
PRIMARY KEY (cd_Professor),
FOREIGN KEY (cd_Disciplina)
REFERENCES Disciplina (cd_Disciplina)
);

CREATE TABLE Telefone(
cd_Telefone INTEGER NOT NULL,
cd_Professor INTEGER NOT NULL,
ds_Telefone VARCHAR(9),
PRIMARY KEY (cd_Telefone),
FOREIGN KEY (cd_Professor)
REFERENCES Professor (cd_Professor)
);


Insira também alguns dados em suas tabelas:

INSERT INTO Disciplina
(cd_Disciplina,nm_Disciplina) 
VALUES
(1,'ESTRUT DE DADOS'),
(2,'ANALISE DE SIST. III'),
(3,'LINGUAG. E TEC. DE P'),
(4,'METODOL. CIENTIFICA '),
(5,'PRATICA DE PROG. I'),
(6,'SIST. OPERACIONAIS I'),
(7,'TELEPROCESSAMENTO'),
(8,'TEORIA DOS GRAFOS I'),
(9,'COMPILADORES I'),
(10,'EMPREENDEDORISMO I') 
INSERT INTO Professor
VALUES
(1,1,'ANA MARIA'),
(2,1,'MARCIA'),
(3,1,'WILMA'),
(4,2,'VILMA'),
(5,2,'ANTONIO CARLOS'),
(6,2,'WILSON'),
(7,3,'FABIO'),
(8,3,'MARCELO'),
(9,3,'TERTULIANO S'),
(10,7,'TERTULIANO T'),
(11,7,'LIDIANE'),
(12,7,'HELENA'),
(13,9,'WAGNER'),
(14,9,'MAURICIO'),
(15,9,'ANDRE'),
(16,4,'ANDREIA'),
(17,4,'MARCO ANTONIO'),
(18,4,'ALEXANDRE ST'),
(19,5,'ALEXANDRE SO'),
(20,5,'BRUNO'),
(21,5,'KATIA')
INSERT INTO Telefone
VALUES
(1,1,'8811-2113'),
(2,11,'8112-4751'),
(3,12,'3564-3647'),
(4,7,'3406-1085'),
(5,13,'9192-1106'),
(6,4,'9192-4356'),
(7,10,'9667-0934'),
(8,5,'8811-2113'),
(9,21,'8112-4751'),
(10,6,'3564-3647'),
(11,20,'3406-1085'),
(12,17,'9609-0934'),
(13,19,'9723-2345'),
(14,8,'3102-3984')



Ótimo, após confiram fazendo os seguinte teste:

SELECT * FROM Disciplina
SELECT * FROM Professor
SELECT * FROM Telefone


Resultado:


Ótimo. Obtendo esse resultado podemos então construir um select um tanto ousado:
Experimente:





SELECT 
PRF.nm_Professor AS [Nome do Docente], 
TEL.ds_Telefone AS [Nº Telefônico],
DSC.nm_Disciplina AS Disciplina
FROM Professor AS PRF
INNER JOIN Telefone AS TEL 
ON PRF.cd_Professor = TEL.cd_Professor
RIGHT JOIN Disciplina AS DSC
ON PRF.cd_Disciplina = DSC.cd_Disciplina


O resultado será esse:




Bom vejamos então, "Nome do Docente", "Nº Telefônico" e "Disciplina". Agora analise os dados. Na coluna "Nome do Docente", existem alguns campos que retornaram NULL, assim como em "Nº Telefone", mas isso em nenhum momento aconteceu com "Disciplina". Por que isso?
Vamos entender então como funciona o right join. Quando a busca pede que recupere todos os professores que possuem telefone ela o faz. Porém o que fizemos de diferente foi exigir que todas as disciplinas fossem recuperadas, nem todas possuem professores que a lecionem. Nesse caso a matéria e apresentada sem nenhum docente. Dê uma olhada na tabela de Professores. Repare que são 21 registros:



E nem todos aparecem, na consulta que fizemos. No entanto na tabela de disciplinas:


Agora veja a consulta que montamos mais o select da tabela disciplinas. Repare que as disciplinas que são apresentadas na tabela ordenamo resultado da consulta. Isso porque foi dado preferência aos dados da tabela disciplina. 

A syntax:

SELECT Coluna(s)
FROM Tabela_Tal
RIGHT JOIN Outra_tabela
ON Tabela_Tal.ColunaCódigo = Outra_tabela.ColunaCódigo



Para quem gosta de tutoriais, indico pra você esse link. Você precisa entender um pouco de inglês se quiser entender o que o narrador diz, mas só pelas imagens muito se dá pra entender.


Obrigada. Se tiverem alguma dúvida ou ideia para um novo tópico, por favor me contatem.

segunda-feira, 9 de janeiro de 2012

Como faço uma Trigger de Inserção e Update??

Para você, querido internauta:


"Trigger -- Quero fazer uma!"
"Trigger para Delete"


O bom disso tudo é que se você por um acaso tiver dúvidas mais profundas você pode consultar nesses tópicos ou deixar um post no meu mural no face "Nathália Bielski Tavares". Se eu por um acaso não souber responder sua pergunta, vou procurar buscar a resposta.. Não é porque não sei que não possa aprender ;)


Agora continuaremos com o Tópico. Como imagino que você já tenha uma boa base e precise apenas tirar umas dúvidas, vou apenas lançar o ambiente e explicar basicamente os passos da Trigger.


O ambiente (se você estiver acompanhando os tópicos poderá usar o mesmo ambiente dos anteriores se não..):


CREATE DATABASE bd_Trigger
USE bd_Trigger 



CREATE TABLE ProdutosExcluidos(
cd_Produto INT NULL,
ds_produto VARCHAR(50) NULL,
dt_exclusao SMALLDATETIME NULL)
CREATE TABLE Produto(
cd_Produto INT NOT NULL,
ds_Produto VARCHAR(50) NOT NULL,
vl_Produto MONEY NULL,
qt_Estoque INT NULL,
qt_Estoquemin INT NULL,
 CONSTRAINT PK_Produto PRIMARY KEY CLUSTERED(cd_Produto))

 CREATE TABLE PedidoCompra(
cd_PedidoCompra INT IDENTITY NOT NULL,
cd_Produto INT NOT NULL,
dt_Solicitacao SMALLDATETIME  NOT NULL, 
qt_Compra INT NOT NULL,
 CONSTRAINT PK_PedidoCompra PRIMARY KEY CLUSTERED (cd_PedidoCompra))

 CREATE TABLE LogPreco(
cd_LogPreco INT IDENTITY NOT NULL,
dt_Alteracao SMALLDATETIME NOT NULL,
cd_Produto INT NOT NULL,
vl_ProdutoAntigo MONEY NOT NULL,
vl_ProdutoNovo MONEY NOT NULL,
 CONSTRAINT PK_LogPreco PRIMARY KEY CLUSTERED (cd_LogPreco))

ALTER TABLE LogPreco
ADD CONSTRAINT fk_LogPreco
FOREIGN KEY (cd_Produto)
REFERENCES Produto (cd_Produto)


ALTER TABLE PedidoCompra
ADD CONSTRAINT fk_PedidoCompra
FOREIGN KEY (cd_Produto)
REFERENCES Produto (cd_Produto)


INSERT Produto(cd_Produtods_Produto ,  vl_Produto ,qt_Estoque, qt_EstoqueminVALUES  ( 1 , 'Prego' , 1.0000 , 25 , 10) 
INSERT Produto ( cd_Produto , ds_Produto , vl_Produto , qt_Estoque, qt_Estoquemin  VALUES  ( 2 , 'Martelo' , 50.0000, 30 , 15) 
INSERT Produto ( cd_Produto , ds_Produto , vl_Produto , qt_Estoque, qt_Estoquemin  VALUES  ( 3 , 'Parafuso' , 2.0000 ,  10 ,  5) 
INSERT Produto ( cd_Produto , ds_Produto ,vl_Produto , qt_Estoque, qt_Estoquemin   VALUES  ( 4 , 'Chave de Fenda' , 25.0000 , 15 , 10)


Após esses procedimentos faça os seguintes testes:


SELECT * FROM Produto
SELECT * FROM PedidoCompra


Esse deve ser o resultado:



Repare que uma das tabelas você encontra os 5 itens cadastrados corretamente enquanto a outra está totalmente vazia. Perfeito. Como acredito que já conheçam a sintaxe de uma trigger, irei explicar apenas as partes que apareçam como novidade, no caso já na primeira linha posso dizer que como desejo fazer uma trigger para insert e update simplesmente declaro que é "para os dois".

CREATE TRIGGER tr_PedidoCompra ON Produto FOR INSERT,UPDATE
AS

DECLARE @cd_produto INT,@dt_solicitacao SMALLDATETIMA,@qt_compra INT,@qt_estoque INT,
@qt_estoquemin INT

--Repare que tomo valores da tabela inserted apenas. Isso porque estamos trabalhando com um --log para insert e update, lembrando que não existe uma tabela que tão pouco se chame --"updated". Lembresse toda vez que você faz um update você está trocando o antigo --valor por um novo, inserindo um novo.
SELECT @qt_estoque=qt_Estoque , @qt_estoquemin = qt_EstoqueMin ,  @cd_produto = cd_Produto , @qt_compra = qt_EstoqueMin qt_Estoque FROM inserted

--O que nós estamos tentando fazer aqui é simplesmente avaliar: Quando eu inserir na tabela de
--produtos ou alterar um produto já existente na tabela vai existir uma analise entre os campos
--EstoqueMin e Estoque. O dado do campo de Estoque desse tal produto está abaixo do dado do
--EstoqueMin...


IF(@qt_estoque < @qt_estoquemin)
BEGIN

--então um log será enviado para a tabela PedidoCompra.

INSERT INTO PedidoCompra VALUES ( @cd_produto , GETDATE ( ) , @qt_compra)
END

Agora eu gostaria que gentilmente você deletasse esse produto utilize este código:

DELETE Produto WHERE cd_Produto=5

Resultado:


Agora vamos fazer dois teste mas com insert, veja o que acontece:


INSERT INTO Produto VALUES(7,'Serra' , 17 , 3 , 5)
INSERT INTO  Produto  VALUES ( 8 , 'Machado' , 20 , 3 , 7)


Nesse momento você vê que quatro linhas são afetadas. Duas delas são da tabela produto, obvio já que nela foram realizados os dois insert. Mas e as duas outras? Teste isso e veja:

SELECT * FROM PedidoCompra



Sim duas linhas foram inseridas nessa tabela, e isso é bom, significa que a trigger funcionou e que é hora do comerciante fazer compras.

Agora vamos testar com update:

UPDATE Produto SET qt_Estoque= 7 WHERE cd_Produto  1
UPDATE Produto SET qt_Estoque 4 WHERE cd_Produto   3

Interessante:


Agora o teste final:

SELECT * FROM PedidoCompra





E as inserções automáticas foram bem sucedidas.

Espero que tenham aprendido muito e agradeço sua visita.