0% acharam este documento útil (0 voto)
21 visualizações54 páginas

SQL

SQL

Enviado por

gestaolisboainfo
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
21 visualizações54 páginas

SQL

SQL

Enviado por

gestaolisboainfo
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 54












• Para saber mais... (create database)
https://learn.microsoft.com/pt-
CREATE DATABASE database_name br/sql/relational-databases/databases/create-a-
[ CONTAINMENT = { NONE | PARTIAL } ] database?view=sql-server-ver16
[ ON
[ PRIMARY ] <filespec> [ ,...n ] Para saber mais... (primary e filegroups)
[ , <filegroup> [ ,...n ] ] https://learn.microsoft.com/en-us/sql/relational-
databases/databases/database-files-and-
[ LOG ON <filespec> [ ,...n ] ]
filegroups?view=sql-server-ver16
]
[ COLLATE collation_name ]
[ WITH <option> [,...n ] ]
[;]
CREATE DATABASE db_NorthWind_Trader
ON
PRIMARY (NAME = 'db_NorthWind_Trader_data’,
FILENAME = ...\db_NorthWind_Trader_data.mdf’,
SIZE = 10 MB,
MAXSIZE = 100 MB,
FILEGROWTH = 5 % )
LOG ON (NAME = 'db_NorthWind_Trader_log’,
FILENAME = ...\db_NorthWind_Trader_data.ldf’,
SIZE = 10 MB,
MAXSIZE = 100 MB,
FILEGROWTH = 5 %)

COLLATE Latin1_General_CI_AI;
COLLATE Latin1_General_CI_AI;
Insensível ao acento (não diferencia o
caractere acentuado do não
acentuado – e.g., á e a são
considerados iguais do ponto de vista
de comparação)

CI:
Insensível ao caso (não diferencia
maiúsculas de minúsculas)

Latin1_General:
• Alfabeto Latino
Para saber mais... (collate)
• ISO-8859-1 https://learn.microsoft.com/en-us/sql/t-
• ç, Ç, á, é, í, â, ê,ã ...
sql/statements/collations?view=sql-server-
ver16
CREATE TABLE { database_name.schema_name.table_name
| schema_name.table_name
| table_name }
(
{ <column_definition> }
[ ,... n ]
[CONSTRAINT <constraint_name> PRIMARY KEY [CLUSTERED | NONCLUSTERED]
( <columns_names> ),]
[CONSTRAINT <constraint_name> FOREIGN KEY
(<reference_columnn_names>) REFERENCES <referenced_table>(<referenced_columns>),]
[CONSTRAINT <constraint_name> CHECK (<logic_expression>)]
)[;]

<column_definition> ::= column_name data_type [NULL | NOT NULL]


