0

「マージ」に問題があります: MERGE ステートメントが同じ行を複数回 UPDATE または DELETE しようとしました。

問題の修正方法がわからないので、誰かがこれを修正するのを手伝ってくれますか?

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 に重複があります。

IF 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() 関数を呼び出そうとしたときに機能しなかった理由はわかりませんが、この方法で確実に機能し、null 値で発生する問題を処理する必要があります。)

元のファイルに本当に重複した行があり、それらを取り除きたい場合は、次のようなコードを使用できます。

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 を持つ行が削除され、1 つだけが保持されます。

編集:パフォーマンスの問題については、まず推定実行計画を見て、テーブルにインデックスを追加できるかどうかを確認してください。MERGE プロシージャを INSERT ステートメントと 1 つの UPDATE ステートメントに分割することもできます。MERGE の方が優れているはずですが、状況によっては、個別のステートメントよりも実際に悪い場合があります。

于 2013-08-13T17:11:44.357 に答える