使用大型Excel文件插入/更新SQL

时间:2014-05-13 18:34:15

标签: sql sql-server excel sql-server-2005 erp

我有一种情况,我必须在ERP的表格中插入/更新大量信息。我首先要检查表是否存在信息,如果不存在,则插入,如果存在,则更新。

我有以下示例代码。

    IF NOT EXISTS(SELECT * FROM EXT00101 WHERE PT_Window_ID='ITEM_SHIP_MAINT' and PT_UD_Key='18 RND PA' and PT_UD_Number=5)
    BEGIN
          INSERT INTO EXT00101 VALUES('ITEM_SHIP_MAINT', '18 RND PA', 5, '70')
    End

IF EXISTS(SELECT * FROM EXT00101 WHERE PT_Window_ID='ITEM_SHIP_MAINT' and PT_UD_Key='18 RND PA' and PT_UD_Number=5)
    BEGIN
        UPDATE EXT00101
        SET STRGA255='70'
        WHERE PT_Window_ID='ITEM_SHIP_MAINT' and PT_UD_Key='18 RND PA' and PT_UD_Number=5;
    END

我对一个有23,000多行的excel文件使用邮件合并。这导致我的SQL语句为260,000多行。必须有一种更有效的方法来完成它。

如果没有,我将不得不大打破这段代码。

Microsoft SQL Server 2005

1 个答案:

答案 0 :(得分:0)

为了使用SSIS让您使用正确的轨道,第一步是使用执行SQL任务来创建临时表:

IF (OBJECT_ID(N'dbo.tmpEXT00101Staging') IS NOT NULL 
    DROP TABLE dbo.tmpEXT00101Staging;

CREATE TABLE dbo.tmpEXT00101Staging
(       PT_Window_ID    VARCHAR(50) NOT NULL,
        PT_UD_Key       VARCHAR(50) NOT NULL,
        PT_UD_Number    INT NOT NULL,
        STRGA255        VARCHAR(50) NOT NULL
);

然后使用数据流任务将数据导入此表(平面文件或Excel源,目标将是OLE DB目标。您可能需要将数据流任务上的“延迟验证”设置为false和/或者在目标上“验证外部元数据”为false,因为目标是在运行时创建的)。您也可以将临时表永久保存在那里,而只需在每次执行开始时使用TRUNCATE TABLE dbo.tmpEXT00101Staging清除它。

最后使用此临时表更新主表(如果您不想永久保留,则删除临时表以进行清理)

BEGIN TRAN;

-- UPDATE ROWS THAT EXIST
UPDATE  t
SET     STRGA255 = st.STRGA255
FROM    dbo.EXT00101 t
        INNER JOIN dbo.tmpEXT00101Staging st
            ON st.PT_Window_ID = T.PT_Window_ID
            AND st.PT_UD_Key = t.PT_UD_Key
            AND st.PT_UD_Number = t.PT_UD_Number;

-- INSERT ROWS THAT DO NOT EXIST
INSERT EXT00101 (PT_Window_ID, PT_UD_Key, PT_UD_Number, STRGA255)
SELECT PT_Window_ID, PT_UD_Key, PT_UD_Number, STRGA255
FROM    dbo.tmpEXT00101Staging st
WHERE   NOT EXISTS
        (   SELECT  1
            FROM    dbo.EXT00101 t
            WHERE   st.PT_Window_ID = T.PT_Window_ID
            AND     st.PT_UD_Key = t.PT_UD_Key
            AND     st.PT_UD_Number = t.PT_UD_Number
        );

COMMIT TRAN;

-- CLEAN UP AND DROP STAGING TABLE (OPTIONAL)
IF (OBJECT_ID(N'dbo.tmpEXT00101Staging') IS NOT NULL 
DROP TABLE dbo.tmpEXT00101Staging;

这里有可能遇到竞争条件,所以你应该确保你有一些约束来阻止试图插入同一记录的并发线程的任何完整性违规。

为了完整起见,执行UPSERT的首选方案是MERGE(如果您从2005年的任何时候升级):

MERGE dbo.EXT00101 WITH (HOLDLOCK) AS t
USING dbo.tmpEXT00101Staging AS st
    ON st.PT_Window_ID = T.PT_Window_ID
    AND st.PT_UD_Key = t.PT_UD_Key
    AND st.PT_UD_Number = t.PT_UD_Number
WHEN MATCHED THEN 
    UPDATE  
    SET STRGA255 = st.STRGA255
WHEN NOT MATCHED THEN 
    INSERT (PT_Window_ID, PT_UD_Key, PT_UD_Number, STRGA255)
    VALUES (st.PT_Window_ID, st.PT_UD_Key, st.PT_UD_Number, st.STRGA255);