2010-02-11 46 views
5

考虑到在连接ODBC的客户端应用程序中有很长的键列表,在MySql中使用很多行的好方法是什么?MySql:在许多行上使用长列表组合PK操作

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

任务是从9个表中删除一些行,但我可能有5000个以上的密钥对。

我开始了通过我的所有键循环,并提交一份声明中为每一个对每个表,如简单的方法:

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,我真的不知道第一次调查哪些可能性,我希望得到一些帮助,以免我做出糟糕的决定和/或以艰难的方式学习。

回答

2

我会使用临时表解决方案,并将它连接到DELETE语句中的每个主表。所以你只需要进行九次删除,每次删除一次。使用LOAD DATA LOCAL INFILE

LOAD DATA LOCAL INFILE 'C:/path/to/datafile' INTO TABLE Keys; 
  • 删除使用MySQL的多表DELETE语法

    • CREATE TEMPORARY TABLE

      CREATE TEMPORARY TABLE Keys (
          Key1 INT UNSIGNED NOT NULL, 
          Key2 INT UNSIGNED NOT NULL, 
          PRIMARY KEY(Key1, Key2) 
      ); 
      
    • 负载制表符分隔的数据到临时表中的一个文件。

      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); 
      

    回复您的评论:

    CREATE TABLE MySQL的文档说以下内容:

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

    这很清楚!

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

  • +0

    谢谢比尔,这看起来像炸药。我会研究LOAD DATA方法,但我不确定是否可以轻松地写入这样的文件。是否有另一种脚本方式来加载临时表?另外,您能否详细说明临时表的范围(如果两个会话尝试创建具有相同名称的临时表,或者该名称已作为实际表存在,并且在连接断开时会销毁临时表关闭)? – ErikE 2010-02-12 20:18:54

    +0

    P.S. USING很酷,我希望SQL Server具有这一点。 – ErikE 2010-02-12 20:19:45

    +0

    我希望我能给你多一个upvote。谢谢你的答案的深度和细节。我承认我可以去研究所有这些事情(而且我打算继续这样做),但是一个很好的答案非常棒。 – ErikE 2010-02-12 20:48:58