2010-02-11 15 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

    相關問題