2009-03-17 5 views
33

У меня есть 2 таблицы (srcTable1 & destTable), которые имеют одинаковые схемы. Я пытаюсь скопировать все строки из srcTable в destTable и игнорировать дубликаты. Я думал, что могу просто добавить предложение WHERE с подзапросом, который даст мне только строки, которые не дублируются. Однако, похоже, это не работает. Я не получаю никаких вставленных или выбранных строк.Копирование строк из одной таблицы в другую, игнорирование дубликатов

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

Я понимаю, что я мог бы сделать что-то вроде этого:

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

Однако мои таблицы имеют несколько ключей, и я не могу думать о том, как вы могли бы сделать это с несколькими ключами.

Любая идея, что я делаю неправильно или у вас есть идеи?

+0

Можете ли вы быть немного более конкретно о том, что дублирует вас беспокоит. Возникает проблема с вставкой строк из источника, которые уже находятся в dest, строки, которые дублируются в источнике, или и то, и другое? – JohnFx

+0

Вы используете mysql или mssql? –

ответ

43

Ваша проблема в том, что вам нужен другой, где положение в подзапрос, который определяет, что делает дубликат:

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

Как отметил другой отвечающего, внешнее соединение, вероятно, является более кратким подход. Мой вышеприведенный пример был просто попыткой объяснить использование вашего текущего запроса, чтобы быть более понятным. Любой подход мог бы технически работать.

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 

Оба вышеуказанных подхода предполагают, что вас беспокоит вставка строк из источника, который уже может быть в месте назначения. Если вас беспокоит возможность того, что источник имеет повторяющиеся строки, вы должны попробовать что-то вроде этого.

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

Еще одна вещь. Я также предлагаю указать конкретные поля в инструкции insert вместо использования SELECT *.

+0

Ваше первое решение. JOIN не делает этого, потому что любой JOIN возвращает только строки, которые имеют две таблицы. Мне нужны строки, в которых нет двух таблиц. –

+0

На самом деле Join будет работать, но только OUTER присоединяется. Обратите внимание на условие, что d.key1 IS NULL означает, что вы хотите иметь непревзойденные строки. Конечно, вам нужно будет настроить это условие на то, что именно представляет собой дубликат в вашем сценарии. – JohnFx

+0

@JohnFx Присоединение хорошо сработало для меня, где у меня есть таблица назначения с немного другой структурой. –

4

Нечто подобное ?:

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

Я пробовал это, но он не работает. Присоединение, будь то INNER или OUTER, даст мне только строки, которые имеют 2 таблицы. Мне нужны строки, которые у них нет общего. Я до сих пор не нашел ответа на это. –

+1

Я рад, что вы нашли что-то, что работает для вас, но ваше утверждение неверно. LEFT (OUTER) JOIN возвращает все строки из левой таблицы, независимо от того, есть ли соответствующая строка в правой таблице. Предложение WHERE исключает все результирующие строки, где есть совпадение. –

2

Пытались SELECT DISTINCT вы?

INSERT INTO destTable 
SELECT DISTINCT * FROM srcTable 
+0

Я пробовал это, и он не работает. DISTINCT предоставит мне список различных строк в srcTable. Мне нужен отдельный список, когда две таблицы объединены. –

0

DISTINCT - ключевое слово, которое вы ищете.

В MSSQL, копирование уникальных строк из таблицы в другую можно сделать так:

SELECT DISTINCT column_name 
INTO newTable 
FROM srcTable 

column_name является столбцом вы ищете уникальные значения из.

Протестировано и работает.

+0

Это может сработать, если я создаю новую таблицу, но исходная таблица уже существует, поэтому она не работает. –

4

Я надеюсь, что этот вопрос поможет вам

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

Точно, что мне нужно для переноса данных из старой версии фреймворка в новую версию фреймворка, где некоторые из значений уже были установлены, а некоторые отсутствовали. – JxAxMxIxN

+1

... Хотя я удалил все «знаки для моего вкуса интерпретатора SQL». – JxAxMxIxN

15

Я понимаю, что это старый, но я попал сюда из Google и после рассмотрения принятого ответа я сделал свое собственное заявление, и она работала для меня надеюсь кто-то найдет это полезно:

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

Edit: Это работает на MySQL я не проверял на MSSQL

+2

Это работает только с MySQL. – ostrokach

+1

Для MySQL мне нужно было добавить отличный от этого. полный запрос: 'INSERT IGNORE INTO destination_table (поле, поле1, поле2) Поле SELECT DISTINCT, поле1, поле2 FROM origin_table' – Craicerjack

+0

Это сработало для меня. благодаря –

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

так который работал для меня с 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>");} 
} 

}

Смежные вопросы