2010-02-11 14 views
5

Qual è un buon modo per lavorare con molte righe in MySql, dato che ho un lungo elenco di chiavi in ​​un'applicazione client che si connette con ODBC?MySql: operare su molte righe utilizzando una lunga lista di PK compositi

Nota: la mia esperienza è in gran parte SQL Server, quindi ne conosco un po ', solo non specificamente MySQL.

L'operazione è di eliminare alcune righe da 9 tabelle, ma potrei avere più di 5.000 coppie di chiavi.

ho iniziato con il modo più semplice di loop attraverso tutte le mie chiavi e la presentazione di una dichiarazione per ciascuno contro ogni tabella, come ad esempio:

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 
... 

Salvo, che esce a 45.000 prospetti separati, che come puoi immaginare è un po 'lento.

Quindi, senza preoccuparmi del linguaggio di programmazione che sto usando sul front-end, quale è un buon modo per inviare l'elenco in modo che possa UNIRE e fare l'operazione tutto in una volta o almeno in grandi lotti? Qui ci sono le mie idee finora:

  • Creare una tabella temporanea e inserire ad esso, poi unire. Guarderò volentieri la sintassi di MySQL per creare una tabella temporanea, ma è una buona strada da percorrere?

  • Supponendo di utilizzare una tabella temporanea, qual è il miglior metodo per compilare una tabella temporanea? 5000 INSERT Table VALUES() dichiarazioni? SELECT 123, 456 UNION ALL SELECT 124, 457? Ho appena provato che MySql consente questo tipo di SELECT che non viene emesso su un tavolo. Ma SQL Server alla fine esploderà se la lista diventa troppo lunga, quindi è un buon modo in MySQL? Devo semplicemente mantenere l'elenco a poche centinaia contemporaneamente?

    --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. Vedo che MySQL 5.1 ha alcune funzioni XML, ma da una ricerca superficiale non sembra supportare la trasformazione di un pezzo di testo XML in un set di righe per unirsi contro. È vero? È estremamente facile per me ottenere i valori in XML.

  • Un virtual split operation. Presumo in MySql che ci sia una sorta di linguaggio procedurale possibile. In SQL Server potrei scrivere del codice personalizzato che analizza una stringa e lo trasforma in un set di righe:

    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 
    

Visto che sono familiarità con MySQL, io davvero non so quale possibilità di indagare prima, e gradirei un po 'di aiuto per salvarmi dal prendere una decisione sbagliata e/o imparare nel modo più duro.

risposta

2

Vorrei utilizzare la soluzione tabella temporanea e unirla a ciascuna tabella principale nelle istruzioni DELETE. Quindi devi solo fare nove eliminazioni, una per ogni tabella.

  • CREATE TEMPORARY TABLE

    CREATE TEMPORARY TABLE Keys (
        Key1 INT UNSIGNED NOT NULL, 
        Key2 INT UNSIGNED NOT NULL, 
        PRIMARY KEY(Key1, Key2) 
    ); 
    
  • caricare un file di dati separati da tabulazione nella tabella temporanea utilizzando LOAD DATA LOCAL INFILE

    LOAD DATA LOCAL INFILE 'C:/path/to/datafile' INTO TABLE Keys; 
    
  • eliminare utilizzando più tabelle DELETE sintassi di MySQL.

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

Re tuo commento:

La documentazione di MySQL su CREATE TABLE dire quanto segue:

una tabella temporanea è visibile solo per la connessione corrente, ed è caduto automaticamente quando la connessione è chiusa. Ciò significa che due diverse connessioni possono utilizzare lo stesso nome di tabella temporaneo senza conflitto tra loro o con una tabella non TEMPORANEA esistente con lo stesso nome. (La tabella esistente è nascosta fino a quando la tabella temporanea non viene rilasciata.)

Questo è abbastanza chiaro!

Per quanto riguarda il caricamento dei dati, è possibile farlo con INSERT. 5000 file non sono un grosso problema. Io uso uno script PHP per caricare milioni di di righe (ad esempio il dump di dati XML StackOverflow) in MySQL e ci vogliono solo circa 20 minuti. Io uso una dichiarazione preparata e poi la eseguo con i parametri.

+0

Grazie Bill, sembra una dinamite. Osserverò il metodo LOAD DATA, anche se non sono sicuro che sarò in grado di scrivere facilmente su un file di questo tipo. C'è un altro modo di script per caricare la tabella temporanea? Inoltre, potresti elaborare solo un poco sull'ambito delle tabelle temporanee (cosa succede se due sessioni cercano di creare una tabella temporanea con lo stesso nome, o il nome esiste già come una tabella reale, e la tabella temporanea viene distrutta quando la connessione chiude)? – ErikE

+0

P.S. USING è bello, vorrei che SQL Server avesse questo. – ErikE

+0

Vorrei poterti dare più di un upvote. Grazie per la profondità e i dettagli della tua risposta. Ammetto che sarei potuto andare a fare ricerche su tutte queste cose (e ho intenzione di farlo ancora) ma una bella risposta rotonda è così grande. – ErikE