2013-03-13 4 views
4

Я делаю SQLBulkCopy из своего веб-приложения и вставляя записи в промежуточную таблицу. Это мой первый опыт работы с промежуточными столами. Живая таблица, которая будет принимать данные, имеет около 200 полей и может измениться в будущем. Когда это изменение происходит, я не хотел переписывать оператор слияния.Функция слияния SQL без указания имен столбцов

Я придумал этот SQL, который имитирует функциональность слияния, но не требует, чтобы я описывал столбцы таблицы. Я не эксперт по SQL и не хочу, чтобы кто-то взглянул и сообщите мне, видите ли вы какие-либо проблемы, которые могут возникнуть при использовании этого SQL, потому что я не видел примеров этого и многих людей.

Обратите внимание, что записи в промежуточной таблице, которые имеют поле нулевого идентификатора, должны быть вставлены.

-- set the table names, primary key field & vars to hold query parts 
DECLARE @LiveTable varchar(20) = 'Test' 
DECLARE @StagingTable varchar(20) = 'TestStaging' 
DECLARE @PKField varchar(20) = 'TestPK' 
DECLARE @SQLSet nvarchar(MAX) = '' 
DECLARE @SQLInsertFields nvarchar(MAX) = '' 

-- get comma delimited field names 
DECLARE @Fields nvarchar(MAX) = (SELECT dbo.fn_GetCommaDelimitedFieldNames(@LiveTable)) 

-- loop through fields generating set clause of query to execute 
WHILE LEN(@Fields) > 0 
BEGIN 
    DECLARE @Field varchar(50) = left(@Fields, CHARINDEX(',', @Fields+',')-1) 
    IF @Field <> @PKField -- the primary key field cannot be updated 
     BEGIN 
      SET @SQLSet += ', ' + @LiveTable + '.' + @Field + ' = ' + @StagingTable + '.' + @Field 
      SET @SQLInsertFields += ', ' + @Field 
     END 
    SET @Fields = STUFF(@Fields, 1, CHARINDEX(',', @Fields+','), '') 
END 

-- remove the leading comma 
SET @SQLSet = SUBSTRING(@SQLSet,3,LEN(@SQLSet)) 
SET @SQLInsertFields = SUBSTRING(@SQLInsertFields,3,LEN(@SQLInsertFields)) 

-- update records from staging table where primary key is provided 
DECLARE @SQL nvarchar(MAX) = N'UPDATE ' + @LiveTable + 
          ' SET ' + @SQLSet + 
          ' FROM ' + @LiveTable + 
          ' INNER JOIN ' + @StagingTable + 
          ' ON ' + @LiveTable + '.' + @PKField + ' = ' + @StagingTable + '.' + @PKField 

-- insert records from staging table where primary key is null 
SET @SQL += '; INSERT INTO ' + @LiveTable + ' (' + @SQLInsertFields + ') SELECT ' + @SQLInsertFields + ' FROM ' + @StagingTable + ' WHERE ' + @PKField + ' IS NULL' 

-- delete the records from the staging table 
SET @SQL += '; DELETE FROM ' + @StagingTable 

-- execute the sql statement to update existing records and insert new records 
exec sp_executesql @SQL; 

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

+2

Возможно, вы захотите сделать это как транзакцию, чтобы не получить ошибку при вставке или обновлении, а затем удалить свою промежуточную таблицу. – Hogan

+0

@ Хоган - Хороший момент, безусловно, будет заключен в сделку. Спасибо за ваш вклад. – Ricketts

+0

200 полей в одном столе? Является реляционным или плоским файлом? –

ответ

0

Не делайте этого. В самом деле. Вы очень много работаете, чтобы избежать редкой проблемы, с которой вы, вероятно, не справитесь, когда придет время.

Если таблица целей изменяется, как вы знаете, она изменится так, что ваш фантастический динамический SQL будет работать правильно? Как вы можете быть уверены, что это не будет покажут, чтобы работать - т. Е. Будет работать, синтаксически - но на самом деле делать не ту вещь? Если и когда целевая таблица изменится, вам не придется менять приложение и промежуточную таблицу? Что все в воздухе, что добавляет еще один пункт SET?

Между тем, как можно ожидать, что кто-нибудь сможет прочитать этот gobbledygook (а не ваша вина, действительно, это синтаксис SQL)? Стандартная вставка для болота будет очень четкой и надежной.

И быстро. SQL Server не может оптимизировать динамический запрос. Вы использовали bcp для повышения эффективности, и теперь вы побеждаете его с хорошо продуманной надежностью.

+0

Спасибо за ваш вклад, он будет рассмотрен. Я буду тестировать производительность этого против MERGE, и если будут большие различия, я поеду на этот маршрут и вручную буду поддерживать инструкцию MERGE. Я не могу придумать сценарий, когда это не будет выполнено правильно, возможно, вы можете привести пример? Существует триггер, который поддерживает структуру промежуточной таблицы в синхронизации с целевой таблицей, поэтому там не было бы проблем. Если целевая таблица изменяется, единственным изменением в моем приложении будет обновление EntityModel, но код не изменяется, потому что отображение из источника является динамическим. – Ricketts

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