I have a stored procedure that does an insert like this one:
INSERT INTO [TargetTable] ([Hash], [Year], [Metadata])
SELECT [Hash], [Year], [Metadata]
FROM [SourceTable]
This query will fail because the [TargetTable] has data already and an unique index on the [Hash] column. It cannot insert duplicates.
How I can insert only the non-duplicates? I guess I could select first only the non-duplicates and then do the inserts. But the select would be more complex.
Another approach I tried is to ignore the duplicates. For instance:
BEGIN TRY
INSERT INTO [TargetTable] ([Hash], [Event], [Year], [Metadata])
SELECT [Hash], [Event], [Year], [Metadata]
FROM [SourceTable]
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;
END CATCH
I was expecting something like, try to insert this, if you cannot insert it, then ignore it, and then continue inserting the rest of rows.
INSERT, or at least within aBEGIN TRY...CATCHrow by row. SQL Server works in datasets and will process the whole dataset in one go. If 1 row out of 1M has an error, then the entire statement errors and is rolled back. When working with a DBMS you need to not think in rows, and think in sets of data. This is why your second attempt didn't work. AnINSERTdoesn't work like aFOR EACHloop (nor does aSELECT,UPDATE, DELETE`, etc).