2009-06-15 4 views
32

Поддерживаются ли в любых версиях SQL Server отложенные ограничения (DC)?Отложенные ограничения в SQL Server

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

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

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

+0

Вы в основном задаете вариант [этого вопроса] (http://stackoverflow.com/questions/998267/deferred-constraint-checking)? –

ответ

9

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

+0

У нас есть ORM-уровень в нашей бизнес-системе, который использует DC в Oracle, который может потребоваться для подключения к SQL Server. Несомненно, DC, похоже, не поддерживается, что усложняет усилия по переносу реализации. В частности, сеть записей изменений должна обрабатываться в очень специфическом (и сложном для вычисления порядке), чтобы избежать нарушения каких-либо ограничений RI. Просто ищите способ избежать этого. – LBushkin

+2

Я написал небольшое сообщение об этом некоторое время назад. В основном вы сохраняете черновики строк во всех ваших таблицах, чем вы помечаете их как готовые, после чего включается RI. Google вверх «Подражание отложенным ограничениям с использованием устойчивых вычисляемых столбцов». –

3

Видимо, нет.

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

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

+1

Ссылка кажется нарушенной? –

3

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

21

OT: Там будут ИМХО довольно много вещей, SQL Server не поддерживает, но будет иметь смысл в корпоративной среде:

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

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

+2

Теперь вы можете иметь уникальные индексы, содержащие нули, используя отфильтрованный индекс. – LMK

1

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

  1. Удалить все внешние ключевые ссылки, определенные вашего изменение набора, как удаляется, то есть набор соответствующего внешних ключей столбцов NULL, или , для отношений, использующих таблицы сопоставления, DELETE записи из таблиц сопоставления в зависимости от ситуации.
  2. Удалить все объекты, определенные как «удаленный» по вашему изменению устанавливает
  3. Создать все новые объекты в наборе изменений, но еще не установлены столбцы внешнего ключа
  4. Обновить все «примитивные» изменения стоимости на любых обновленных объектах набор изменений, то есть не обновлять столбцы внешнего ключа
  5. Установить значения столбца внешнего ключа, как определено в вашем наборе изменений.
  6. отображение таблицы отображения для отображения Добавить таблицы на основе отношений
  7. Зафиксировать

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

+0

Или используйте хранимую процедуру и подключите ее к установке() Update() этого объекта в ORM (Entity Framework и Linq to SQL), это позволяет http://stackoverflow.com/questions/5346601/stored-procedures-and- ORMs) –

1

Существует метод, позволяющий обойти отсутствующее ограничение отложенного ограничения при определенных условиях (по состоянию на январь 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 является подходящим типом данных для суррогатного ключа. Предполагается, что значение для суррогатного ключа назначается СУРБД во время операции INSERT (т. Е. IDENTITY).

Вариант использования - сохранить «последнюю» версию объекта 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 заявления завершает все манипуляции с данными перед проверкой ограничений.

Смежные вопросы