Criar e gerenciar relacionamentos de chave externa

Nesta página, descrevemos como gerenciar relações de chave externa no banco de dados.

Uma chave externa é uma coluna compartilhada entre tabelas para estabelecer um link entre dados relacionados. Quando você usa uma chave externa, o Spanner garante que essa relação seja mantida.

O diagrama a seguir mostra um esquema de banco de dados básico em que os dados de uma tabela têm uma relação com os dados de outra.

Exemplo de esquema de banco de dados mostrando relações de chave externa entre tabelas.

Figura 1. Diagrama de um esquema de banco de dados de processamento de pedidos

Há três tabelas no esquema mostrado na Figura 1:

  • A tabela Customers registra os nomes de cada cliente.
  • As tabelas Orders registram todos os pedidos feitos.
  • A tabela Products armazena as informações de cada produto.

Há duas relações de chave externa entre essas tabelas:

  • Um relacionamento de chave externa é definido entre a tabela Orders e a tabela Customers para garantir que um pedido não seja criado a menos que haja um cliente correspondente.

  • Uma relação de chave externa entre a tabela Orders e a tabela Products garante que não seja possível criar um pedido para um produto que não existe.

Usando o esquema anterior como exemplo, este tópico discute as instruções da linguagem de definição de dados (DDL) CONSTRAINT que podem ser usadas para gerenciar relações entre tabelas em um banco de dados.

Por padrão, todas as chaves estrangeiras no Spanner são chaves estrangeiras aplicadas, que aplicam a integridade referencial. No Spanner, você também pode usar chaves estrangeiras informativas, que não validam nem aplicam a integridade referencial. Para mais informações, consulte Comparação de chaves externas e Escolher qual tipo de chave externa usar. Quando não especificado, as chaves estrangeiras nos exemplos desta página são chaves estrangeiras aplicadas.

Adicionar uma chave externa a uma nova tabela

Suponha que você tenha criado uma tabela Customers no banco de dados básico de pedidos de produtos. Agora, você precisa de uma tabela Orders para armazenar informações sobre os pedidos que os clientes fazem. Para garantir que todos os pedidos sejam válidos, não permita que o sistema insira linhas na tabela Orders, a menos que haja também uma entrada correspondente na tabela Customers. Portanto, você precisa de uma chave externa aplicada para estabelecer uma relação entre as duas tabelas. Uma opção é adicionar uma coluna CustomerID à nova tabela e usá-la como chave externa para criar uma relação com a coluna CustomerID na tabela Customers.

Ao criar uma tabela com uma chave externa, você usa REFERENCE para estabelecer uma relação com outra tabela. A tabela que contém a instrução REFERENCE é chamada de tabela de referência. A tabela nomeada na instrução REFERENCE é a tabela referenciada. A coluna nomeada na instrução REFERENCE é chamada de coluna de referência.

O exemplo a seguir mostra como usar a instrução DDL CREATE TABLE para criar a tabela Orders com uma restrição de chave externa que faz referência a CustomerID na tabela Customers.

GoogleSQL

CREATE TABLE Orders (
OrderID INT64 NOT NULL,
CustomerID INT64 NOT NULL,
Quantity INT64 NOT NULL,
ProductID INT64 NOT NULL,
CONSTRAINT FK_CustomerOrder FOREIGN KEY (CustomerID) REFERENCES Customers (CustomerID)
) PRIMARY KEY (OrderID);

PostgreSQL

CREATE TABLE Orders (
OrderID BIGINT NOT NULL,
CustomerID BIGINT NOT NULL,
Quantity BIGINT NOT NULL,
ProductID BIGINT NOT NULL,
CONSTRAINT FK_CustomerOrder FOREIGN KEY (CustomerID) REFERENCES Customers (CustomerID),
PRIMARY KEY (OrderID)
);

A instrução anterior contém uma cláusula CONSTRAINT com as seguintes características:

  • O uso da sintaxe CONSTRAINT para nomear uma restrição, facilitando a remoção da tabela usando o nome escolhido.

  • A restrição tem o nome FK_CustomerOrder. Os nomes das restrições têm escopo no esquema e precisam ser exclusivos dentro dele.

  • A tabela Orders, em que você define a restrição, é a tabela de referência. A tabela Customers é a tabela referenciada.

  • A coluna de referência na tabela de referência é CustomerID. Ela faz referência ao campo CustomerID na tabela Customers. Se alguém tentar inserir uma linha em Orders com um CustomerID que não existe em Customers, a inserção vai falhar.

