2009-03-17 29 views
33

Ho due tabelle (srcTable1 & destTable) con schemi identici. Sto cercando di copiare tutte le righe da srcTable a destTable e di ignorare i duplicati. Ho pensato di aggiungere una clausola WHERE con una sottoquery che mi avrebbe dato solo le righe che non sono duplicate. Tuttavia, non sembra funzionare. Non ottengo nessuna riga inserita o selezionata.Copia righe da una tabella a un'altra, ignorando i duplicati

INSERT INTO destTable 
SELECT * FROM srcTable 
WHERE NOT EXISTS(SELECT * FROM destTable) 

mi rendo conto che potrei fare qualcosa di simile:

INSERT INTO destTable 
SELECT * FROM srcTable 
WHERE MyKey IN (SELECT MyKey FROM destTable) 

Tuttavia, le mie tabelle avere più chiavi e non posso pensare a come si potrebbe fare questo con più chiavi.

Qualche idea su cosa sto facendo male o hai qualche idea migliore?

+0

si può essere un po 'più specifico su ciò che i duplicati si sono preoccupati. La preoccupazione relativa all'inserimento di righe dall'origine già presenti in dest, righe duplicate nell'origine o entrambe? – JohnFx

+0

Stai usando mysql o mssql? –

risposta

43

Il tuo problema è che è necessario un altro dove clausola nel subquery che identifica ciò che rende un duplicato:

INSERT INTO destTable 
SELECT Field1,Field2,Field3,... 
FROM srcTable 
WHERE NOT EXISTS(SELECT * 
       FROM destTable 
       WHERE (srcTable.Field1=destTable.Field1 and 
         SrcTable.Field2=DestTable.Field2...etc.) 
       ) 

Come notato da un altro risposto, un outer join è probabilmente un approccio più concisa. Il mio esempio precedente era solo un tentativo di spiegare usando la tua query corrente per essere più comprensibile. Entrambi gli approcci potrebbero tecnicamente funzionare.

INSERT INTO destTable 
SELECT s.field1,s.field2,s.field3,... 
FROM srcTable s 
     LEFT JOIN destTable d ON (d.Key1 = s.Key1 AND d.Key2 = s.Key2 AND...) 
WHERE d.Key1 IS NULL 

Entrambi gli approcci riportati sopra presuppongono che si sia preoccupati di inserire righe da origine che potrebbero già essere nella destinazione. Se invece sei preoccupato della possibilità che la fonte abbia righe duplicate dovresti provare qualcosa di simile.

INSERT INTO destTable 
SELECT Distinct field1,field2,field3,... 
FROM srcTable 

Un'altra cosa. Vorrei anche suggerire di elencare i campi specifici sulla tua istruzione di inserimento invece di usare SELECT *.

+0

La tua prima soluzione ha funzionato. Un JOIN non lo fa perché qualsiasi JOIN restituisce solo le righe che le 2 tabelle hanno in comune. Ciò di cui ho bisogno sono le righe che i 2 tavoli non hanno in comune. –

+0

In realtà il join funzionerà, ma solo un join ESTERNO. Si noti la condizione che d.key1 IS NULL significhi che si vogliono le righe non corrispondenti. Ovviamente dovresti modificare questa condizione per ciò che costituisce esattamente un duplicato nel tuo scenario. – JohnFx

+0

@JohnFx Il join ha funzionato bene per me, dove ho una tabella di destinazione con una struttura leggermente diversa. –

4

Qualcosa di simile ?:

INSERT INTO destTable 
SELECT s.* FROM srcTable s 
LEFT JOIN destTable d ON d.Key1 = s.Key1 AND d.Key2 = s.Key2 AND... 
WHERE d.Key1 IS NULL 
+0

Ho provato questo, ma non funziona. Un join, che sia INNER o OUTER, mi darà solo le righe che i 2 tavoli hanno in comune. Ho bisogno delle righe che non hanno in comune. Non ho ancora trovato risposta a questo. –

+1

Sono felice che tu abbia trovato qualcosa che funzioni per te, ma la tua affermazione è * non * corretta. A SINISTRA (OUTER) JOIN restituirà tutte le righe dalla tabella di sinistra, indipendentemente dal fatto che ci sia una riga corrispondente nella tabella di destra. La clausola WHERE elimina tutte le righe risultanti in cui esiste una corrispondenza. –

2

Hai provato SELEZIONA distinti?

INSERT INTO destTable 
SELECT DISTINCT * FROM srcTable 
+0

