2013-07-15 6 views
2

Привет У меня есть следующая хранимая процедура, которая работает нормально, используя пользовательский тип таблицы.Обновление нескольких таблиц из пользовательской таблицы

ALTER procedure [dbo].[wl] 
@test [dbo].[testType] readonly 
as 
Begin 
merge into t_values as Target 
using @test as Source 
on Target.Id =Source.Id 
when matched then 
update set target.Num=Source.Num 
when not matched then 
insert (Id,Num) 
values (Source.Id, Source.Num); 
End 

У меня есть еще две таблицы test2 и test3, где мне нужно обновить некоторые значения из источника. Я не уверен, как я могу это сделать. В принципе, моя цель - когда согласованное условие обновляется или вставляет значения во все три таблицы из-за внешних отношений с ключевыми словами. Пожалуйста, дайте мне знать, как я могу это сделать. Спасибо

+0

Является Sql Server 2012? И почему тег C#? Даже если вы контролируете это с помощью кода C#, ваш вопрос вообще не связан с этим. – gunr2171

+0

Хотя логика с настройками обычно предпочтительнее, есть время и места для использования курсора, и это может быть одно. Курсоры иногда могут быть более удобочитаемыми и удобными для чтения. Если вам нужно всего лишь предпринять действия на нескольких строках, вы можете сделать курсор для выбора только тех конкретных строк исходной таблицы, которые объединены с вашими несколькими целевыми таблицами. Или, если вам нужно, вы можете отступить к простым старым заявлениям IF. – criticalfix

+0

@criticalfix, я должен подчеркнуть: курсоры очень медленны, когда дело доходит до большого набора данных. Выбирайте свои ситуации внимательно. – gunr2171

ответ

0

Вам нужно использовать предложение «output», чтобы захватить «ключи» вставленных строк ....... сразу после их вставки.

Вот пример ... не точное совпадение .... но показывает эту идею.

http://granadacoder.wordpress.com/2008/12/10/sqlserver20052008-output-clause-in-insertupdatedelete-statements/

EDIT:

Вот пример того, что я сделал ....... где я ввожу "лицо" (материнской компании) и некоторые адреса электронной почты (дочернего объекта). Я измельчил xml, ваша таблица данных должна быть аналогичной.

Ключ в том, что я «ревизую» (с производным предложением) ИДЕНТИФИКАЦИЯ, сгенерированная с помощью Я вставляю Person ..... но я сохраняю эту информацию в соответствии с естественным уникальным идентификатором (SSN в этом примере). Когда я вставляю адреса электронной почты, у меня есть ИДЕНТИФИКАЦИЯ вставляемого Я.

Мои #TempTables будут «реальными столами» в вашем окончательном решении. My @VariableTable - это таблица «аудита», которая собирает и хранит информацию, собранную в разделе «выход».

IF OBJECT_ID('tempdb..#DestinationPersonParentTable') IS NOT NULL 
begin 
     drop table #DestinationPersonParentTable 
end 



IF OBJECT_ID('tempdb..#DestinationEmailAddressPersonChildTable') IS NOT NULL 
begin 
     drop table #DestinationEmailAddressPersonChildTable 
end 



CREATE TABLE #DestinationPersonParentTable 
(
PersonParentSurrogateIdentityKey int not null identity (1001, 1), 
SSNNaturalKey int, 
HireDate datetime 
) 



declare @PersonOutputResultsAuditTable table 
(
SSNNaturalKey int, 
PersonParentSurrogateIdentityKeyAudit int 
) 





CREATE TABLE #DestinationEmailAddressPersonChildTable 
(
DestinationChildSurrogateIdentityKey int not null identity (3001, 1), 
PersonParentSurrogateIdentityKeyFK int, 
EmailAddressValueNaturalKey varchar(64), 
EmailAddressType int 
) 





-- Declare XML variable 

DECLARE @data XML; 

-- Element-centered XML 

