2010-08-12 5 views
2

У меня есть 2 таблицы. Ниже приведены только обезжиренные версии этих таблиц.Как исправить эту проблему с хранимой процедурой

TableA 
Id <pk> incrementing 
Name varchar(50) 

TableB 
TableAId <pk> non incrementing 
Name varchar(50) 

Теперь эти таблицы имеют отношение друг к другу.

Сценарий

Пользователь 1 приходит на мой сайт и делает какие-то действия (в данном случае добавляет строки в таблице A). Поэтому я использую SqlBulkCopy для всех этих данных в таблице A.

Однако мне нужно добавить данные также в таблицу B, но я не знаю вновь созданного Идентификатора из таблицы A, поскольку SQLBulkCopy не вернет их.

Так что я имею в виду иметь хранимую процедуру, которая находит все идентификаторы, которые не существуют в таблице B, а затем вставьте их в.

INSERT INTO TableB (TableAId , Name) 
SELECT Id,Name FROM TableA as tableA 
WHERE not exists(...) 

Однако это приходит с проблемой. Пользователь в любое время может удалить что-то из TableB, поэтому, если пользователь удаляет строку, а затем появляется другой пользователь, или даже тот же пользователь приходит и делает что-то в таблице. Моя хранимая процедура вернет эту удаленную строку в таблицу B. Поскольку он все еще будет существовать в таблице A, но не в таблице B и, таким образом, будет удовлетворять условию хранимой процедуры.

Итак, есть ли лучший способ справиться с двумя таблицами, которые необходимо обновить при использовании массовой вставки?

+1

Я уверен, что вся суть RDMS заключается в том, чтобы избежать проблем взаимного исключения и обновления при наличии нескольких параллельных соединений.Я не эксперт по БД и не играю по телевизору, но, насколько мне известно, есть конструкции, которые вы можете использовать, чтобы сделать запрос «атомарным». –

+0

@San Jacinto: правильно, но SQLBulkCopy - это сложность. Даже тогда более поздние записи не могут отличить, какие строки принадлежат им, из предыдущих записей с пробелами в B. – gbn

ответ

3

SqlBulkCopy усложняет это так, я бы рассмотреть возможность использования промежуточной таблицы и OUTPUT clause

Например, в смеси клиент псевдокоде и SQL

create SQLConnection 

Create #temptable 
Bulkcopy to #temptable 

Call proc on same SQLConnection 

proc: 
    INSERT tableA (..) 
    OUTPUT INSERTED.key, .. INTO TableB 
    SELECT .. FROM #temptable 

close connection 

Примечания:

  • соблазнительные будут локальными для соединения и будут изолированы

  • пишет A и B, будет атомарным
  • , перекрывая или более поздние записи, не заботятся о том, что произойдет позже в A и B
  • , подчеркивая последнюю точку, A и B будут только когда-либо заполняться из набора строк в # TempTable

Альтернатива:

Добавить еще один столбец а и в называется SessionID и использовать его для идентификации пакетов строк.

1

Одним из вариантов было бы использовать выходной пункт SQL Servers:

INSERT YourTable (name) 
OUTPUT INSERTED.* 
VALUES ('NewName') 

Это вернет id, name вставленных строк клиенту, так что вы можете использовать их в операции вставки для второй таблицы.

+0

Вот почему я сказал, что SQLBulkCOpy усложняет это: нет предложения OUTPUT ... – gbn

1

Как альтернативное решение, вы можете использовать database triggers для обновления второй таблицы.

+0

Простой, но вам нужно указать [ триггеры запуска] [http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopyoptions.aspx], которым могут потребоваться права DDL – gbn

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