O exemplo a seguir mostra uma instrução de criação de tabela alternativa. Aqui, a restrição de chave externa é definida sem um nome. Quando você usa essa sintaxe, o Spanner gera um nome para você. Para descobrir os nomes de todas as chaves externas, consulte Exibir propriedades de uma relação de chave externa.

GoogleSQL

CREATE TABLE Orders (
OrderID INT64 NOT NULL,
CustomerID INT64 NOT NULL,
ProductID INT64 NOT NULL,
FOREIGN KEY (CustomerID) REFERENCES Customers (CustomerID)
) PRIMARY KEY (OrderID);

PostgreSQL

CREATE TABLE Orders (
OrderID BIGINT NOT NULL,
CustomerID BIGINT NOT NULL,
Quantity BIGINT NOT NULL,
ProductID BIGINT NOT NULL,
FOREIGN KEY (CustomerID) REFERENCES Customers (CustomerID),
PRIMARY KEY (OrderID)
);

Adicionar uma chave estrangeira a uma tabela atual

Você também quer garantir que os clientes só possam pedir produtos que existem. Se a tabela tiver restrições, remova todas elas. No Spanner, todas as restrições aplicadas em uma tabela precisam ser implementadas ao mesmo tempo em uma única instrução DDL em lote.

Se a tabela não tiver restrições, use a instrução DDL ALTER TABLE para adicionar uma restrição de chave externa aplicada à tabela Orders, conforme mostrado no exemplo a seguir:

ALTER TABLE Orders
  ADD CONSTRAINT DB_ProductOrder FOREIGN KEY (ProductID) REFERENCES Products (ProductID);

A coluna de referência em Orders é ProductID e faz referência à coluna ProductID em Products. Se você estiver bem com o Spanner nomeando essas restrições para você, use a seguinte sintaxe:

ALTER TABLE Orders
  ADD FOREIGN KEY (ProductID) REFERENCES Products (ProductID);

Adicionar uma chave externa com uma ação de exclusão a uma nova tabela

Lembre-se do exemplo anterior em que você tem uma tabela Customers em um banco de dados de pedidos de produtos que precisa de uma tabela Orders. Você quer adicionar uma restrição de chave externa que faça referência à tabela Customers. No entanto, você quer garantir que, quando excluir um registro de cliente no futuro, o Spanner também exclua todos os pedidos desse cliente. Nesse caso, use a ação ON DELETE CASCADE com a restrição de chave externa.

A instrução DDL CREATE TABLE a seguir para a tabela Orders inclui a restrição de chave externa que faz referência à tabela Customers com uma ação ON DELETE CASCADE.

GoogleSQL

CREATE TABLE Orders (
OrderID INT64 NOT NULL,
CustomerID INT64 NOT NULL,
Quantity INT64 NOT NULL,
ProductID INT64 NOT NULL,
CONSTRAINT FK_CustomerOrder FOREIGN KEY (CustomerID)
  REFERENCES Customers (CustomerID) ON DELETE CASCADE
) PRIMARY KEY (OrderID);

PostgreSQL

CREATE TABLE Orders (
OrderID BIGINT NOT NULL,
CustomerID BIGINT NOT NULL,
Quantity BIGINT NOT NULL,
ProductID BIGINT NOT NULL,
FOREIGN KEY (CustomerID)
  REFERENCES Customers (CustomerID) ON DELETE CASCADE,
PRIMARY KEY (OrderID)
);

A instrução anterior contém uma restrição de chave externa com uma cláusula ON DELETE CASCADE. A coluna CustomerID é uma chave externa que faz referência ao campo CustomerID na tabela Customers. Isso significa que cada valor CustomerID na tabela Orders também precisa existir na tabela Customers. Se alguém tentar excluir uma linha da tabela Customers, todas as linhas da tabela Orders que fazem referência ao valor CustomerID excluído também serão excluídas na mesma transação.