使用外键更新SQL表中数百万条记录的最佳方法

使用外键更新SQL表中数百万条记录的最佳方法,sql,database,vb.net,Sql,Database,Vb.net,我有一个数据库,有几个表,每个表包含数百万条记录。 每年我们都会收到一组用于更新表格的CSV文件。这是一个刷新,而不仅仅是一个附加。 一些表具有返回到其他表的外键。 要在不使用FK的情况下更新表,我只需截断数据库表,创建一个新的临时表,将所有新数据加载到临时表中,并将其插入数据库表中。一切都很好,而且相当快 当我需要更新具有FK的表中的数据时,就会出现问题,因为我不能再简单地截断该表,所以需要一种更新现有表行的方法。 我通过循环中运行的SQL update语句来实现这一点,每次运行一行。它可以工

我有一个数据库,有几个表,每个表包含数百万条记录。 每年我们都会收到一组用于更新表格的CSV文件。这是一个刷新,而不仅仅是一个附加。 一些表具有返回到其他表的外键。 要在不使用FK的情况下更新表,我只需截断数据库表,创建一个新的临时表,将所有新数据加载到临时表中,并将其插入数据库表中。一切都很好,而且相当快

当我需要更新具有FK的表中的数据时,就会出现问题,因为我不能再简单地截断该表,所以需要一种更新现有表行的方法。 我通过循环中运行的SQL update语句来实现这一点,每次运行一行。它可以工作,但需要13天来处理数百万条记录。 一定有更快的办法


如何一次快速更新多个数据库表行(比如3500),其中每行有8列需要更新?1列是FK,加上其他3列不会改变。