[PRIMARY KEY]
CREATE TABLE GeneralAdvices ( (1) Define GeneralAdviceID como chave
GeneralAdviceID int NOT NULL , primária da tabela GeneralAdvices
Advice nvarchar(200) NOT NULL ,
AdviceResponse nvarchar(1000) NULL ,
AdviceStartDate datetime NOT NULL,
AdviceEndDate datetime NULL,
AdviceCreator nchar(5) NULL,
Advicer int NOT NULL,
1 CONSTRAINT PK_GeneralAdvices PRIMARY KEY CLUSTERED (GeneralAdviceID),

2 CONSTRAINT FK_GeneralAdvices_Customers
FOREIGN KEY (AdviceCreator) REFERENCES dbo.Customers (CustomerID),
2 CONSTRAINT FK_GeneralAdvices_Suppliers
FOREIGN KEY (Advicer) REFERENCES dbo.Suppliers (SupplierID),
3 CONSTRAINT CK_Dates
CHECK (AdviceEndDate IS NULL OR AdviceEndDate > AdviceStartDate))
(2) Define que o criador do aviso (cliente), se existir (3) Define uma restrição de domínio (no dado), a
algum, deve ser um Cliente, observe que o campo data de término da validade do aviso deve estar
AdviceCreator não é obrigatório indefinida ou ser menor que data de início
CREATE TABLE Employees (
EmployeeID int IDENTITY (1, 1) NOT NULL , (1) Define EmployeeID como chave primária
LastName nvarchar (20) NOT NULL , da tabela Employees
FirstName nvarchar (10) NOT NULL ,
Title nvarchar (30) NULL ,
TitleOfCourtesy nvarchar (25) NULL ,
BirthDate datetime NULL , (2) Define que o valor de ReportsTo é uma chave estrangeira a
HireDate datetime NULL , referenciando a própria tabela Employees. Isto indica que ReportsTo
pode ser um Employee (Funcionário) ou nada (por permitir nulo)
Address nvarchar (60) NULL ,
City nvarchar (15) NULL ,
Region nvarchar (15) NULL ,
PostalCode nvarchar (10) NULL ,
(3) Define uma restrição de domínio (no
Country nvarchar (15) NULL ,
dado), a data BirthDate tem que ser menor
HomePhone nvarchar (24) NULL , que a data corrente
Extension nvarchar (4) NULL ,
Photo image NULL ,
Notes ntext NULL ,
ReportsTo int NULL ,
PhotoPath nvarchar (255) NULL ,
1 CONSTRAINT PK_Employees PRIMARY KEY CLUSTERED (EmployeeID),
CONSTRAINT FK_Employees_Employees
FOREIGN KEY (ReportsTo) REFERENCES dbo.Employees (EmployeeID), 2
3 CONSTRAINT CK_Birthdate CHECK (BirthDate < getdate())
)
Vamos criar uma tabela para registrar sugestões dos cliente para fornecedores do
produto. A tabela deverá conter:
• o cliente (chave estrangeira para a tabela Customers)
• o fornecedor para quem a sugestão será enviada
• a data do registro da sugestão
• a descrição da sugestão
• a resposta dada pelo fornecedor
• a data da resposta do forncedor

O que precisamos determinar?


• o tipo dos dados
• a chave primária (possivelmente pode-se criar
um campo para este fim)
• os dados que podem ou não ser nulo
CREATE TABLE CustomerAdvices
(
CustomerAdvicesID INT NOT NULL IDENTITY(1, 1),
CustomerID nchar(5) NOT NULL,
SupplierID int NOT NULL,
Advice nvarchar(4000) NOT NULL,
AdviceDate datetime NOT NULL,
Response nvarchar(4000) NULL,
ResponseDate datetime NULL,
CONSTRAINT PK_CustomerAdvice PRIMARY KEY CLUSTERED (CustomerAdvicesID),
CONSTRAINT FK_CustomerAdvicesCustomers FOREIGN KEY (CustomerID) REFERENCES dbo.Customers (CustomerID),
CONSTRAINT FK_CustomerAdvicesSuppliers FOREIGN KEY (SupplierID) REFERENCES dbo.Suppliers (SupplierID)
)

Reflita:
Por quê as colunas Response e ResponseDate permitem “nulo”?
O registro da resposta (coluna Response) implica no registro da data de reposta, será possível registrar o valor para a data da resposta
de forma automática?

Colunas Calculadas : (https://learn.microsoft.com/en-us/sql/relational-databases/tables/specify-computed-columns-in-a-


table?view=sql-server-ver16) Não funciona para nossa coluna ResponseDate, por quê!?
Triggers: (https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql?view=sql-server-ver16)

