Ограничения на кромках
применимо к: SQL Server 2019 (15.x) и более поздним версиям
Базе данных SQL Azure
Управляемому экземпляру SQL Azure
базе данных SQL в Microsoft Fabric
Ограничения пограничных вычислений можно использовать для обеспечения целостности данных и конкретной семантики в пограничных таблицах в базе данных графов SQL Server.
Ограничения на ребра
По умолчанию таблицы ребер не применяют никаких правил для конечных точек ребра. То есть ребро в базе данных графа может соединить любой узел с другим, независимо от типа.
Graph SQL поддерживает ограничения ребер, позволяющие пользователям добавлять ограничения к таблицам ребер, тем самым принудительно применяя определенную семантику и сохраняя целостность данных. При добавлении нового ребра в таблицу ребер с ограничениями для ребер ядро СУБД обеспечивает, что узлы, которые ребро пытается подключить, существуют в соответствующих таблицах узлов. Также обеспечивается, что узел не может быть удалён, если какое-либо ребро ссылается на этот узел.
Условия ограничения для ребер
Отдельное ограничение ребра состоит из одного или нескольких ограничительных условий для ребер.
CONSTRAINT constraint_name CONNECTION (cause1[, clause2...])
- Предложение ограничения ребер — это пара имен таблиц узлов, разделенная ключевым словом
TO
. - Первое имя таблицы в предложении ограничения ребер — это имя таблицы узла FROM для отношения ребер.
- Второе имя таблицы в предложении ограничения ребер — это имя таблицы узла TO для отношения ребер.
- То есть пара имен таблиц обозначает направление отношения ребер.
- Как упоминалось ранее, ограничение ребра может содержать одну или несколько клауз ограничения ребер.
Несколько ограничений и условий
- Несколько ограничений, касающихся ребер, определенных для одной и той же таблицы ребер, применяются с помощью оператора
AND
. - В пределах одного ограничения ребер несколько клауз применяются с оператором
OR
.
Рассмотрим узлы Supplier
и Customer
в вашем графе. Каждый из них может быть связан с узлом Product
через единую общую таблицу ребер: bought
. Таблица ребер bought
поддерживает отношения типов Customer-(bought)->Product
и Supplier-(bought)->Product
. Этого можно достичь с помощью одного ограничения на ребро с несколькими условиями этого ограничения.
Примеры
CONSTRAINT EC_BOUGHT CONNECTION (Customer TO Product)
В примере выше показано одно ограничение на ребро с одним пунктом ограничения. Это ограничение поддерживает Customer-(bought)->Product
. Это значит, что допускается вставка связи между ребрами bought
, идущей из Customer
в Product
. Если вы попытаетесь вставить любое другое сочетание узлов, например, Supplier-(bought)->Product
, даже если оно может описывать допустимую связь в реальном мире, это приведет к ошибке.
CONSTRAINT EC_BOUGHT CONNECTION (Supplier TO Product, Customer TO Product)
В приведенном выше примере определяется одно ограничение ребра с двумя условиями ограничения ребра. Эти предложения ограничений позволяют ребру bought
включать отношения Supplier-(bought)->Product
или Customer-(bought)->Product
. Вставка любых других типов отношений ребер в таблицу bought
приведет к ошибке.
CONSTRAINT EC_BOUGHT1 CONNECTION (Supplier TO Product)
CONSTRAINT EC_BOUGHT2 CONNECTION (Customer TO Product)
В примере выше приведены два ограничения для одной таблицы ребер, при этом каждое ограничение ребер указывает одно предложение ограничения. В такой ситуации SQL будет разрешать только те операции вставок, которые одновременно удовлетворяют ОБЕИМ условиям ограничений ребер. Это невозможно. Не существует пары узлов, которые могут удовлетворить оба условия ограничений ребер. Такое сочетание ограничений ребер приводит к тому, что таблицу ребер невозможно использовать.
Подробное описание того, где можно использовать несколько ограничений ребер в реальном сценарии, см. в примере "Создание нового ограничения ребра в существующей таблице ребер с новым предложением ограничения ребра" далее на этой странице.
Индексы для ограничений на рёбрах
Создание граничного ограничения не создает автоматически соответствующий индекс для столбцов $from_id
и $to_id
в граничной таблице. Рекомендуется создать индексы для пары $from_id
и $to_id
вручную, если имеются запросы на поиск точек или рабочая нагрузка OLTP.
Ссылочные действия ON DELETE для ограничений ребер
Каскадные действия для ограничений ребер позволяют пользователям определять действия, которые будет предпринимать ядро СУБД, когда пользователь удаляет узлы, соединяемые указанным ребром. Можно определить следующие ссылочные действия: NO ACTION. При попытке удалить узел с подключенными ребрами ядро СУБД вызывает ошибку.
CASCADE Когда узел удаляется из базы данных, связанные ребра удаляются.
Работа с краевыми ограничениями
Ограничение границ в SQL Server можно определить с помощью Transact-SQL. Ограничение ребра можно задать только для таблицы ребер графа. Чтобы создать, удалить или изменить ограничение ребра, вам необходимо иметь разрешение ALTER для таблицы.
Создание граничных ограничений
В следующих примерах показано, как создать ограничение edge для новых или существующих таблиц.
Создание ограничения границ для новой пограничной таблицы
В следующем примере создается ограничение границ в bought
таблице edge.
-- CREATE node and edge tables
CREATE TABLE Customer
(
ID INTEGER PRIMARY KEY
,CustomerName VARCHAR(100)
)
AS NODE;
GO
CREATE TABLE Product
(
ID INTEGER PRIMARY KEY
,ProductName VARCHAR(100)
)
AS NODE;
GO
CREATE TABLE bought
(
PurchaseCount INT
,CONSTRAINT EC_BOUGHT CONNECTION (Customer TO Product) ON DELETE NO ACTION
)
AS EDGE;
Определение ссылальных действий в новой пограничной таблице
В следующем примере создается ограничение ребра в пограничной bought
таблице и определяется действие ON DELETE CASCADE со ссылкой.
-- CREATE node and edge tables
CREATE TABLE Customer
(
ID INTEGER PRIMARY KEY
,CustomerName VARCHAR(100)
)
AS NODE;
GO
CREATE TABLE Product
(
ID INTEGER PRIMARY KEY
,ProductName VARCHAR(100)
)
AS NODE;
GO
CREATE TABLE bought
(
PurchaseCount INT
,CONSTRAINT EC_BOUGHT CONNECTION (Customer TO Product) ON DELETE CASCADE
)
AS EDGE;
Добавьте ограничение на ребро в существующую таблицу ребер
В следующем примере используется ALTER TABLE для добавления ограничения графа в таблицу рёбер bought
.
-- CREATE node and edge tables
CREATE TABLE Customer
(
ID INTEGER PRIMARY KEY
, CustomerName VARCHAR(100)
)
AS NODE;
CREATE TABLE Product
(
ID INTEGER PRIMARY KEY
, ProductName VARCHAR(100)
)
AS NODE;
GO
CREATE TABLE bought
(
PurchaseCount INT
)
AS EDGE;
GO
ALTER TABLE bought ADD CONSTRAINT EC_BOUGHT1 CONNECTION (Customer TO Product);
Создайте новое ограничение ребра в существующей таблице ребер с добавлением дополнительных условий ограничения.
В следующем примере используется команда ALTER TABLE
для добавления нового ограничения кромки с дополнительными условиями ограничения на кромке в таблице кромок bought
.
-- CREATE node and edge tables
CREATE TABLE Customer
(
ID INTEGER PRIMARY KEY
, CustomerName VARCHAR(100)
)
AS NODE;
GO
CREATE TABLE Supplier
(
ID INTEGER PRIMARY KEY
, SupplierName VARCHAR(100)
)
AS NODE;
GO
CREATE TABLE Product
(
ID INTEGER PRIMARY KEY
, ProductName VARCHAR(100)
)
AS NODE;
GO
CREATE TABLE bought
(
PurchaseCount INT
, CONSTRAINT EC_BOUGHT CONNECTION (Customer TO Product)
)
AS EDGE;
-- Drop the existing edge constraint first and then create a new one.
ALTER TABLE bought DROP CONSTRAINT EC_BOUGHT;
GO
-- User ALTER TABLE to create a new edge constraint.
ALTER TABLE bought ADD CONSTRAINT EC_BOUGHT1 CONNECTION (Customer TO Product, Supplier TO Product);
В предыдущем примере в ограничении EC_BOUGHT1
есть два условия ограничения по краям: одно соединяет Customer
с Product
, а другое соединяет Supplier
с Product
. Оба этих положения применяются в дизъюнкции. То есть, заданное ребро должно удовлетворять хотя бы одному из этих двух условий, чтобы его можно было использовать в таблице ребер.
Создание нового ограничения на ребро в существующей таблице ребер с новым условием ограничения на ребро.
В следующем примере следующим образом используется команда ALTER TABLE
для добавления нового ограничения ребра с новым условием ограничения ребер в таблице ребер bought
.
-- CREATE node and edge tables
CREATE TABLE Customer
(
ID INTEGER PRIMARY KEY
, CustomerName VARCHAR(100)
)
AS NODE;
GO
CREATE TABLE Supplier
(
ID INTEGER PRIMARY KEY
, SupplierName VARCHAR(100)
)
AS NODE;
GO
CREATE TABLE Product
(
ID INTEGER PRIMARY KEY
, ProductName VARCHAR(100)
)
AS NODE;
GO
CREATE TABLE bought
(
PurchaseCount INT,
CONSTRAINT EC_BOUGHT CONNECTION (Customer TO Product)
)
AS EDGE;
GO
Опираясь на приведенный выше пример, представьте, что теперь нам нужно включить связь Supplier
с Product
с помощью таблицы ребер bought
. Вы можете попробовать добавить новое ограничение на ребро.
ALTER TABLE bought ADD CONSTRAINT EC_BOUGHT1 CONNECTION (Supplier TO Product);
Однако добавление нового ограничения edge не является правильным решением. Мы создали два отдельных ограничения края в таблице ребер bought
: EC_BOUGHT
и EC_BOUGHT1
. Оба этих ограничения имеют различные положения, касающиеся ограничения ребра. Если в таблице ребер присутствует более одного ограничения, данное ребро должно соответствовать ВСЕМ ограничениям, чтобы использоваться в таблице ребер. Так как ни одно ребро не может удовлетворить как EC_BOUGHT
, так и EC_BOUGHT1
, приведенный выше ALTER TABLE
оператор терпит неудачу, если в таблице ребер bought
есть вообще какие-либо строки.
Для успешного создания этого ограничения границы необходимо выполнить последовательность действий, как показано в этом примере.
-- First, add the desired ("super-set") constraint:
ALTER TABLE bought ADD CONSTRAINT EC_BOUGHT_NEW CONNECTION (Customer TO Product, Supplier TO Product);
GO
-- Then, drop the older edge constraint:
ALTER TABLE bought DROP CONSTRAINT EC_BOUGHT;
GO
-- If needed, you can rename the new edge constraint to match the original name:
EXECUTE sp_rename '[dbo].[EC_BOUGHT_NEW]', '[dbo].[EC_BOUGHT]';
Тот факт, что мы добавили новое ограничение "супер-набор", не удалив сначала более раннее ограничение, позволяет сделать операцию только с метаданными - не нужно проверять все существующие данные в таблице bought
, так как оно охватывает существующее ограничение.
Для того чтобы разрешить включение данного ребра в границу bought
, оно должно соответствовать хотя бы одному из условий ограничения ребер в ограничении EC_BOUGHT_NEW
. Поэтому разрешено любое ребро, которое пытается подключиться к узлам Customer
и Product
или Supplier
и Product
.
Удалите ограничения ребер
В следующем примере сначала определяется имя ограничения ребер, а затем удаляется ограничение.
-- CREATE node and edge tables
CREATE TABLE Customer
(
ID INTEGER PRIMARY KEY
, CustomerName VARCHAR(100)
)
AS NODE;
GO
CREATE TABLE Product
(
ID INTEGER PRIMARY KEY
, ProductName VARCHAR(100)
) AS NODE;
GO
CREATE TABLE bought
(
PurchaseCount INT
, CONSTRAINT EC_BOUGHT CONNECTION (Customer TO Product)
)
AS EDGE;
GO
-- Return the name of edge constraint.
SELECT name
FROM sys.edge_constraints
WHERE type = 'EC' AND parent_object_id = OBJECT_ID('bought');
GO
-- Delete the primary key constraint.
ALTER TABLE bought
DROP CONSTRAINT EC_BOUGHT;
Изменение ограничений ребер
Чтобы изменить ограничение ребра с помощью Transact-SQL, необходимо сначала удалить существующее ограничение ребра, а затем заново создать его с новым определением.
Просмотр ограничений граней
Видимость метаданных в представлениях каталога ограничена защищаемыми объектами, которыми владеет пользователь или которым пользователь получил некоторое разрешение. Дополнительные сведения см. в разделе Metadata Visibility Configuration.
Пример возвращает все ограничения ребер и их свойства для таблицы bought
в базе данных tempdb
.
-- CREATE node and edge tables
CREATE TABLE Customer
(
ID INTEGER PRIMARY KEY
, CustomerName VARCHAR(100)
)
AS NODE;
GO
CREATE TABLE Supplier
(
ID INTEGER PRIMARY KEY
, SupplierName VARCHAR(100)
)
AS NODE;
GO
CREATE TABLE Product
(
ID INTEGER PRIMARY KEY
, ProductName VARCHAR(100)
)
AS NODE;
-- CREATE edge table with edge constraints.
CREATE TABLE bought
(
PurchaseCount INT
, CONSTRAINT EC_BOUGHT CONNECTION (Customer TO Product, Supplier TO Product)
)
AS EDGE;
-- Query sys.edge_constraints and sys.edge_constraint_clauses to view
-- edge constraint properties.
SELECT
EC.name AS edge_constraint_name
, OBJECT_NAME(EC.parent_object_id) AS edge_table_name
, OBJECT_NAME(ECC.from_object_id) AS from_node_table_name
, OBJECT_NAME(ECC.to_object_id) AS to_node_table_name
, is_disabled
, is_not_trusted
FROM sys.edge_constraints EC
INNER JOIN sys.edge_constraint_clauses ECC
ON EC.object_id = ECC.object_id
WHERE EC.parent_object_id = object_id('bought');