Обеспечение целостности данных только после завершения транзакции

#sql #sql-server #tsql #unique-constraint

#sql #sql-сервер #tsql #уникальное ограничение

Вопрос:

У меня есть схема следующим образом:

 CounterParty  PersonalInfo  TwoRows
============  ============  =======
Id            Id            Id
Type          Name          
              Surname   
 

Таблицы CounterParty и PersonalInfo находятся в отношениях один к одному.

Затем я получил представление, содержащее контрагента

 create view V_CHK_CounterParty_Name
with schemabinding
as
select c.Id from CounterParty c
join PersonalInfo p on p.Id = c.Id and p.Name is null and
c.Type = 2
cross join TwoRows
 

и уникальный ключ в его столбце Id, где, если выбрана строка, она будет дублироваться из-за перекрестного соединения и приведет к нарушению уникального ключа.

Я также получил другое представление, очень похожее, но оно проверяет, имеет ли фамилия значение null и тип = 1. Он называется V_CHK_CounterParty_Surname

Проблема

Когда я пытаюсь изменить запись с Type = 1 на 2 и стереть фамилию и заполнить имя, я нарушаю ограничение UK. Это происходит потому, что мне нужно обновить сначала данные одной таблицы, а затем другие, что приводит к ошибке. Могу ли я обработать это обновление из двух таблиц как один запрос? В некоторых случаях заполняются фамилия и имя, тогда проблем нет.

Есть ли способ обеспечить целостность данных на уровне базы данных даже при совместном использовании таких таблиц?

РЕДАКТИРОВАТЬ: я предоставлю некоторые данные, чтобы лучше проиллюстрировать ошибку.

Данные перед транзакцией:

 CounterParty          PersonalInfo       TwoRows
============          ============       =======
Id: 4444              Id: 5879           Id: 1
Type: 1               Name: NULL         =======
IdPersonalInfo: 5879  Surname: "Cane"    Id: 2
 

Данные, которые я хотел бы получить после транзакции:

 CounterParty          PersonalInfo       TwoRows
============          ============       =======
Id: 4444              Id: 5879           Id: 1
Type: 2               Name: "John"       =======
IdPersonalInfo: 5879  Surname: NULL      Id: 2
 

Как я пытаюсь это сделать: я на самом деле использую entity framework, но выполняемый SQL:

 BEGIN TRAN;

UPDATE CounterParty
SET Type = 2
WHERE Id = 4444;

/*UK gets violated, because we are now in state where data projects into the view, gets cross-joined with TwoRows and immediately violate UK constraint.*/

UPDATE PersonalInfo
SET Surname = NULL, Name = 'John'
WHERE Id = 5879;

COMMIT;
 

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

Определение уникального ключа:

 CREATE UNIQUE CLUSTERED INDEX UK_V_CHK_CounterParty_Name ON
V_CHK_CounterParty_Name
( Id ASC )
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, 
IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = 
ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
 

И еще один, называемый UK_V_CHK_CounterParty_Surname, который является точно таким же, но работает с V_CHK_CounterParty_Surname.

Комментарии:

1. Можете ли вы добавить некоторые образцы данных (в виде форматированного текста) до и после, которые иллюстрируют эту проблему. А также предоставьте определение вашего уникального ограничения.

2. Поскольку они имеют отношение «один к одному», вам было бы лучше переместить столбец типа контрагента в PersonalInfo — тогда вы могли бы просто добавить простые ограничения проверки для обеспечения того, чтобы не было строк, где имя равно нулю, а тип контрагента равен 2, и чтобы не было строк, где фамилия равна нулю, а тип контрагента равен 1

3. @MartinSmith Таблица PersonalInfo используется многими другими таблицами, которые совместно используют поля Имя, фамилия и многие другие. Все находятся в отношениях один к одному. Отредактированный пост и, надеюсь, сделал его более понятным.

4. Некоторые системы баз данных поддерживают отложенную проверку ограничений, что допускает временные нарушения при условии, что они устраняются до фиксации транзакции. SQL Server не является одним из них.

5. Означает ли это, что я должен обратиться, например, к add extra value, которое указывает, что значения редактируются, и представления должны игнорировать такие данные?