5

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

注意:我的经验主要是 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
...

除了,这是 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
    
  • .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
    

由于我不熟悉 MySQL,我真的不知道首先要调查哪种可能性,我希望能得到一些帮助,以免我做出错误的决定和/或艰难地学习。

4

1 回答 1

2

我会使用临时表解决方案,并将其加入DELETE语句中的每个主表。所以你只需要进行九次删除,每个表一次。

  • CREATE TEMPORARY TABLE

    CREATE TEMPORARY TABLE Keys (
        Key1 INT UNSIGNED NOT NULL, 
        Key2 INT UNSIGNED NOT NULL, 
        PRIMARY KEY(Key1, Key2)
    );
    
  • 将制表符分隔的数据文件加载到临时表中LOAD DATA LOCAL INFILE

    LOAD DATA LOCAL INFILE 'C:/path/to/datafile' INTO TABLE Keys;
    
  • 使用 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);
    

回复您的评论:

MySQL 文档上CREATE TABLE的内容如下:

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

这很清楚!

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

于 2010-02-12T18:42:25.277 回答