0

我的“合并”出现问题:MERGE 语句多次尝试更新或删除同一行。

有人可以帮我解决这个问题,因为我不明白如何解决这个问题:

ALTER PROCEDURE [Files].[ImportFiles]
AS
    -- Create a temporary table for the bulk import
    CREATE TABLE #TempImportFileTable(
        [fileID] [bigint] IDENTITY(1,1) NOT NULL,
        [FileName] [nvarchar](max) NULL,
        [FilePath] [nvarchar](max) NULL,
        [FullPath] [nvarchar](max) NULL,
        [FileSize] [nvarchar](max) NULL,
        [FileExtension] [nvarchar](max) NULL,
        [FileCreated] [nvarchar](max) NULL,
        [FileLastAccessed] [nvarchar](max) NULL,
        [FileModified] [nvarchar](max) NULL
     CONSTRAINT [PK_fileID1] PRIMARY KEY CLUSTERED 
    (
        [fileID] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY];

    -- Import into the temp table
    BULK INSERT #TempImportFileTable FROM 'C:\Program Files\o7th FileSystem to DB\import.txt' 
    WITH(KEEPIDENTITY, FIELDTERMINATOR =',', ROWTERMINATOR = '\n');

    -- Delete the Duplicate entries
    DELETE FROM #TempImportFileTable WHERE fileID NOT IN (SELECT MAX(fileID) FROM #TempImportFileTable GROUP BY FullPath);


    -- Now Merge the 2 tables
    MERGE [Files].[File] AS TargetTable
    USING #TempImportFileTable AS SourceTable  
    ON (TargetTable.FullPath = SourceTable.FullPath)
    WHEN NOT MATCHED BY TARGET                                
        THEN INSERT (FileName, FilePath, FileSize, FileExtension, FileCreated, FileLastAccessed, FileModified)
        VALUES(SourceTable.FileName, SourceTable.FilePath, SourceTable.FileSize, SourceTable.FileExtension, SourceTable.FileCreated, SourceTable.FileLastAccessed, SourceTable.FileModified)
    WHEN MATCHED                                              
        THEN UPDATE SET
            TargetTable.FileName = SourceTable.FileName,
            TargetTable.FilePath = SourceTable.FilePath,
            TargetTable.FileSize = SourceTable.FileSize,
            TargetTable.FileExtension = SourceTable.FileExtension,
            TargetTable.FileCreated = SourceTable.FileCreated,
            TargetTable.FileLastAccessed = SourceTable.FileLastAccessed,
            TargetTable.FileModified = SourceTable.FileModified;
4

2 回答 2

1

因此,您的#TempFileTable 中有重复项。

如果 FileName + FilePath 足以使一行唯一,您可以将此条件用于您的 MERGE:

MERGE [Files].[File] AS TargetTable
    USING #TempFileTable AS SourceTable  
    ON ( 
        ISNULL(TargetTable.FileName,'') = ISNULL(SourceTable.FileName,'') 
        AND ISNULL(TargetTable.FileName,'') = ISNULL(SourceTable.FileName,'') 
    )

(我不知道为什么 ISNULL() 函数在您之前尝试调用它时不起作用,但它绝对应该以这种方式工作,并处理空值出现的问题。)

如果您的原始文件中确实有重复的行并且您想摆脱它们,您可以使用这种代码:

DELETE FROM #TempFileTable WHERE fileID IN (
    SELECT u.fileID FROM(
        select fileID, ROW_NUMBER() OVER(PARTITION BY FileName, FilePath OVER fileID) as r_number 
        FROM #TempFileTable
    ) where u.r_number>1
)

这很丑陋,但是当多行具有相同的 FileName 和相同的 FilePath 时,它将删除具有最高 fileID 的行并只保留一个。

编辑:关于性能问题,首先尝试查看估计的执行计划,看看是否可以为表添加索引。您还可以尝试将 MERGE 过程分解为 on INSERT 和一个 UPDATE 语句。MERGE 应该更好,但在某些情况下它实际上比单独的语句更糟糕。

于 2013-08-13T17:11:44.357 回答
0

Merge 语句有一个限制,它不能多次更新同一行,或者更新和删除同一行。因此,请确保您的源数据中有不同的文件名行。此外,在进行更新时,您不必更新文件名列,因为它在源表和目标表中都是相同的。

您可以在此链接中找到解决方法:http: //support.microsoft.com/kb/976316

于 2013-08-13T15:28:59.473 回答