INSERT INTO Customers (CustomerID, CompanyName, ContactName, ContactTitle, Address,


City, Region, PostalCode, Country, Phone, Fax) VALUES
('FLOJA', 'Flor de Jambu Produtos da Amazônia', 'Antônio da Silva','Sr.', 'Rua Augusta,
2000', 'São Paulo', 'SP', '01412000', 'BRAZIL', '5511667042233', NULL)

Vamos usar o comando SELECT para ver o registro realizado:

SELECT *
FROM Customers
WHERE CustomerID = 'FLOJA’

UPDATE Customers
SET Address = 'Rua Augusta, 2000, Loja 123'
WHERE CustomerID = 'FLOJA'

Vamos usar o comando SELECT para ver o registro atualizado:

O que acontece se executarmos o comando


SELECT *
sem a cláusula WHERE ?! FROM Customers
WHERE CustomerID = 'FLOJA’

DELETE Customers Cuidado!!!


WHERE CustomerID = 'FLOJA' Lembre-se da
Cláusula WHERE

Vamos usar o comando SELECT para “não” ver o registro excluído:

SELECT *
FROM Customers
WHERE CustomerID = 'FLOJA'
• →

Exemplo:

UPDATE Products
SET UnitPrice = UnitPrice - 6.0

Restrição existente na tabela Products

CONSTRAINT CK_Products_UnitPrice
CHECK (UnitPrice >= 0)

Falha para uma linha, devido a restrição, então falha para todas.

SELECT * -- todas as colunas


FROM Customers
WHERE CustomerID = 'COMMI'
-- Select sem cláusula WHERE, com especificação das colunas

SELECT CustomerID, CompanyName, Country -- projeção => especificação das colunas


FROM Customers

Sem WHERE o SELECT retorna todos


os registros da tabela
-- Select com clásula WHERE => restrição, usando expressão simples

SELECT *
FROM Products
WHERE CategoryID = 2 AND UnitPrice > 21.0
Seleção =>
Discontinued = 1 AND
UnitsInStock > 0

SELECT ProductName, UnitPrice => projeção


FROM Products
WHERE Discontinued = 1 AND UnitsInStock > 0
A

Restrição
É

Aplicada

Linha

Linha

SELECT ProductName, UnitPrice


FROM Products
WHERE Discontinued = 1 AND UnitsInStock > 0
Agora

Aplicada

Projeção

Sobre

Seleção

SELECT ProductName, UnitPrice


FROM Products
WHERE Discontinued = 1 AND UnitsInStock > 0
SELECT 1

SELECT 1, 5 - 3, 198 / 4

SELECT 1, 5 - 3, 198.0 / 4

Projeção de uma constante é a própria constante

Projeção de uma expressão é o resultado da expressão

Lembre-se que a projeção, mesmo para constante e expressões, será apresentada para cada linha que
atender a restrição (se existir uma), se não existir restrição o resultado é uma linha com os valores
constantes e resultados de expressões da projeção
-- Estamos entendidos?

SELECT 1, 5 - 3, 198.0 / 4 Qual o resultado desta consulta?


FROM Products
WHERE Discontinued = 1 AND UnitsInStock > 0
-- Ficou claro? Qual o resultado desta consulta?
SELECT 1, 5 - 3, 198.0 / 4
1. Aplicar a seleção
FROM Products 2. Aplicar a projeção sobre o resultado
Products
-- Ficou claro? Qual o resultado desta consulta?
SELECT 1, 5 - 3, 198.0 / 4
1. Aplicar a seleção
FROM Products 2. Aplicar a projeção sobre o resultado
Products
-- Uma restrição é uma expressão lógica (booleana), o resultado da avaliação de uma
expressão lógica será sempre falso ou verdadeiro
Uma expressão lógica é formada por:

1. Operadores Lógicos (binários – AND e OR, e unário -- NOT – existem outros no SQL)

2. Expressões de Comparação (expressões com >, <, <=, >=, <> ou !=)

3. Forma geral ➔ [ NOT ] <expressão de comparação> [ <operador lógico> [ NOT ] <expressão


de comparação> ]

e.g. : NOT UnitPrice > 10.0 AND UnitsInStock < 29 OR ReorderLevel > 29
-- o NOT tem a maior precedência, seguido do AND e por último o OR

NOT UnitPrice > 10.0 AND UnitsInStock < 29 OR ReorderLevel > 29

NOT UnitPrice > 10.0 → Resultado1

Resultado1 AND UnitsInStock < 29 → Resultado2

Resultado2 OR ReorderLevel > 29 → Resultado

o uso de parênteses altera a precedência


NOT UnitPrice > 10.0 AND (UnitsInStock < 29 OR ReorderLevel > 29)

NOT UnitPrice > 10.0 → Resultado1

UnitsInStock < 29 OR ReorderLevel > 29 → Resultado2

Resultado1 AND Resultado2 → Resultado

parênteses aumentam a precedência


SELECT *
FROM Products
WHERE NOT UnitPrice > 10.0 AND UnitsInStock < 29 OR ReorderLevel > 29
SELECT *
FROM Products
WHERE NOT UnitPrice > 10.0 AND (UnitsInStock < 29 OR ReorderLevel > 29)
• Intervalos, datas e NULL
• Busca por intervalos podem ser generalizadas da seguinte forma:

<nome da coluna ref> >= <primeiro valor dentro do intervalo> AND <nome da coluna ref> < <primeiro valor fora do intervalo>

e.g., selecionar os produtos com preços unitários entre 10 e 50

SELECT *
FROM Products
WHERE UnitPrice >= 10.0 AND UnitPrice < 51.0
• Intervalos, datas e NULL
• Datas são representadas como texto (usando aspas simples):
SELECT *
FROM Orders
WHERE OrderDate >= '01/07/1996' AND OrderDate < '01/08/1996’

Que intervalo de data é este? O que retorna esta consulta?

Cuidado com o formato de data!!!

Configurações de usuário – Incluindo formato de data


https://learn.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-
useroptions-transact-sql?view=sql-server-ver16
• Observe que o tipo datetime inclui a data e a hora, um valor
possível seria ’21/12/1996 13:45:00.875’

de forma geral dd/MM/yyyy hh:mm:ss.fff

dd → dia
MM → mês
YYYY → ano
hh → hora
mm → minuto
ss → segundo
fff → milisegundo

• Como você escreveria uma consulta para retornar todos


os pedidos realizados no dia 26/03/1998 ?
• Intervalos, datas e NULL
• Intervalos para campos texto :

SELECT *
FROM Products
WHERE ProductName >= 'GU' AND ProductName < 'GV’

Que intervalo é este? O que retorna esta consulta?

Consultas por padrões de texto podem ser feitas usando o operador


LIKE !!!
Configurações de usuário – Incluindo formato de data
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/like-transact-
sql?view=sql-server-ver16
• Toda expressão algébrica com NULL - sem uso de operadores especiais – resulta
em NULL (em geral, expressões com null resultam em null, mas, por exemplo, a
expressão booleana

1 = 1 OR null = 10 → resulta em ‘verdadeiro’

• NULL é tratado desconhecido e do ponto de vista de avaliação para obtenção de


resultado deve ser visto como ‘falso’, ou seja:

<qualquer valor> <comparador> null → desconhecido → será tratado como falso

10 < null → desconhecido, ’28/09/2022’ >= null → desconhecido


‘banana’ != null → desconhecido, null = null → desconhecido

https://learn.microsoft.com/pt-br/sql/t-sql/language-elements/null-and-unknown-transact-sql?view=sql-server-ver16
Expressões com NULL:

• IS NULL → verifica se uma expressão é null

SELECT * FROM Products WHERE SupplierID IS NULL

• IS NOT NULL → verifica se uma expressão é ‘diferente’ de null

SELECT * FROM Products WHERE SupplierID IS NOT NULL

• ISNULL(<expressão1>, <expressão2>) → retorna a primeira expressão não nula

SELECT *, ISNULL(UnitsOnOrder, 0) AS UnitsOnOrderNumeric


FROM Products
WHERE ProductID = 1

• COALESCE((<expressão1>, <expressão2>, ..., <expressãon>) → retorna


a primeira expressão não nula – semelhante ao ISNULL mas com mais
expressões
• Joins permitem relacionar dados de mais de uma tabela* numa consulta, existem 3
tipos de Join:

• O join sempre será aplicado de duas em duas tabela, ou seja,


o join é uma operação de uma tabela sobre outra, mas o resultado
de um join outros da mesma tabela
• CROSS JOIN

SELECT O.OrderId, CustomerID, OD.OrderID, ProductID


FROM Orders O CROSS JOIN [Order Details] OD

No produto cartesiano, a combinação dos registros, em geral, não faz


sentido.

Neste exemplo todos os pedidos foram combinados com todos os


items (do mesmo e de outros pedidos).

Veja o OrderID do Pedido e o OrderID do item com


valores diferentes.
• CROSS JOIN

SELECT O.OrderId, CustomerID, OD.OrderID, ProductID


FROM Orders O CROSS JOIN [Order Details] OD
WHERE O.OrderID = OD.OrderID

Incluindo a restrição O.OrderID = OD.OrderID o resultado é


equivalente ao INNER JOIN

Do produto cartesiano pedido x item retornamos


apenas os registros cuja o número do pedido do item
seja igual ao número do pedido em si
• INNER JOIN

SELECT O.OrderId, CustomerID, OD.OrderID, ProductID


FROM Orders O INNER JOIN [Order Details] OD
ON O.OrderID = OD.OrderID

Mesmo resultado do apresentado do slide anterior, mas agora


usando o INNER JOIN
• UNION → equivale à operação de união da teoria de conjuntos

• Sintaxe: <select ...> UNION [ALL] <select ...>

• Restrições: A lista de colunas dos dois “selects” deve ser


equivalente em relação à quantidade de colunas e os tipos de
dados

• A operação de União não traz linhas repetidas (respeita a


teoria básica de conjuntos), mas o modificador ALL faz com
que as linhas repetidas sejam mantidas no resultado final
SELECT ProductName, OrderDate Produtos
FROM Products P INNER JOIN [Order Details] OD ON P.ProductID = OD.ProductID vendidos em
INNER JOIN Orders O ON O.OrderID = OD.OrderID 25/07/1996
WHERE OrderDate >= '25/07/1996' AND OrderDate < '26/07/1996'

UNION

SELECT ProductName, NULL


FROM Products P Produtos não
WHERE ProductID NOT IN vendidos em
(SELECT P.ProductId 25/07/1996
FROM Products P INNER JOIN [Order Details] OD ON P.ProductID = OD.ProductID
INNER JOIN Orders O ON O.OrderID = OD.OrderID
WHERE OrderDate >= '25/07/1996' AND OrderDate < '26/07/1996')

Produto Vendido em 25/07/1996

Produtos não Vendidos em 25/07/1996

Sub-consultas é um
tópico para depois!!!
SELECT ProductName, OrderDate
FROM Orders O INNER JOIN [Order Details] OD
ON O.OrderID = OD.OrderID AND
OrderDate >= '25/07/1996' AND OrderDate < '26/07/1996’

RIGHT OUTER JOIN Products P ON P.ProductID = OD.ProductID

ORDER BY ProductName

Observar

• Mesmo resultado da consulta anterior usando UNION

• A aplicação do JOIN se dá da esquerda para a direita, assim

• Colocar condições que filtram o conjunto base de dados na cláusula ON

• Incluir todos os dados base da sua consulta com INNER JOIN e somente
depois aplicar o(s) OUTER(s) JOIN
SELECT ProductName, OrderDate
FROM Orders O INNER JOIN [Order Details] OD
ON O.OrderID = OD.OrderID AND Todas as vendas do dia
OrderDate >= '25/07/1996' AND OrderDate < '26/07/1996’ 25 de Julho de 1996

Todos os produtos com


RIGHT OUTER JOIN Products P ON P.ProductID = OD.ProductID
ou sem vendas no dia
25 de Julho de 1996
ORDER BY ProductName

SELECT ProductName, OrderDate


FROM Orders O INNER JOIN [Order Details] OD
Todas as vendas
ON O.OrderID = OD.OrderID

Resultado diferente! Por quê?


RIGHT OUTER JOIN Products P ON P.ProductID = OD.ProductID Todos os produtos com
ou sem vendas
WHERE OrderDate >= '25/07/1996' AND OrderDate < '26/07/1996’

ORDER BY ProductName
SELECT ProductName, OrderDate
FROM Orders O INNER JOIN [Order Details] OD
Todos as vendas
ON O.OrderID = OD.OrderID

RIGHT OUTER JOIN Products P ON P.ProductID = OD.ProductID Todos os produtos com*


ou sem vendas
WHERE OrderDate >= '25/07/1996' AND OrderDate < '26/07/1996’

ORDER BY ProductName

*Todos os produtos já foram vendidos em alguma data, mas em 25/07/1996 apenas alguns
foram vendidos mas não todos

Então os “joins” vão retornar (se aplicados sem restrição) todos os produtos com
alguma data de venda, inclusive datas diferentes de 25/07/1996

A restrição com a data vai remover os produtos que não foram vendidos em 25/07/1996

Você também pode gostar