2009-10-23 15 views
40

Zastanawiam się, czy możliwe jest przeniesienie wszystkich wierszy danych z jednej tabeli do drugiej, które pasują do określonego zapytania?Przenieś dane SQL z jednej tabeli do drugiej

Na przykład muszę przenieść wszystkie wiersze tabeli z tabeli 1 do tabeli 2, gdzie ich nazwa użytkownika = "X" i hasło = "X", tak aby nie były już wyświetlane w tabeli 1.

Używam programu SQL Server 2008 Management Studio.

Dziękuję.

+0

Hej chłopaki, dziękuję bardzo za szybką odpowiedź. Bardzo doceniane. – doubleplusgood

Odpowiedz

70

Powinno być możliwe przy użyciu dwóch sprawozdań w ciągu jednej transakcji, wkładki oraz kasowania:

INSERT INTO Table2 (<columns>) 
SELECT <columns> 
FROM Table1 
WHERE <condition>; 

DELETE FROM Table1 
WHERE <condition>; 

COMMIT; 

Jest to najprostsza forma. Jeśli musisz się martwić o nowe pasujące rekordy wstawiane do tabeli1 między dwiema instrukcjami, możesz dodać and exists <in table2>.

+1

chcesz, aby oba oświadczenia były wykonywane jako pojedyncza transakcja. Aby powiedzieć, wyłącz automatyczne zatwierdzanie i wykonaj pojedyncze zatwierdzenie po usunięciu, tylko jeśli nie wystąpiły błędy. Prawdopodobnie nie chcesz usuwać, jeśli wstawianie się nie powiedzie, lub na odwrót. – Jay

+0

To prawda, ale nawet jeśli są wykonywane jako pojedyncza transakcja, mogą wystąpić problemy z wstawianiem wystąpień podczas wykonywania dwóch instrukcji. Nie zbyt wiele baz danych jest uruchamianych w taki sposób, aby "odczyty były powtarzalne" w ramach transakcji. – Thorsten

+0

Wydaje mi się, że możesz użyć "USTAWIENIA POZIOMU ​​PRZEJŚCIU TRANSAKCJI PRZEZ SERIALIZABLE" dla transakcji, aby upewnić się, że nie widzisz nowych rekordów. –

2

Spróbuj

INSERT INTO TABLE2 (Cols...) SELECT Cols... FROM TABLE1 WHERE Criteria 

Następnie

DELETE FROM TABLE1 WHERE Criteria 
3

powinien być w stanie z podzapytania w INSERT.

INSERT INTO table1(column1, column2) SELECT column1, column2 FROM table2 WHERE ...; 

a następnie usunięcie z tabeli1.

Pamiętaj, aby uruchamiać go jako pojedynczą transakcję, więc jeśli coś pójdzie nie tak, możesz wycofać całą operację.

8

Tak jest. Najpierw INSERT + SELECT, a następnie DELETE orginals.

INSERT INTO Table2 (UserName,Password) 
SELECT UserName,Password FROM Table1 WHERE UserName='X' AND Password='X' 

następnie usunąć orginals

DELETE FROM Table1 WHERE UserName='X' AND Password='X' 

może chcesz zachować UserID lub someother klucz podstawowy, a następnie można użyć IDENTITY INSERT zachować klucz.

see more on SET IDENTITY_INSERT on MSDN

15

Wszystkie te odpowiedzi uruchomić tę samą kwerendę dla wstawiania i usuwania. Jak wspomniano wcześniej, istnieje ryzyko usunięcia rekordów wstawianych między instrukcjami i może być powolne, jeśli zapytanie jest złożone (chociaż sprytne silniki "powinny" szybko wykonać drugie połączenie).

Prawidłowy sposób (zakładając, że INSERT ma świeżą tabelę), należy wykonać DELETE względem tabeli 1, używając pola klucza w tabeli2.

delete powinno być:

DELETE FROM tbl_OldTableName WHERE id in (SELECT id FROM tbl_NewTableName) 

wybaczyć składnia, ja skaczę pomiędzy silnikami, ale masz pomysł.

29

To jest starożytny post, przepraszam, ale natknąłem się tylko na to teraz i chciałem dać moje rozwiązanie każdemu, kto mógłby natknąć się na ten jeden dzień.

Jak niektórzy wspominali, wykonywania INSERT a potem DELETE może doprowadzić do problemów z integralnością, więc może to sposób, aby dostać się wokół niego, i wykonywać wszystko starannie w jednym rachunku, jest skorzystanie z tabeli tymczasowej [deleted] .

DELETE FROM [source] 
OUTPUT [deleted].<column_list> 
INTO [destination] (<column_list>) 
+0

Nigdy nie usunąłbym żadnej zawartości przed dodaniem jej tam, gdzie jej potrzebuję. Jeśli coś pójdzie nie tak, to może być trudne do wymyślenia! – d00dle