我认为你最好的选择是:

  • 删除外键约束
  • 截断外键表
  • 截断主键表
  • 从包含主键数据的CSV文件插入主键表
  • 将外键数据插入新的临时表
  • 将外键临时表内部联接到相关字段上新填充的主键表
  • 将该联接结果插入到最终的外键表中
  • 在外键表上重新创建外键
  • 通过一点动态SQL,您可以创建一个存储过程,并将表名、文件名和外键名作为参数传递到该过程中。然后只需冲洗并重复每一组相关表格

    即使没有存储过程,也应该不到13天:)

    更新了一个可能的示例

    ALTER TABLE [SecondaryTable] DROP CONSTRAINT [NameOfForeignKey]
    
    TRUNCATE TABLE [SecondaryTable]
    
    TRUNCATE TABLE [PrimaryTable]
    
    BULK INSERT [PrimaryTable]
    FROM 'C:\PrimaryCSVfile.csv' WITH (FIELDTERMINATOR =',', ROWTERMINATOR ='\n', FIRSTROW = 1)
    
    -- [TempTableSecondary] is a structural copy of [SecondaryTable]
    CREATE TABLE [TempTableSecondary] (column1, column2, ..., columnX)
    
    BULK INSERT [TempTableSecondary]
    FROM 'C:\SecondaryCSVfile.csv' WITH (FIELDTERMINATOR =',', ROWTERMINATOR ='\n', FIRSTROW = 1)
    
    INSERT INTO [SecondaryTable]
    SELECT [TempTableSecondary].*
    FROM [TempTableSecondary]
        INNER JOIN [PrimaryTable] ON [TempTableSecondary].PrimaryKeyFieldName = [PrimaryTable].ForeignKeyFieldName
    
    ALTER TABLE [SecondaryTable] WITH CHECK ADD CONSTRAINT [NameOfForeignKey] FOREIGN KEY([PrimaryKeyFieldName])
    REFERENCES [PrimaryTable] ([ForeignKeyFieldName])
    
    ALTER TABLE [SecondaryTable] CHECK CONSTRAINT [NameOfForeignKey]
    
    DROP TABLE [TempTableSecondary]
    

    我认为你最好的选择是:

  • 删除外键约束
  • 截断外键表
  • 截断主键表
  • 从包含主键数据的CSV文件插入主键表
  • 将外键数据插入新的临时表
  • 将外键临时表内部联接到相关字段上新填充的主键表
  • 将该联接结果插入到最终的外键表中
  • 在外键表上重新创建外键
  • 通过一点动态SQL,您可以创建一个存储过程,并将表名、文件名和外键名作为参数传递到该过程中。然后只需冲洗并重复每一组相关表格

    即使没有存储过程,也应该不到13天:)

    更新了一个可能的示例

    ALTER TABLE [SecondaryTable] DROP CONSTRAINT [NameOfForeignKey]
    
    TRUNCATE TABLE [SecondaryTable]
    
    TRUNCATE TABLE [PrimaryTable]
    
    BULK INSERT [PrimaryTable]
    FROM 'C:\PrimaryCSVfile.csv' WITH (FIELDTERMINATOR =',', ROWTERMINATOR ='\n', FIRSTROW = 1)
    
    -- [TempTableSecondary] is a structural copy of [SecondaryTable]
    CREATE TABLE [TempTableSecondary] (column1, column2, ..., columnX)
    
    BULK INSERT [TempTableSecondary]
    FROM 'C:\SecondaryCSVfile.csv' WITH (FIELDTERMINATOR =',', ROWTERMINATOR ='\n', FIRSTROW = 1)
    
    INSERT INTO [SecondaryTable]
    SELECT [TempTableSecondary].*
    FROM [TempTableSecondary]
        INNER JOIN [PrimaryTable] ON [TempTableSecondary].PrimaryKeyFieldName = [PrimaryTable].ForeignKeyFieldName
    
    ALTER TABLE [SecondaryTable] WITH CHECK ADD CONSTRAINT [NameOfForeignKey] FOREIGN KEY([PrimaryKeyFieldName])
    REFERENCES [PrimaryTable] ([ForeignKeyFieldName])
    
    ALTER TABLE [SecondaryTable] CHECK CONSTRAINT [NameOfForeignKey]
    
    DROP TABLE [TempTableSecondary]
    

    我认为你最好的选择是:

  • 删除外键约束
  • 截断外键表
  • 截断主键表
  • 从包含主键数据的CSV文件插入主键表
  • 将外键数据插入新的临时表
  • 将外键临时表内部联接到相关字段上新填充的主键表
  • 将该联接结果插入到最终的外键表中
  • 在外键表上重新创建外键
  • 通过一点动态SQL,您可以创建一个存储过程,并将表名、文件名和外键名作为参数传递到该过程中。然后只需冲洗并重复每一组相关表格

    即使没有存储过程,也应该不到13天:)

    更新了一个可能的示例

    ALTER TABLE [SecondaryTable] DROP CONSTRAINT [NameOfForeignKey]
    
    TRUNCATE TABLE [SecondaryTable]
    
    TRUNCATE TABLE [PrimaryTable]
    
    BULK INSERT [PrimaryTable]
    FROM 'C:\PrimaryCSVfile.csv' WITH (FIELDTERMINATOR =',', ROWTERMINATOR ='\n', FIRSTROW = 1)
    
    -- [TempTableSecondary] is a structural copy of [SecondaryTable]
    CREATE TABLE [TempTableSecondary] (column1, column2, ..., columnX)
    
    BULK INSERT [TempTableSecondary]
    FROM 'C:\SecondaryCSVfile.csv' WITH (FIELDTERMINATOR =',', ROWTERMINATOR ='\n', FIRSTROW = 1)
    
    INSERT INTO [SecondaryTable]
    SELECT [TempTableSecondary].*
    FROM [TempTableSecondary]
        INNER JOIN [PrimaryTable] ON [TempTableSecondary].PrimaryKeyFieldName = [PrimaryTable].ForeignKeyFieldName
    
    ALTER TABLE [SecondaryTable] WITH CHECK ADD CONSTRAINT [NameOfForeignKey] FOREIGN KEY([PrimaryKeyFieldName])
    REFERENCES [PrimaryTable] ([ForeignKeyFieldName])
    
    ALTER TABLE [SecondaryTable] CHECK CONSTRAINT [NameOfForeignKey]
    
    DROP TABLE [TempTableSecondary]
    

    我认为你最好的选择是:

  • 删除外键约束
  • 截断外键表
  • 截断主键表
  • 从包含主键数据的CSV文件插入主键表
  • 将外键数据插入新的临时表
  • 将外键临时表内部联接到相关字段上新填充的主键表
  • 将该联接结果插入到最终的外键表中
  • 在外键表上重新创建外键
  • 通过一点动态SQL,您可以创建一个存储过程,并将表名、文件名和外键名作为参数传递到该过程中。然后只需冲洗并重复每一组相关表格

    即使没有存储过程,也应该不到13天:)

    更新了一个可能的示例

    ALTER TABLE [SecondaryTable] DROP CONSTRAINT [NameOfForeignKey]
    
    TRUNCATE TABLE [SecondaryTable]
    
    TRUNCATE TABLE [PrimaryTable]
    
    BULK INSERT [PrimaryTable]
    FROM 'C:\PrimaryCSVfile.csv' WITH (FIELDTERMINATOR =',', ROWTERMINATOR ='\n', FIRSTROW = 1)
    
    -- [TempTableSecondary] is a structural copy of [SecondaryTable]
    CREATE TABLE [TempTableSecondary] (column1, column2, ..., columnX)
    
    BULK INSERT [TempTableSecondary]
    FROM 'C:\SecondaryCSVfile.csv' WITH (FIELDTERMINATOR =',', ROWTERMINATOR ='\n', FIRSTROW = 1)
    
    INSERT INTO [SecondaryTable]
    SELECT [TempTableSecondary].*
    FROM [TempTableSecondary]
        INNER JOIN [PrimaryTable] ON [TempTableSecondary].PrimaryKeyFieldName = [PrimaryTable].ForeignKeyFieldName
    
    ALTER TABLE [SecondaryTable] WITH CHECK ADD CONSTRAINT [NameOfForeignKey] FOREIGN KEY([PrimaryKeyFieldName])
    REFERENCES [PrimaryTable] ([ForeignKeyFieldName])
    
    ALTER TABLE [SecondaryTable] CHECK CONSTRAINT [NameOfForeignKey]
    
    DROP TABLE [TempTableSecondary]
    


    只是想一想,对于性能问题,您的sql更新应该使用操作符
    ,同时使用更精确的sql筛选器。不使用或操作符。只有几百万个循环。这可能不是最好的方法,但我已经见过了。您只需在启动流程之前删除FK,然后再将其添加回。如果你的CSV文件中有坏数据,可能会把你搞得一团糟。@Malcom,将一百万个循环放到程序脚本中会有好处。在重新加载之间会有多少数据变化?插入新数据、更新已修改的现有数据以及删除/禁用不在新数据集中的数据可能更有效。考虑到性能问题,您的sql更新应该使用运算符
    ,同时使用更精确的sql筛选器。无或运算符。只有几百万个循环。这可能不是最好的方法,但我已经见过了。您只需在启动流程之前删除FK,然后再将其添加回。如果你的CSV文件中有坏数据,可能会把你搞得一团糟。@Malcom,将一百万个循环放到程序脚本中会有好处。在重新加载之间会有多少数据变化?插入新数据、更新已修改的现有数据以及删除/禁用不在新数据集中的数据可能会更有效