MySql:使用复合PK的长列表在许多行上运行

Eri*_*ikE 5 mysql stored-procedures list large-data-volumes set-based

在MySql中处理多行的好方法是什么,因为我在与ODBC连接的客户端应用程序中有很长的键列表?

注意:我的经验主要是SQL Server,所以我知道一点,而不是专门针对MySQL.

任务是从9个表中删除一些行,但我可能有超过5,000个密钥对.

我开始时使用简单的方法循环遍历所有密钥,并针对每个表为每个密钥提交一个语句,例如:

DELETE FROM Table WHERE Key1 = 123 AND Key2 = 567 -- and 8 more tables
DELETE FROM Table WHERE Key1 = 124 AND Key2 = 568 -- and 8 more tables
DELETE FROM Table WHERE Key1 = 125 AND Key2 = 569 -- and 8 more tables
...
Run Code Online (Sandbox Code Playgroud)

除此之外,有45,000个单独的陈述,你可以想象这有点慢.

因此,在不担心我在前端使用的编程语言的情况下,提交列表的好方法是什么,以便我可以一次或至少大批量地加入并执行操作?以下是我的想法:

  • 创建临时表并插入,然后加入.我很乐意查找MySQL的语法来创建临时表,但这是一条很好的路线吗?

  • 假设我使用临时表,那么填充临时表的最佳方法是什么?5000条INSERT Table VALUES ()陈述?SELECT 123, 456 UNION ALL SELECT 124, 457?我刚刚测试过MySql允许这种不针对表发出的SELECT.但是如果列表太长,SQL Server最终会爆炸,所以这在MySQL中是一个好方法吗?我应该一次将列表保持几百个吗?

    --CREATE Temp Table ( I do not know the syntax in MySql yet)
    
    INSERT INTO TempTable
    SELECT 123, 456
    UNION ALL SELECT 124, 457
    UNION ALL SELECT 125, 458
    
    DELETE T
    FROM
       Table T
       INNER JOIN TempTable X ON T.Key1 = X.Key1 AND T.Key2 = X.Key2
    
    Run Code Online (Sandbox Code Playgroud)
  • XML.我看到MySQL 5.1有一些XML函数,但是从粗略的搜索来看,它似乎不支持将一大块XML文本转换为一个加入的行集.真的吗?我很容易将值转换为XML.

  • 虚拟拆分操作.我在MySql中假设有某种程序语言是可能的.在SQL Server中,我可以编写一些自定义代码来解析字符串并将其转换为行集:

    CREATE PROCEDURE DoStuff @KeyString varchar(max)
    AS
    DECLARE @Keys TABLE (
       Key1 int,
       Key2 int,
       PRIMARY KEY CLUSTERED (Key1, Key2)
    )
    DECLARE @Pos int
    WHILE @Pos < Len(@KeyString) BEGIN
       -- loop to search for delimiting commas in @KeyString
       -- and insert pairs of parsed tokens to table variable @Keys
    END
    
    DELETE T
    FROM
       Table T
       INNER JOIN @Keys K ON T.Key1 = K.Key1 AND T.Key2 = K.Key2
    
    Run Code Online (Sandbox Code Playgroud)

由于我不熟悉MySQL,我真的不知道首先调查哪种可能性,我希望得到一些帮助,以免我做出糟糕的决定和/或学习困难的方法.

Bil*_*win 2

我将使用临时表解决方案,并将其连接到DELETE语句中的每个主表。因此,您只需执行九次删除,每个表一次。

  • CREATE TEMPORARY TABLE

    CREATE TEMPORARY TABLE Keys (
        Key1 INT UNSIGNED NOT NULL, 
        Key2 INT UNSIGNED NOT NULL, 
        PRIMARY KEY(Key1, Key2)
    );
    
    Run Code Online (Sandbox Code Playgroud)
  • 使用以下命令将制表符分隔的数据文件加载到临时表中LOAD DATA LOCAL INFILE

    LOAD DATA LOCAL INFILE 'C:/path/to/datafile' INTO TABLE Keys;
    
    Run Code Online (Sandbox Code Playgroud)
  • 使用MySQL的多表DELETE语法进行删除。

    DELETE t FROM Table1 t JOIN Keys USING (Key1, Key2);
    DELETE t FROM Table2 t JOIN Keys USING (Key1, Key2);
    DELETE t FROM Table3 t JOIN Keys USING (Key1, Key2);
    DELETE t FROM Table4 t JOIN Keys USING (Key1, Key2);
    DELETE t FROM Table5 t JOIN Keys USING (Key1, Key2);
    DELETE t FROM Table6 t JOIN Keys USING (Key1, Key2);
    DELETE t FROM Table7 t JOIN Keys USING (Key1, Key2);
    DELETE t FROM Table8 t JOIN Keys USING (Key1, Key2);
    DELETE t FROM Table9 t JOIN Keys USING (Key1, Key2);
    
    Run Code Online (Sandbox Code Playgroud)

回复您的评论:

MySQL 文档上CREATE TABLE说了以下内容:

TEMPORARY 表仅对当前连接可见,并在连接关闭时自动删除。这意味着两个不同的连接可以使用相同的临时表名称,而不会相互冲突或与现有的同名非 TEMPORARY 表发生冲突。(现有表将被隐藏,直到临时表被删除。)

这很清楚!

关于加载数据,您可以使用INSERT. 5000 行没什么大不了的。我使用 PHP 脚本将数百万行(例如 StackOverflow XML 数据转储)加载到 MySQL 中,这只需要大约 20 分钟。我使用准备好的语句,然后使用参数执行它。