SQL如果不存在则插入else更新

时间:2014-05-30 12:45:04

标签: sql sql-server sql-server-2008

我的存储过程如下:

--Stored procedure to update data in Data_Archive.dbo.company
CREATE PROC dbo.TransferCompanyInfo
as
BEGIN TRAN
INSERT INTO Data_Archive.dbo.Company
Select 
CompanyID,
CompanyName,
Address1,
Address2,
Address3,
Address4,
ZipCode,
FROM OLD.dbo.company 
where not exists (select Data_Archive.dbo.Company.CompanyID from                   Data_Archive.dbo.Company
WHERE CompanyID = OLD.dbo.Company.CompanyID)

Update Data_Archive.dbo.Company
Set 
Data_Archive.dbo.Company.CompanyID = b.CompanyID,
Data_Archive.dbo.Company.CompanyName = b.CompanyName,
Data_Archive.dbo.Company.Address1 = b.Address1,
Data_Archive.dbo.Company.Address2 = b.Address2,
Data_Archive.dbo.Company.Address3 = b.Address3,
Data_Archive.dbo.Company.Address4 = b.Address4,
Data_Archive.dbo.Company.ZipCode = b.ZipCode,
From Data_Archive.dbo.Company a, OLD.dbo.Company b
Where a.CompanyID = b.CompanyID


IF @@ERROR <> 0
            BEGIN
                ROLLBACK TRAN
                RAISERROR ('Error occured while copying data to TachographData_Archive.dbo.company', 16, 1)
                RETURN -1
           END

 IF @@TRANCOUNT > 0
     BEGIN
           COMMIT TRAN
           RETURN 0
     END

但是我想知道如何让它更快,因为目前它必须扫描表以查看是否不存在,然后插入,然后再次扫描并更新。我想如果相反我做了如果存在更新其他插入它会使它更快但我不知道如何重新格式化它。目前我尝试了下面的代码但是没有工作:

- 更新Data_Archive.dbo.company中的数据的存储过程

 CREATE PROC dbo.TransferCompanyInfo
    as
    BEGIN TRAN
    Update Data_Archive.dbo.Company
    Set 
    Data_Archive.dbo.Company.CompanyID = b.CompanyID,
    Data_Archive.dbo.Company.CompanyName = b.CompanyName,
    Data_Archive.dbo.Company.Address1 = b.Address1,
    Data_Archive.dbo.Company.Address2 = b.Address2,
    Data_Archive.dbo.Company.Address3 = b.Address3,
    Data_Archive.dbo.Company.Address4 = b.Address4,
    Data_Archive.dbo.Company.ZipCode = b.ZipCode,
    From Data_Archive.dbo.Company a, OLD.dbo.Company b
    Where a.CompanyID = b.CompanyID

    ELSE
    INSERT INTO Data_Archive.dbo.Company
    Select 
    CompanyID,
    CompanyName,
    Address1,
    Address2,
    Address3,
    Address4,
    ZipCode,
    FROM OLD.dbo.company 
    where not exists (select Data_Archive.dbo.Company.CompanyID from                   Data_Archive.dbo.Company
    WHERE CompanyID = OLD.dbo.Company.CompanyID)



    IF @@ERROR <> 0
                BEGIN
                    ROLLBACK TRAN
                    RAISERROR ('Error occured while copying data to TachographData_Archive.dbo.company', 16, 1)
                    RETURN -1
               END

     IF @@TRANCOUNT > 0
         BEGIN
               COMMIT TRAN
               RETURN 0
         END

4 个答案:

答案 0 :(得分:3)

您可以使用MERGE

MERGE Data_Archive.dbo.Company WITH (HOLDLOCK) AS a
USING OLD.dbo.Company AS o
    ON a.CompanyID = b.CompanyID
WHEN MATCHED THEN UPDATE    
    SET CompanyName = o.CompanyName,
        Address1 = o.Address1,
        Address2 = o.Address2,
        Address3 = o.Address3,
        Address4 = o.Address4,
        ZipCode = o.ZipCode
WHEN NOT MATCHED BY TARGET THEN 
    INSERT (CompanyName, Address1, Address2, Address3, Address4, ZipCode)
    VALUES (o.CompanyName, o.Address1, o.Address2, o.Address3, o.Address4, o.ZipCode)
WHEN NOT MATCHED BY SOURCE THEN DELETE;

这将更新存在的所有记录,插入任何新记录,并从归档中删除已从OLD数据库中删除的任何记录。如果不需要最后一位,则只需删除WHEN NOT MATCHED BY SOURCE THEN DELETE