Ho provato questo e non funziona. DISTINCT mi fornirà un elenco di righe distinte nella tabella src. Quello di cui ho bisogno è una lista distinta quando le 2 tabelle sono combinate. –

0

DISTINCT è la parola chiave che stai cercando.

In MSSQL, copiando righe uniche da una tabella ad un altro può essere fatto in questo modo:

SELECT DISTINCT column_name 
INTO newTable 
FROM srcTable 

Il column_name è la colonna che si sta cercando i valori univoci da.

Testato e funziona.

+0

Potrebbe funzionare se stessimo creando una nuova tabella, ma la tabella di origine esiste già, quindi non funziona. –

4

Spero che questa query vi aiuterà a

INSERT INTO `dTable` (`field1`, `field2`) 
SELECT field1, field2 FROM `sTable` 
WHERE `sTable`.`field1` NOT IN (SELECT `field1` FROM `dTable`) 
+1

Esattamente ciò di cui avevo bisogno per la migrazione dei dati da una vecchia versione di framework in una nuova versione di framework in cui alcuni dei valori erano già stati impostati e alcuni erano mancanti. – JxAxMxIxN

+1

... Anche se ho rimosso tutti i '' marchi per il mio sapore dell'interprete SQL. – JxAxMxIxN

15

Mi rendo conto che è vecchio, ma sono arrivato qui da Google e dopo aver esaminato la risposta accettata ho fatto la mia dichiarazione e ha funzionato per me spero che qualcuno troverà utile:

INSERT IGNORE INTO destTable SELECT id, field2,field3... FROM origTable 

Edit: Questo funziona su MySQL non ho la prova su MSSQL

+2

Funziona solo con MySQL. – ostrokach

+1

Per MySQL ho bisogno di aggiungere distinti a questo. query completa: 'INSERISCI IGNORE IN destinazione_table (campo, campo1, campo2) SELEZIONA campo DISTINCT, campo1, campo2 FROM tabella_origine ' – Craicerjack

+0

Questo ha funzionato per me. Grazie –

1
insert into tbl2 
select field1,field2,... from tbl1 
where not exists 
    ( 
     select field1,field2,... 
     from person2 
     where (tbl1.field1=tbl2.field1 and 
     tbl1.field2=tbl2.field2 and .....) 
    ) 
0

Il modo che ha funzionato per me con PHP/PDO.

public function createTrainingDatabase($p_iRecordnr){ 
// Methode: Create an database envirioment for a student by copying the original 
// @parameter: $p_iRecordNumber, type:integer, scope:local 
// @var: $this->sPdoQuery,   type:string, scope:member 
// @var: $bSuccess,     type:boolean, scope:local 
// @var: $aTables,     type:array,  scope:local 
// @var: $iUsernumber,    type:integer, scope:local 
// @var: $sNewDBName,    type:string, scope:local 
// @var: $iIndex,     type:integer, scope:local 

// -- Create first the name of the new database -- 
$aStudentcard = $this->fetchUsercardByRecordnr($p_iRecordnr); 
$iUserNumber = $aStudentcard[0][3]; 
$sNewDBName = $_SESSION['DB_name']."_".$iUserNumber; 
// -- Then create the new database -- 
$this->sPdoQuery = "CREATE DATABASE `".$sNewDBName."`;"; 
$this->PdoSqlReturnTrue(); 
// -- Create an array with the tables you want to be copied -- 
$aTables = array('1eTablename','2ndTablename','3thTablename'); 
// -- Populate the database -- 
for ($iIndex = 0; $iIndex < count($aTables); $iIndex++) 
{ 
// -- Create the table -- 
    $this->sPdoQuery = "CREATE TABLE `".$sNewDBName."`.`".$aTables[$iIndex]."` LIKE `".$_SESSION['DB_name']."`.`".$aTables[$iIndex]."`;"; 
    $bSuccess = $this->PdoSqlReturnTrue(); 
    if(!$bSuccess){echo("Could not create table: ".$aTables[$iIndex]."<BR>");} 
    else{echo("Created the table ".$aTables[$iIndex]."<BR>");} 
    // -- Fill the table -- 
    $this->sPdoQuery = "REPLACE `".$sNewDBName."`.`".$aTables[$iIndex]."` SELECT * FROM `".$_SESSION['DB_name']."`.`".$aTables[$iIndex]."`"; 
    $bSuccess = $this->PdoSqlReturnTrue(); 
    if(!$bSuccess){echo("Could not fill table: ".$aTables[$iIndex]."<BR>");} 
    else{echo("Filled table ".$aTables[$index]."<BR>");} 
} 

}

Problemi correlati