2009-03-17 40 views
33

Tôi có 2 bảng (srcTable1 & destTable) có các lược đồ giống nhau. Tôi đang cố gắng để sao chép tất cả các hàng từ srcTable để destTable và bỏ qua các bản sao. Tôi nghĩ rằng tôi chỉ có thể thêm một mệnh đề WHERE với một truy vấn phụ mà sẽ cho tôi chỉ những hàng không trùng lặp. Tuy nhiên, nó dường như không hoạt động. Tôi không nhận được bất kỳ hàng nào được chèn vào hoặc được chọn.Sao chép các hàng từ bảng này sang bảng khác, bỏ qua các bản sao

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

Tôi nhận ra tôi có thể làm một cái gì đó như thế này:

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

Tuy nhiên, bảng của tôi có nhiều khóa và tôi không thể nghĩ về cách bạn có thể làm điều này với nhiều phím.

Bất kỳ ý tưởng nào tôi đang làm sai hoặc bạn có ý tưởng nào tốt hơn không?

+0

Bạn có thể là một chút cụ thể hơn về những gì bản sao bạn lo lắng về. Có phải lo ngại về việc chèn các hàng từ nguồn đã ở đích, các hàng được sao chép trong nguồn hoặc cả hai? – JohnFx

+0

Bạn đang sử dụng mysql hoặc mssql? –

Trả lời

43

Vấn đề của bạn là bạn cần một mệnh đề where trong subquery xác định những gì làm cho một bản sao:

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

Theo ghi nhận của người trả lời khác, một bên ngoài tham gia có lẽ là một cách tiếp cận ngắn gọn hơn. Ví dụ trên của tôi chỉ là một nỗ lực để giải thích bằng cách sử dụng truy vấn hiện tại của bạn để dễ hiểu hơn. Hoặc là cách tiếp cận có thể làm việc về mặt kỹ thuật.

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 

Cả hai phương pháp trên đều cho rằng bạn đang lo lắng về việc chèn hàng từ nguồn có thể đã đến đích. Nếu bạn thay vì lo ngại về khả năng nguồn có hàng trùng lặp, bạn nên thử một cái gì đó như thế nào.

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

Một điều nữa. Tôi cũng khuyên bạn nên liệt kê các trường cụ thể trên câu lệnh chèn của bạn thay vì sử dụng SELECT *.

+0

Giải pháp đầu tiên của bạn đã làm điều đó. Một JOIN không làm điều đó bởi vì bất kỳ JOIN chỉ trả về các hàng mà 2 bảng có điểm chung. Những gì tôi cần là những hàng mà 2 bảng không có điểm chung. –

+0

Thực ra, Join sẽ hoạt động, nhưng chỉ có một OUTER tham gia. Lưu ý điều kiện d.key1 IS NULL có nghĩa là bạn muốn các hàng chưa được so khớp. Tất nhiên bạn sẽ phải tinh chỉnh điều kiện đó cho những gì chính xác tạo thành một bản sao trong kịch bản của bạn. – JohnFx

+0

@JohnFx Việc tham gia làm việc tốt cho tôi, nơi tôi có một bảng đích với một cấu trúc hơi khác nhau. –

4

Something như thế này ?:

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

Tôi đã thử điều này, nhưng nó không hoạt động. Tham gia, cho dù đó là INNER hay OUTER, sẽ chỉ cho tôi những hàng có 2 bảng chung. Tôi cần những hàng họ không có điểm chung. Tôi vẫn chưa tìm thấy câu trả lời cho điều này. –

+1

Tôi rất vui vì bạn đã tìm thấy thứ gì đó phù hợp với mình, nhưng tuyên bố của bạn là * không * đúng. Một LEFT (OUTER) JOIN sẽ trả về tất cả các hàng từ bảng bên trái, bất kể có một hàng phù hợp trong bảng bên phải hay không. Mệnh đề WHERE loại bỏ tất cả các hàng kết quả trong đó có một kết quả phù hợp. –

2

Bạn đã thử chọn riêng biệt?

INSERT INTO destTable 
SELECT DISTINCT * FROM srcTable 
+0

Tôi đã thử điều này và nó không hoạt động. DISTINCT sẽ cung cấp cho tôi danh sách các hàng riêng biệt trong srcTable. Những gì tôi cần là một danh sách riêng biệt khi 2 bảng được kết hợp. –

0

DISTINCT là từ khóa bạn đang tìm kiếm.

Trong MSSQL, sao chép hàng độc đáo từ một bảng khác có thể được thực hiện như thế này:

SELECT DISTINCT column_name 
INTO newTable 
FROM srcTable 

Các column_name là cột bạn đang tìm kiếm những giá trị độc đáo từ.

Đã kiểm tra và hoạt động.

+0

Điều đó có thể hoạt động nếu tôi đang tạo một bảng mới, nhưng bảng nguồn đã tồn tại, vì vậy nó không hoạt động. –

4

Tôi hy vọng câu hỏi này sẽ giúp bạn

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

Chính xác những gì tôi cần để di chuyển dữ liệu từ phiên bản khung cũ sang phiên bản khung mới nơi một số giá trị đã được đặt và một số giá trị bị thiếu. – JxAxMxIxN

+1

... Mặc dù tôi đã xóa tất cả các dấu '' cho hương vị của trình thông dịch SQL của tôi. – JxAxMxIxN

15

Tôi nhận ra điều này là cũ, nhưng tôi đã ở đây từ google và sau khi xem xét các câu trả lời chấp nhận tôi đã tuyên bố riêng của tôi và nó làm việc cho tôi hy vọng ai đó sẽ tìm thấy nó hữu ích:

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

chỉnh sửa: Đây hoạt động trên MySQL tôi không thử nghiệm trên MSSQL

+2

Điều này chỉ hoạt động với MySQL. – ostrokach

+1

Đối với MySQL, tôi cần thêm sự khác biệt cho điều này. truy vấn đầy đủ: 'INSERT IGNORE INTO destination_table (trường, trường1, trường2) SELECT DISTINCT field, field1, field2 FROM origin_table' – Craicerjack

+0

Điều này làm việc cho tôi. Cảm ơn –

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

Cái lution đã làm việc cho tôi với 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>");} 
} 

}

Các vấn đề liên quan