web-dev-qa-db-fra.com

Déplacer les données SQL d'une table à une autre

Je me demandais s'il était possible de déplacer toutes les lignes de données d'une table à une autre, correspondant à une requête donnée?

Par exemple, je dois déplacer toutes les lignes de table de Table1 vers Table2, où leur nom d'utilisateur = 'X' et mot de passe = 'X', afin qu'elles n'apparaissent plus dans Table1.

J'utilise SQL Server 2008 Management Studio.

52
doubleplusgood

Doit être possible en utilisant deux instructions dans une transaction, une insertion et une suppression: 

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

DELETE FROM Table1
WHERE <condition>;

COMMIT;

C'est la forme la plus simple. Si vous devez vous soucier des nouveaux enregistrements correspondants insérés dans la table1 entre les deux instructions, vous pouvez ajouter un and exists <in table2>

89
Thorsten

C’est un article ancien, désolé, mais je ne l’ai trouvé que maintenant et je voulais donner ma solution à quiconque pourrait tomber sur ce jour.

Comme certains l'ont mentionné, effectuer INSERT puis DELETE pourrait entraîner des problèmes d'intégrité. Un moyen de contourner le problème et d'exécuter parfaitement toutes les tâches dans une seule instruction consiste à tirer parti de la table temporaire [deleted].

DELETE FROM [source]
OUTPUT [deleted].<column_list>
INTO [destination] (<column_list>)
37
that0th3rGuy

Toutes ces réponses exécutent la même requête pour INSERT et DELETE. Comme mentionné précédemment, cela risquerait que DELETE récupère les enregistrements insérés entre les instructions et pourrait être lent si la requête est complexe (bien que des moteurs intelligents "devraient" effectuer le second appel rapidement).

La bonne façon (en supposant que l'INSERT soit dans une table fraîche) consiste à effectuer la commande DELETE contre table1 en utilisant le champ clé de table2.

La suppression devrait être:

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

Excusez ma syntaxe, je saute de moteur à l’autre, mais vous voyez l’idée.

16
Ken Sands

Oui, ça l'est. D'abord INSERT + SELECT et ensuite DELETE orginals.

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

puis supprimez les orginales

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

vous souhaiterez peut-être conserver UserID ou une autre clé primaire, vous pourrez alors utiliser IDENTITY INSERT pour conserver la clé.

En savoir plus sur SET IDENTITY_INSERT sur MSDN

8
pirho

Vous devriez pouvoir utiliser une sous-requête dans l'instruction INSERT.

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

suivie par la suppression de table1.

N'oubliez pas de l'exécuter en tant que transaction unique afin qu'en cas de problème, vous puissiez annuler toute l'opération.

3
workmad3

Essaye ça

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

Ensuite

DELETE FROM TABLE1 WHERE Criteria
3
Adriaan Stander

Vous pouvez essayer ceci:

SELECT * INTO tbl_NewTableName 
FROM tbl_OldTableName
WHERE Condition1=@Condition1Value

Puis exécutez une suppression simple:

DELETE FROM tbl_OldTableName
WHERE Condition1=@Condition1Value
2
royse41

Une représentation plus claire de ce à quoi certaines autres réponses ont fait allusion:

DELETE sourceTable
OUTPUT DELETED.*
INTO destTable (Comma, separated, list, of, columns)
WHERE <conditions (if any)>
1
GreySage

Voici comment faire avec une seule déclaration

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

EXEMPLE:

    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
1
gpdude_

Utilisez cette instruction SQL unique qui ne présente aucun risque, sans avoir besoin de commettre/annuler des déclarations multiples.

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

Works sur le serveur SQL apporter les modifications appropriées pour MySql 

1
Dheerendra Kulkarni

Si les deux tables utilisent le même ID ou ont une clé UNIQUE commune:

1) Insérer l'enregistrement sélectionné dans le tableau 2

INSERT INTO table2 SELECT * FROM table1 WHERE (conditions)

2) supprimer l'enregistrement sélectionné de la table1 s'il est présent dans la table2

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

Vous pouvez utiliser "Partitionnement logique" pour permuter les données entre les tables:

En mettant à jour la colonne de partition, les données seront automatiquement déplacées vers l'autre table:

voici l'échantillon:

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
abdkok

Il va créer une table et copier toutes les données de l'ancienne table dans la nouvelle table

SELECT * INTO event_log_temp FROM event_log

Et vous pouvez effacer les anciennes données de la table.

DELETE FROM event_log

0