【问题标题】:Inserting/Updating SQL using large Excel File使用大型 Excel 文件插入/更新 SQL
【发布时间】:2014-05-13 18:34:15
【问题描述】:

我有一种情况,我必须在我们的 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 行。必须有更有效的方法来完成。

如果没有,我将不得不大大分解这段代码。

微软 SQL Server 2005

【问题讨论】:

  • 您不能只将电子表格导入临时表(使用 SSIS 之类的东西)然后从那里插入数据吗?这比逐行执行要高效得多。
  • 我的意思是作为帖子中的一个想法。我很可能会在我们的工作临时数据库中创建一个临时表并从那里开始。在过去的几个月里,我也刚刚开始接触 SQL。如果 UPSERT 是一个有效的声明,我可以研究它,看看它是否确实是我正在寻找的。​​span>
  • 我现在意识到,我上面的陈述反映了我现在耳朵后面有多湿。先生,这可能对我有用!
  • 如果您可以升级到 sql 2008,您可以使用合并命令,使此类操作更简单、更快。除此之外,是的,临时表是要走的路。
  • Gary,一旦 ERP 升级获得批准,我们将进行升级,但不幸的是,我们等不及了。临时表,这与普通表不同吗?还是因为我用了之后,还是要删掉才叫staging?

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


【解决方案1】:

为了让您使用 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);

【讨论】:

  • 非常感谢您的好先生。实际上,我今天早上早些时候编写了代码并对其进行了测试,结果非常好,SSIS 一开始给我带来了一些问题。
猜你喜欢
  • 2018-12-31
  • 2016-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-01
相关资源
最近更新 更多