SET @data = N' 
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <Person> 
     <SSN>222222222</SSN> 
     <HireDate>2002-02-02</HireDate> 
    </Person> 

    <Person> 
     <SSN>333333333</SSN> 
     <HireDate>2003-03-03</HireDate> 
    </Person> 

    <EmailAddress> 
     <SSNLink>222222222</SSNLink> 
     <EmailAddressValue>[email protected]</EmailAddressValue> 
     <EmailAddressType>1</EmailAddressType> 
    </EmailAddress> 

    <EmailAddress> 
     <SSNLink>222222222</SSNLink> 
     <EmailAddressValue>[email protected]</EmailAddressValue> 
     <EmailAddressType>2</EmailAddressType> 
    </EmailAddress> 

    <EmailAddress> 
     <SSNLink>333333333</SSNLink> 
     <EmailAddressValue>[email protected]</EmailAddressValue> 
     <EmailAddressType>1</EmailAddressType> 
    </EmailAddress> 

    <EmailAddress> 
     <SSNLink>333333333</SSNLink> 
     <EmailAddressValue>[email protected]</EmailAddressValue> 
     <EmailAddressType>2</EmailAddressType> 
    </EmailAddress> 

</root> 

'; 




INSERT INTO #DestinationPersonParentTable (SSNNaturalKey , HireDate) 

output inserted.SSNNaturalKey , inserted.PersonParentSurrogateIdentityKey into @PersonOutputResultsAuditTable (SSNNaturalKey , PersonParentSurrogateIdentityKeyAudit) 

SELECT T.parentEntity.value('(SSN)[1]', 'INT') AS SSN, 
     T.parentEntity.value('(HireDate)[1]', 'datetime') AS HireDate 
FROM @data.nodes('root/Person') AS T(parentEntity) 
/* add a where not exists check on the natural key */ 
where not exists (
    select null from #DestinationPersonParentTable innerRealTable where innerRealTable.SSNNaturalKey = T.parentEntity.value('(SSN)[1]', 'INT')) 
; 

/* Optional. You could do a UPDATE here based on matching the #DestinationPersonParentTableSSNNaturalKey = T.parentEntity.value('(SSN)[1]', 'INT') 
You could Combine INSERT and UPDATE using the MERGE function on 2008 or later. 
*/ 


select 'PersonOutputResultsAuditTable_Results' as Label, * from @PersonOutputResultsAuditTable 


INSERT INTO #DestinationEmailAddressPersonChildTable ( PersonParentSurrogateIdentityKeyFK , EmailAddressValueNaturalKey , EmailAddressType) 
SELECT par.PersonParentSurrogateIdentityKeyAudit , 
     T.childEntity.value('(EmailAddressValue)[1]', 'varchar(64)') AS EmailAddressValue, 
     T.childEntity.value('(EmailAddressType)[1]', 'INT') AS EmailAddressType 
FROM @data.nodes('root/EmailAddress') AS T(childEntity) 
/* The next join is the "trick". Join on the natural key (SSN)....**BUT** insert the PersonParentSurrogateIdentityKey into the table */ 
join @PersonOutputResultsAuditTable par on par.SSNNaturalKey = T.childEntity.value('(SSNLink)[1]', 'INT') 
where not exists (
    select null from #DestinationEmailAddressPersonChildTable innerRealTable where innerRealTable.PersonParentSurrogateIdentityKeyFK = par.PersonParentSurrogateIdentityKeyAudit AND innerRealTable.EmailAddressValueNaturalKey = T.childEntity.value('(EmailAddressValue)[1]', 'varchar(64)')) 
; 



print '/#DestinationPersonParentTable/' 
select * from #DestinationPersonParentTable 


print '/#DestinationEmailAddressPersonChildTable/' 
select * from #DestinationEmailAddressPersonChildTable 


select SSNNaturalKey , HireDate , '---' as Sep1 , EmailAddressValueNaturalKey , EmailAddressType , '---' as Sep2, par.PersonParentSurrogateIdentityKey as ParentPK , child.PersonParentSurrogateIdentityKeyFK as childFK from #DestinationPersonParentTable par join #DestinationEmailAddressPersonChildTable child 
on par.PersonParentSurrogateIdentityKey = child.PersonParentSurrogateIdentityKeyFK 



IF OBJECT_ID('tempdb..#DestinationPersonParentTable') IS NOT NULL 
begin 
     drop table #DestinationPersonParentTable 
end 


IF OBJECT_ID('tempdb..#DestinationEmailAddressPersonChildTable') IS NOT NULL 
begin 
     drop table #DestinationEmailAddressPersonChildTable 
end 
+0

http://blogs.msdn.com/b/sqltips/archive/2005/06/13/output-clause.aspx – granadaCoder

+0

Я знаю, что это ваш собственный блог, но он может помочь обобщить код здесь, если вы 404. – gunr2171

+0

http://msdn.microsoft.com/en-us/library/ms177564.aspx – granadaCoder

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