使用HOLDLOCK将确保您不会遇到race condition,虽然MERGE仍有some quirks,但我认为这不会成为问题。

这样做的主要好处是SQL在单个事务中管理它,因此您无需检查一个部件是否出现故障,然后再回滚事务。

答案 1 :(得分:1)

使用MERGE声明:

MERGE INTO Stg.Data_Archive.dbo.Company AS tbl
USING (
    SELECT old.CompanyID, old.CompanyName, old.Address1, old.Address2, old.Address3, old.Address4, old.ZipCode
    FROM OLD.dbo.Company AS old
    LEFT OUTER JOIN Data_Archive.dbo.Company AS new
    ON old.CompanyID = new.CompanyID 
    WHERE new.CompanyID IS NOT NULL) AS source
ON tbl.CompanyID=source.CompanyID
WHEN MATCHED THEN --if i find a row, update
    UPDATE SET
    tbl.CompanyID = source.CompanyID,
    tbl.CompanyName = source.CompanyName,
    tbl.Address1 = source.Address1,
    tbl.Address2 = source.Address2,
    tbl.Address3 = source.Address3,
    tbl.Address4 = source.Address4,
    tbl.ZipCode = source.ZipCode
WHEN NOT MATCHED THEN --if not, insert a new one
    INSERT (CompanyID, CompanyName, Address1, Address2, Address3, Address4, ZipCode)
    VALUES (source.CompanyID, source.CompanyName, source.Address1, source.Address2, source.Address3, source.Address4, source.ZipCode);

答案 2 :(得分:0)

BEGIN TRY
      SET NOCOUNT ON
      DECLARE @l_numberOfRecordsInserted INT       
         BEGIN
               RAISERROR ( N'Invalid Application User ID %d passed.'
               ,17
               ,1
               ,-1 )
         END
      IF NOT EXISTS ( SELECT 
                          1
                      FROM
                          Data_Archive.dbo.Company
                      WHERE
                          ( CompanyID  = @i_CompanyID  )
                          AND CompanyName = @vc_CompanyName ) 
         BEGIN
               INSERT INTO
                   Data_Archive.dbo.Company
                   (
                    CompanyID,
                    CompanyName,
                    Address1,
                    Address2,
                    Address3,
                    Address4,
                    ZipCode
                   )
            Select  CompanyID,
                    CompanyName,
                    Address1,
                    Address2,
                    Address3,
                    Address4,
                    ZipCode
                      FROM OLD.dbo.company 
    where not exists (select Data_Archive.dbo.Company.CompanyID from  Data_Archive.dbo.Company
                                    WHERE CompanyID = @i_CompanyID)


         END
      ELSE
         BEGIN
              Update Data_Archive.dbo.Company
                            Set 
                            Data_Archive.dbo.Company.CompanyID = b.CompanyID,
                            Data_Archive.dbo.Company.CompanyName = b.CompanyName,
                            Data_Archive.dbo.Company.Address1 = b.Address1,
                            Data_Archive.dbo.Company.Address2 = b.Address2,
                            Data_Archive.dbo.Company.Address3 = b.Address3,
                            Data_Archive.dbo.Company.Address4 = b.Address4,
                            Data_Archive.dbo.Company.ZipCode = b.ZipCode,
                            From Data_Archive.dbo.Company a, OLD.dbo.Company b
                            Where a.CompanyID = @i_CompanyID

         END

      RETURN 0
END TRY        
--------------------------------------------------------         
BEGIN CATCH        
    -- Handle exception        
      DECLARE @i_ReturnedErrorID INT
      EXECUTE @i_ReturnedErrorID = dbo.usp_HandleException @i_UserId = @i_AppUserId

      RETURN @i_ReturnedErrorID
END CATCH

答案 3 :(得分:0)

您可以尝试使用Merge语句。我相信这对你有用:

Merge Into Data_Archive.dbo.Company As Target
Using
(
    Select  CompanyID,
            CompanyName,
            Address1,
            Address2,
            Address3,
            Address4,
            ZipCode
    From    OLD.dbo.company 
) As Source On  Source.CompanyID = Target.CompanyID
When Not Matched Then 
    Insert (CompanyID, CompanyName, Address1, Address2, Address3, Address4, ZipCode)
    Values (Source.CompanyID, Source.CompanyName, Source.Address1, Source.Address2, Source.Address3, Source.Address4, Source.ZipCode)
When Matched Then
    Update
    Set     CompanyName = Source.CompanyName,
            Address1    = Source.Address1,
            Address2    = Source.Address2,
            Address3    = Source.Address3,
            Address4    = Source.Address4,
            ZipCode     = Source.ZipCode
;