82 votes

MYSQL : Comment copier une ligne entière d'une table à une autre dans mysql avec la deuxième table ayant une colonne supplémentaire ?

J'ai deux tables dont la structure est identique à l'exception d'une colonne... La table 2 possède une colonne supplémentaire dans laquelle je dois insérer le CURRENT_DATE().

Je voudrais copier toutes les valeurs de la table 1 vers la table 2.

si j'utilise

INSERT INTO dues_storage SELECT * FROM dues WHERE id=5;

il jette une erreur signalant la différence dans le nombre de colonnes.

J'ai deux questions à ce sujet :

  1. Comment puis-je contourner ce problème ?
  2. et comment ajouter la valeur de la colonne de date supplémentaire (CURRENT_DATE()) dans le tableau 2 dans cette même déclaration ?

0 votes

Vous pourriez jeter un coup d'oeil à ça. Cela a fonctionné pour moi dans mysql. stackoverflow.com/questions/57168/

107voto

crunchdog Points 3068

Pour affiner la réponse de Zed, et pour répondre à votre commentaire :

INSERT INTO dues_storage
SELECT d.*, CURRENT_DATE()
FROM dues d
WHERE id = 5;

Voir le commentaire de T.J. Crowder

58 votes

Soyez TRES PRUDENT en faisant cela. Cela fonctionne, mais cela suppose que l'ordre des colonnes dans les deux tables est identique ; il ne s'agit pas de no correspond au nom de la colonne, et essaie de forcer les valeurs à s'adapter, ce qui peut provoquer des résultats inattendus. Maintenant, si votre structure de développement garantit que les ordres des colonnes sont identiques jusqu'à la dernière colonne, c'est un moyen pratique et direct de le faire, mais la mise en garde est importante.

0 votes

Heureusement, l'ordre est le même. Je garderai à l'esprit de garder la structure identique même à l'avenir. merci à tous !

0 votes

@crunchdog comment la requête devrait être organisée si j'ai besoin d'établir where comme A.id = B.id ?

58voto

paxdiablo Points 341644

La façon la plus sûre de procéder est de spécifier complètement les colonnes à la fois pour l'insertion et l'extraction. Il n'y a aucune garantie (pour l'application) que l'une ou l'autre sera dans l'ordre auquel vous pensez.

insert into dues_storage (f1, f2, f3, cd)
    select f1, f2, f3, current_date() from dues where id = 5;

Si vous craignez de devoir modifier plusieurs pages PHP qui font cela (comme vous semblez l'indiquer dans le commentaire d'une autre réponse), c'est le moment d'utiliser une procédure stockée. De cette façon, toutes vos pages PHP appellent simplement la procédure stockée avec (par exemple) juste l'ID à copier et elle contrôle le processus de copie réel. De cette façon, il n'y a qu'un seul endroit où vous devez maintenir le code, et, à mon avis, le SGBD est le bon endroit pour le faire.

0 votes

Oui mais je commence à peine. Je dois maintenant découvrir ce que sont les procédures stockées, merci ! Une chose de plus à apprendre aujourd'hui !

1 votes

C'est la meilleure réponse

0 votes

Pour le peu de travail supplémentaire, CETTE SOLUTION offre la protection ultime. Vous ne regretterez pas de l'avoir fait dès le départ.

8voto

Zed Points 27408
INSERT INTO dues_storage
SELECT field1, field2, ..., fieldN, CURRENT_DATE()
FROM dues
WHERE id = 5;

0 votes

Il y a tellement de champs dans la table, y a-t-il un moyen plus court ? Si je modifie la structure de la table à cet endroit, je devrai penser à modifier les pages php également.

0 votes

Vous pouvez l'échapper avec dues.*

5voto

Josh Strike Points 31

J'espère que cela pourra aider quelqu'un... Voici un petit script PHP que j'ai écrit au cas où vous auriez besoin de copier certaines colonnes mais pas d'autres, et/ou les colonnes ne sont pas dans le même ordre sur les deux tables. Tant que les colonnes portent le même nom, cela fonctionnera. Donc, si la table A a [userid, handle, quelque chose] et la table B a [userID, handle, timestamp], alors vous devriez "SELECT userID, handle, NOW() as timestamp FROM tableA", puis obtenir le résultat de cette opération, et passer le résultat comme premier paramètre à cette fonction ($z). $toTable est un nom de chaîne pour la table vers laquelle vous copiez, et $link_identifier est le db vers lequel vous copiez. C'est relativement rapide pour les petits ensembles de données. Il n'est pas recommandé d'essayer de déplacer plus de quelques milliers de lignes à la fois de cette façon dans un environnement de production. Je l'utilise principalement pour sauvegarder les données collectées au cours d'une session lorsqu'un utilisateur se déconnecte, puis j'efface immédiatement les données de la base de données active pour la garder mince.

 function mysql_multirow_copy($z,$toTable,$link_identifier) {
            $fields = "";
            for ($i=0;$i<mysql_num_fields($z);$i++) {
                if ($i>0) {
                    $fields .= ",";
                }
                $fields .= mysql_field_name($z,$i);
            }
            $q = "INSERT INTO $toTable ($fields) VALUES";
            $c = 0;
            mysql_data_seek($z,0); //critical reset in case $z has been parsed beforehand. !
            while ($a = mysql_fetch_assoc($z)) {
                foreach ($a as $key=>$as) {
                    $a[$key] = addslashes($as);
                    next ($a);
                }
                if ($c>0) {
                    $q .= ",";
                }
                $q .= "('".implode(array_values($a),"','")."')";
                $c++;
            }
            $q .= ";";
            $z = mysql_query($q,$link_identifier);
            return ($q);
        }

-1voto

infocs Points 4

J'ai essayé ce que vous avez dit mais je reçois un message disant qu'il y a un problème avec la clause where.

C'est ce que j'ai essayé :

 INSERT INTO `seller` SELECT  FROM `seller_test` WHERE
`s_code`=11;

erreur :

> #1064 - You have an error in your SQL syntax; check the manual that corresponds to your   MySQL server version for the right syntax to use
> near 'FROM `seller` WHERE `s_code`=11' at line 1

mais quand j'ai ajouté le * après le mot clé SELECT, la requête est devenue comme ceci :

INSERT INTO `seller` SELECT ***** FROM `seller_test` WHERE
`s_code`=11;

j'obtiens un bon résultat essayez donc d'ajouter * après le mot clé SELECT

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X