•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
• Para saber mais... (create database)
[Link]
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 ] ] [Link]
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 [Link]
• ç, Ç, á, é, í, â, ê,ã ...
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 [Link] (CustomerID),
2 CONSTRAINT FK_GeneralAdvices_Suppliers
FOREIGN KEY (Advicer) REFERENCES [Link] (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 [Link] (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 [Link] (CustomerID),
CONSTRAINT FK_CustomerAdvicesSuppliers FOREIGN KEY (SupplierID) REFERENCES [Link] (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 : ([Link]
table?view=sql-server-ver16) Não funciona para nossa coluna ResponseDate, por quê!?
Triggers: ([Link]
•
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
[Link]
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:[Link]
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
[Link]
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
[Link]
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 [Link], CustomerID, [Link], 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 [Link], CustomerID, [Link], ProductID
FROM Orders O CROSS JOIN [Order Details] OD
WHERE [Link] = [Link]
Incluindo a restrição [Link] = [Link] 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 [Link], CustomerID, [Link], ProductID
FROM Orders O INNER JOIN [Order Details] OD
ON [Link] = [Link]
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 [Link] = [Link] vendidos em
INNER JOIN Orders O ON [Link] = [Link] 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 [Link] 25/07/1996
FROM Products P INNER JOIN [Order Details] OD ON [Link] = [Link]
INNER JOIN Orders O ON [Link] = [Link]
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 [Link] = [Link] AND
OrderDate >= '25/07/1996' AND OrderDate < '26/07/1996’
RIGHT OUTER JOIN Products P ON [Link] = [Link]
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 [Link] = [Link] 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 [Link] = [Link]
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 [Link] = [Link]
Resultado diferente! Por quê?
RIGHT OUTER JOIN Products P ON [Link] = [Link] 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 [Link] = [Link]
RIGHT OUTER JOIN Products P ON [Link] = [Link] 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