+2

Za pomocą instrukcji "DELETE" wszystkie rekordy są najpierw zapisywane w tabeli tymczasowej '[usunięto]', zanim klauzula "DELETE" zostanie rozwiązana, skąd mogą być przetwarzane - w tym przypadku wstawiona do innej tabeli - po czym oświadczenie rozwiązuje. Jeśli sekcja przetwarzania instrukcji nie powiedzie się, całe oświadczenie zostanie zakończone; nie tylko klauzula "INTO". Poza tym "BEGIN TRY ... BEGIN CATCH" i "TRANSAKCJA ROLLBACK" to świetne instrukcje zapobiegawcze. – that0th3rGuy

+5

Spowoduje to problemy, jeśli miejsce docelowe jest zaangażowane w relacje klucza obcego. Otrzymasz błąd: Tabela docelowa "" klauzuli OUTPUT INTO nie może znajdować się po obu stronach relacji (klucz podstawowy, klucz obcy). Znaleziono ograniczenie odniesienia "". –

0

Jeśli dwie tabele używać tego samego identyfikatora lub mają wspólny klucz wyjątkowy:

1) Wstawić wybrany rekord w tabeli 2

INSERT INTO table2 SELECT * FROM table1 WHERE (conditions) 

2) usunąć wybrany rekord z Tabela1 jeśli przedstawia w Table2

DELETE FROM table1 as A, table2 as B WHERE (A.conditions) AND (A.ID = B.ID) 
2

Oto jak to zrobić z jednej instrukcji

WITH deleted_rows AS (
DELETE FROM source_table WHERE id = 1 
RETURNING * 
) 
INSERT INTO destination_table 
SELECT * FROM deleted_rows; 

PRZYKŁAD:

postgres=# select * from test1 ; 
id | name 
----+-------- 
    1 | yogesh 
    2 | Raunak 
    3 | Varun 
(3 rows) 


postgres=# select * from test2; 
id | name 
----+------ 
(0 rows) 


postgres=# WITH deleted_rows AS (
postgres(# DELETE FROM test1 WHERE id = 1 
postgres(# RETURNING * 
postgres(#) 
postgres-# INSERT INTO test2 
postgres-# SELECT * FROM deleted_rows; 
INSERT 0 1 


postgres=# select * from test2; 
id | name 
----+-------- 
    1 | yogesh 
(1 row) 

postgres=# select * from test1; 
id | name 
----+-------- 
    2 | Raunak 
    3 | Varun 
0

Można użyć "logiczne partycjonowanie" przełączyć danych między tabelami:

Poprzez aktualizację Kolumna partycji, dane będą automatycznie przenoszone do druga tabela:

tutaj jest próbka:

CREATE TABLE TBL_Part1 
(id INT NOT NULL, 
val VARCHAR(10) NULL, 
PartitionColumn VARCHAR(10) CONSTRAINT CK_Part1 CHECK(PartitionColumn = 'TBL_Part1'), 
CONSTRAINT TBL_Part1_PK PRIMARY KEY(PartitionColumn, id) 
); 

CREATE TABLE TBL_Part2 
(id INT NOT NULL, 
val VARCHAR(10) NULL, 
PartitionColumn VARCHAR(10) CONSTRAINT CK_Part2 CHECK(PartitionColumn = 'TBL_Part2'), 
CONSTRAINT TBL_Part2_PK PRIMARY KEY(PartitionColumn, id) 
); 

GO 

CREATE VIEW TBL(id, val, PartitionColumn) 
WITH SCHEMABINDING 
AS 
    SELECT id, val, PartitionColumn FROM dbo.TBL_Part1 
    UNION ALL 
    SELECT id, val, PartitionColumn FROM dbo.TBL_Part2; 

GO 

--Insert sample to TBL (will be inserted to Part1) 
INSERT INTO TBL 
VALUES(1, 'rec1', 'TBL_Part1'); 

INSERT INTO TBL 
VALUES(2, 'rec2', 'TBL_Part1'); 

GO 

--Query sub table to verify 
SELECT * FROM TBL_Part1 

GO 
--move the data to table TBL_Part2 by Logical Partition switching technique 
UPDATE TBL 
    SET 
     PartitionColumn = 'TBL_Part2'; 

GO 

--Query sub table to verify 
SELECT * FROM TBL_Part2 
0

Użyj tej pojedynczej instrukcji SQL, która jest bezpieczna bez potrzeby zatwierdzania/wycofywania z wieloma instrukcjami.

INSERT Table2 (
     username,password 
) SELECT username,password 
     FROM (
      DELETE Table1 
      OUTPUT 
        DELETED.username, 
        DELETED.password 
      WHERE username = 'X' and password = 'X' 
    ) AS RowsToMove ; 

Prace nad serwerem SQL dokonać odpowiednich zmian dla MySQL

Powiązane problemy