SQL合并功能,不指定列名

时间:2013-03-13 02:40:29

标签: sql sql-server merge dynamic-sql

我正在从我的网络应用程序执行SQLBulkCopy并将记录插入临时表。这是我第一次使用登台表。将接受数据的实时表有大约200个字段,可以更改为将来。发生此更改时,我不想重写合并语句。

我提出了这个模仿合并功能的SQL,但不要求我拼出表格列。我不是一个SQL专家,并希望有人看看,如果你发现使用这个SQL可能会出现任何问题,请告诉我,因为我还没有看到任何这样的例子以及很多人搜索。

请注意,要插入临时表中具有空id字段的记录。

-- 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;

如果有人发现任何有关表演或其他任何问题,我都很欣赏这种见解。

1 个答案:

答案 0 :(得分:0)

不要这样做。真。你正在努力避免在时机成熟时可能无法正常处理的罕见问题。

如果目标表发生了变化,您如何知道它会以您的花哨动态SQL正常工作的方式发生变化?你如何确定似乎无法工作 - 即在语法上工作 - 但实际上做错了什么?如果目标表发生更改,您是否也必须更改应用程序和登台表?所有这些都在空中,又增加了一个SET条款?

与此同时,如何才能让人们看到那个gobbledygook(不是你的错,真的,这是SQL的语法)?沼泽标准插入语句将非常清晰可靠。

快。 SQL Server无法优化您的动态查询。你使用bcp来提高效率,现在你已经用很有意义的未来防御来打败它。