MySQL: Comment copier des lignes, mais modifier quelques champs?

195

J'ai un grand nombre de lignes que je voudrais copier, mais je dois changer un champ.

Je peux sélectionner les lignes que je souhaite copier:

select * from Table where Event_ID = "120"

Maintenant, je veux copier toutes ces lignes et créer de nouvelles lignes tout en définissant le Event_IDsur 155. Comment puis-je accomplir cela?

Andrew
la source

Réponses:

279
INSERT INTO Table
          ( Event_ID
          , col2
           ...
          )
     SELECT "155"
          , col2
           ...
      FROM Table WHERE Event_ID = "120"

Ici, le col2, ... représente les colonnes restantes (celles autres que Event_ID) dans votre table.

dcp
la source
39
y a-t-il un moyen de le faire sans avoir à spécifier les noms de colonne?
Andrew
4
Pas que je sache. Bien sûr, si votre table a comme 1000 colonnes ou quelque chose et que vous ne voulez pas les taper toutes, alors vous pouvez écrire une instruction SQL pour construire votre instruction SQL :). La façon dont vous le feriez serait d'utiliser le schéma_information pour obtenir les noms de colonne de la table. Mais c'est vraiment exagéré, je taperais simplement les noms des colonnes.
dcp
3
Serait-ce possible d'utiliser un astérisque pour obtenir les colonnes restantes?
Peter
2
Connectez-vous pour voter pour savoir que j'ai déjà ce vote positif. Je suppose que cela m'a sauvé plusieurs fois maintenant :) Merci!
aexl
2
@Bitterblue - Désolé, je ne comprends pas votre commentaire. Je n'ai jamais dit col2, ... étaient des colonnes que vous ne voulez pas copier, je viens de dire qu'elles représentent les colonnes restantes du tableau. Il est évident qu'ils seront copiés, sinon ils ne figureraient pas du tout dans l'instruction SQL.
dcp
141

C'est une solution où vous avez de nombreux champs dans votre table et que vous ne voulez pas avoir une crampe au doigt en tapant tous les champs, tapez simplement ceux dont vous avez besoin :)

Comment copier certaines lignes dans la même table, avec certains champs ayant des valeurs différentes:

  1. Créez une table temporaire avec toutes les lignes que vous souhaitez copier
  2. Mettez à jour toutes les lignes de la table temporaire avec les valeurs souhaitées
  3. Si vous avez un champ d'incrémentation automatique, vous devez le définir sur NULL dans la table temporaire
  4. Copiez toutes les lignes de la table temporaire dans votre table d'origine
  5. Supprimer la table temporaire

Votre code:

CREATE table temporary_table AS SELECT * FROM original_table WHERE Event_ID="155";

UPDATE temporary_table SET Event_ID="120";

UPDATE temporary_table SET ID=NULL

INSERT INTO original_table SELECT * FROM temporary_table;

DROP TABLE temporary_table

Code de scénario général:

CREATE table temporary_table AS SELECT * FROM original_table WHERE <conditions>;

UPDATE temporary_table SET <fieldx>=<valuex>, <fieldy>=<valuey>, ...;

UPDATE temporary_table SET <auto_inc_field>=NULL;

INSERT INTO original_table SELECT * FROM temporary_table;

DROP TABLE temporary_table

Code simplifié / condensé:

CREATE TEMPORARY TABLE temporary_table AS SELECT * FROM original_table WHERE <conditions>;

UPDATE temporary_table SET <auto_inc_field>=NULL, <fieldx>=<valuex>, <fieldy>=<valuey>, ...;

INSERT INTO original_table SELECT * FROM temporary_table;

Comme la création de la table temporaire utilise le TEMPORARYmot - clé, elle sera automatiquement supprimée à la fin de la session (comme @ ar34z suggéré).

Alex Christodoulou
la source
7
MySQL prend en charge le TEMPORARYmot - clé pour créer des tables temporaires. L'utilisation de CREATE TEMPORARY TABLEsupprimera automatiquement la table lorsque la session (une série de requêtes SQL) est terminée. La suppression de la table ne serait pas nécessaire et elle n'entre pas en conflit avec d'autres tables temporaires utilisant le même nom. (par exemple, lors du piratage en direct (que je ne recommanderais pas))
ar34z
1
ce code ne fonctionne que si vous utilisez #temporary_table au lieu de temporaire_table, peut-être un problème MSSQL?
TruthOf42
16
Cela a fonctionné parfaitement pour moi, mais j'ai dû surmonter une contrainte Not Null sur la clé primaire dans la table temporaire qui semble être copiée à partir de la table d'origine. J'ai corrigé cela en modifiant la table temporaire avant la mise à jour comme suit: ALTER TABLE temporary_table MODIFY <auto_inc_not_null_field> INT; Ensuite, la mise à jour de la clé primaire sur Null n'échouerait pas.
snorris du
1
Je ne peux pas le faire fonctionner dans PostgreSQL 9.4: Exception: null value in column <auto_inc_not_null_field> violates not-null constraint. J'ai essayéALTER TABLE temporary_table ALTER COLUMN <auto_inc_not_null_field> DROP NOT NULL;
n1000
1
J'ai testé avec différentes versions de MySQL et MariaDB. Fonctionne parfaitement pour moi et je préfère cette version à la réponse acceptée, ce qui arrive assez souvent ici :)
logiciel hexerei
41

Disons que votre table a deux autres colonnes: foo et bar

INSERT INTO Table (foo, bar, Event_ID)
SELECT foo, bar, "155"
  FROM Table
 WHERE Event_ID = "120"
Peter Bailey
la source
4
y a-t-il un moyen de le faire sans avoir à spécifier les noms de colonne?
Andrew
@PeterBailey Nouveau sur MySQL, pourriez-vous s'il vous plaît nous éclairer sur le fonctionnement du code: /
3kstc
10

Si vous avez beaucoup de colonnes dans votre table et que vous ne voulez pas taper chacune d'elles, vous pouvez le faire en utilisant une table temporaire, comme;

SELECT *
INTO #Temp
FROM Table WHERE Event_ID = "120"
GO

UPDATE #TEMP
SET Column = "Changed"
GO

INSERT INTO Table
SELECT *
FROM #Temp
Davethebfg
la source
6
une note: cela suppose que vous n'avez pas de clé primaire dans votre table
kommradHomer
2

Hey que diriez-vous de copier tous les champs, changez l'un d'entre eux avec la même valeur + autre chose.

INSERT INTO Table (foo, bar, Event_ID)
SELECT foo, bar, Event_ID+"155"
  FROM Table
 WHERE Event_ID = "120"

??????????

Dimitar
la source
0

Tant que Event_ID est Integer, procédez comme suit:

INSERT INTO Table (foo, bar, Event_ID)
SELECT foo, bar, (Event_ID + 155)
  FROM Table
WHERE Event_ID = "120"
axel.becker
la source