Подтвердить что ты не робот

Отложенные ограничения в SQL Server

Используются ли в любых версиях SQL Server отложенные ограничения (DC)?

Начиная с версии 8.0 Oracle поддерживает отложенные ограничения - ограничения, которые оцениваются только при фиксации группы операторов, а не при вставке или обновлять отдельные таблицы. Отложенные ограничения отличаются от ограничений отключения/включения, поскольку ограничения по-прежнему активны - их просто оценивают позже (когда пакет выполняется).

Преимущество DC заключается в том, что они позволяют устанавливать обновления, которые по отдельности были бы незаконными для оценки, которые могут привести к действительному состоянию завершения. Примером является создание круговых ссылок в таблице между двумя строками, где каждая строка требует наличия значения. Никакая отдельная инструкция insert не передаст ограничение - но группа может.

Чтобы прояснить мою цель, я ищу, чтобы переносить реализацию ORM в С# на SQLServer - к сожалению, реализация полагается на Oracle DC, чтобы избежать вычисления вставки/обновления/удаления заказов среди строк.

4b9b3361

Ответ 1

Пока SQL Server не поддерживает их. В чем проблема, которую вы решаете?

Ответ 2

OT: Есть IMHO немало вещей, которые SQL Server не поддерживает, но имеет смысл в корпоративной среде:

  • Отложенные ограничения, упомянутые здесь
  • MARS: Почему вам нужно установить опцию для чего-то совершенно естественного?
  • Ограничения CASCADE DELETE: SQL Server допускает только один каскадный путь для данного ограничения CASCADE DELETE. Опять же, я не вижу причин, по которым не следует разрешать каскад при удалении с помощью нескольких возможных путей: в конце концов, в то время, когда он действительно выполняется, всегда будет использоваться только один путь, поэтому почему это ограничение?
  • Предотвращение параллельных транзакций в одном соединении ADO.NET.
  • Принуждение каждой команды, выполняемой в соединении, которое имеет транзакцию, выполняемую в рамках этой транзакции.
  • При создании индекса UNIQUE NULL обрабатывается так, как если бы оно было фактическим значением, и разрешалось появляться только один раз в индексе. SQL-представление NULL как "неизвестного значения", однако, указывает, что значения NULL вообще игнорируются при создании индекса...

Все эти мелочи делают многие из ссылочной целостности и транзакционных функций, которые вы ожидаете от полноразмерной RDBMS, почти бесполезной в SQL Server. Например, поскольку отложенные ограничения не поддерживаются, понятие "транзакция" как внешне согласованное подразделение работы частично отрицается, единственное жизнеспособное решение - за исключением некоторых грязных обходных решений - заключается в том, чтобы вообще не определять ограничения ссылочной целостности. Я бы ожидал, что естественное поведение транзакции заключается в том, что вы можете работать внутри нее в порядке и порядке операций, которые вам нравятся, и система будет следить за тем, чтобы она была согласованной в момент ее совершения. Подобные проблемы возникают из-за ограничения, что ограничение ссылочной целостности с ON DELETE CASCADE может быть определено только таким образом, что только одно ограничение может привести к каскадному удалению объекта. Это действительно не подходит для большинства реальных сценариев.

Ответ 3

По-видимому, нет.

Я обнаружил около пяти разных сообщений в блогах, в которых говорилось, что SQLServer (в разных версиях) не поддерживает Deferrable Constraints.

С другой стороны, я также нашел сообщение, которое пытается имитировать эту функцию, используя "сохраненные вычисленные столбцы" (прокрутите до последняя запись), но caveat emptor

Ответ 4

Похоже, что проблема заключается в том, что SQL не поддерживает то, что Date и Darwen называют "множественным назначением". Стандартным ответом SQL на это были "отложенные ограничения", которые SQL Server не поддерживает. Ограничение SQL Server FK или CHECK может быть помечено NOCHECK, но это не совсем то же самое. Подробнее см. В MSDN: ALTER TABLE (Transact-SQL).

Ответ 5

Если у вас есть собственный уровень ORM, одним из решений вашей проблемы может быть разделение обновления объекта с помощью эталонного обновления по логике вашего уровня ORM. Затем ваш ORM будет работать с транзакциями на основе изменения клиентской стороны в несколько этапов:

  • Удалить все ссылки на внешние ключи, определенные вашим набором изменений, как удаленные, т.е. установить соответствующие столбцы внешнего ключа в NULL или для отношений, использующих таблицы сопоставления, записи DELETE из таблиц сопоставления по мере необходимости.
  • Удалите все объекты, определенные как "удаленные" вашими наборами изменений.
  • Создайте все новые объекты в вашем наборе изменений, но еще не установите столбцы внешнего ключа.
  • Обновите все "примитивные" изменения значений для любых обновленных объектов в наборе изменений, т.е. не обновляйте столбцы внешнего ключа.
  • Задайте значения столбцов внешнего ключа, определенные в вашем наборе изменений.
  • Добавление сопоставлений таблицы сопоставлений для сопоставления табличных отношений
  • Фиксировать

Это должно решить вашу проблему, поскольку все ссылки на объекты существуют в любое время, когда установлено значение внешнего ключа...

Ответ 6

Существует метод, позволяющий обойти отсутствующее принуждение к отложенному ограничению при определенных условиях (по состоянию на январь 2017 года в SQL Server нет поддержки отложенных ограничений). Рассмотрим следующую схему базы данных:

Отказ от ответственности: качество схемы или прецедента не обсуждается здесь, оно приводится в качестве основного примера обходного пути

CREATE TABLE T (Id TYPE NOT NULL PRIMARY KEY, NextId TYPE NOT NULL);

ALTER TABLE T WITH CHECK ADD CONSTRAINT FK_T2T 
FOREIGN KEY (NextId) REFERENCES T (Id);

CREATE UNIQUE NONCLUSTERED INDEX UC_T ON T (NextId);

Где TYPE - это подходящий тип данных для суррогатного ключа. Предполагается, что значение для суррогатного ключа назначается СУРБД во время операции ВСТАВКИ (т.е. ИДЕНТИФИКАЦИЯ).

Вариант использования - сохранить "последнюю" версию объекта T с NextId = NULL и сохранить предыдущие версии, поддерживая односвязный список T.NextId → T.Id.

Очевидно, что данная схема подвержена проблеме с отсроченным ограничением, потому что вставка новой "последней" версии должна предшествовать обновлению старого "последнего", и в течение этого времени в базе данных будут две записи: то же значение NextId.

Теперь, если:

Тип данных первичного ключа не обязательно должен быть числовым и может быть рассчитан заранее (т.е. UNIQUEIDENTIFIER), то проблема с отложенным ограничением обойдется с использованием оператора MERGE, например:

DECLARE TABLE @MergeTable TABLE (Id UNIQUEIDENTIFIER);

DECLARE @NewLatestVersion UNIQUEIDENTIFIER = NEWID();

INSERT INTO @MergeTable (Id) VALUES (@NewLatestVersion);
INSERT INTO @MergeTable (Id) VALUES (@OldLatestVersion);

MERGE INTO T
USING @MergeTable m ON T.Id = m.Id
WHEN MATCHED THEN UPDATE SET T.NextId = @NewLatestVersion
WHEN NOT MATCHED THEN INSERT (Id) VALUES (@NewLatestVersion);

По-видимому, оператор MERGE завершает все манипуляции данными перед проверкой ограничений.