Comment copier un enregistrement dans une table SQL mais changer l'id unique de la nouvelle ligne?

cette question est proche de ce dont j'ai besoin, mais mon scénario est légèrement différent. La table source et la table destination sont les mêmes et la clé primaire est un uniqueidentifier (guid). Quand j'essaie ceci:

insert into MyTable
    select * from MyTable where uniqueId = @Id;

j'obtiens évidemment une violation de contrainte de clé primaire, puisque j'essaie de copier sur la clé primaire. En fait, je ne veux pas copier sur la clé primaire. Je veux plutôt en créer un nouveau. En Outre, Je voudrait copier sélectivement sur certains champs, et laisser les autres Nuls. Pour rendre les choses plus complexes, je dois prendre la clé primaire de l'enregistrement original, et l'insérer dans un autre champ de la copie (champ PreviousId).

je suis sûr qu'il y a une solution facile à cela, je ne sais tout simplement pas assez de TSQL pour savoir ce que c'est.

103
demandé sur Community 2008-09-29 21:35:04

10 réponses

essayez ceci:


insert into MyTable(field1, field2, id_backup)
    select field1, field2, uniqueId from MyTable where uniqueId = @Id;

tous les champs Non spécifiés devraient recevoir leur valeur par défaut (qui est généralement nulle lorsqu'elle n'est pas définie).

162
répondu AaronSieb 2008-09-29 20:54:06

Ok, je sais que c'est un vieux problème mais je poste ma réponse quand même.

j'aime cette solution. Je n'ai qu'à spécifier l'identité de la colonne(s).

SELECT * INTO TempTable FROM MyTable_T WHERE id = 1;
ALTER TABLE TempTable DROP COLUMN id;
INSERT INTO MyTable_T SELECT * FROM TempTable;
DROP TABLE TempTable;

la colonne" id " est la colonne identité et c'est la seule colonne que je dois spécifier. C'est mieux que l'inverse de toute façon. :- )

j'utilise SQL Server. Vous pouvez utiliser " CREATE TABLE " et " UPDATE TABLE " aux lignes 1 et 2. Hmm, j'ai vu que je n'ai pas vraiment donner la réponse qu'il voulait. Il voulait aussi copier l'id dans une autre colonne. Mais cette solution est agréable pour faire une copie avec un nouvel auto-id.

j'édite ma solution avec les idées de Michael Dibbets.

use MyDatabase; 
SELECT * INTO #TempTable FROM [MyTable] WHERE [IndexField] = :id;
ALTER TABLE #TempTable DROP COLUMN [IndexField]; 
INSERT INTO [MyTable] SELECT * FROM #TempTable; 
DROP TABLE #TempTable;

Vous pouvez déposer plus d'une colonne en les séparant par des ",". L' :id doit être remplacé par l'id de la ligne que vous souhaitez copier. MyDatabase, MyTable et IndexField doivent être remplacés par vos noms (bien sûr).

69
répondu Jonas 2015-08-19 12:05:11

spécifiez tous les champs sauf votre champ D'identification.

INSERT INTO MyTable (FIELD2, FIELD3, ..., FIELD529, PreviousId)
SELECT FIELD2, NULL, ..., FIELD529, FIELD1
FROM MyTable
WHERE FIELD1 = @Id;
9
répondu Scott Bevington 2008-09-29 17:37:25

je suppose que vous essayez d'éviter d'écrire tous les noms de colonne. Si vous utilisez SQL Management Studio, vous pouvez facilement faire un clic droit sur la table et le Script comme Insert.. ensuite, vous pouvez jouer avec cette sortie pour créer votre requête.

9
répondu Matt Hinze 2009-05-21 19:49:10
insert into MyTable (uniqueId, column1, column2, referencedUniqueId)
select NewGuid(), // don't know this syntax, sorry
  column1,
  column2,
  uniqueId,
from MyTable where uniqueId = @Id
2
répondu Jeffrey L Whitledge 2008-09-29 17:39:42

si " key " est votre champ PK et il est autonome.

insert into MyTable (field1, field2, field3, parentkey)
select field1, field2, null, key from MyTable where uniqueId = @Id

il générera un nouvel enregistrement, copiant field1 et field2 à partir de l'enregistrement original

1
répondu Eduardo Campañó 2008-09-29 17:42:34

vous pouvez faire comme ceci:

INSERT INTO DENI/FRIEN01P 
SELECT 
   RCRDID+112,
   PROFESION,
   NAME,
   SURNAME,
   AGE, 
   RCRDTYP, 
   RCRDLCU, 
   RCRDLCT, 
   RCRDLCD 
FROM 
   FRIEN01P      

il au lieu de 112 vous devriez mettre un nombre de l'id maximum dans le tableau DENI/FRIEN01P.

0
répondu Denis Kutlubaev 2011-08-18 16:54:25

ma table a 100 champs, et j'ai eu besoin d'une requête pour juste travailler. Maintenant je peux désactiver n'importe quel nombre de champs avec une logique conditionnelle de base et ne pas m'inquiéter de sa position ordinale.

  1. remplacer le nom de la table ci-dessous par le nom de la table

    SQLcolums = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE (TABLE_NAME = 'TABLE-NAME')"
    
    Set GetColumns = Conn.Execute(SQLcolums)
    Do WHILE not GetColumns.eof
    
    colName = GetColumns("COLUMN_NAME")
    
  2. remplacer le nom du champ d'identité original par votre nom de champ PK

    IF colName = "ORIGINAL-IDENTITY-FIELD-NAME" THEN ' ASSUMING THAT YOUR PRIMARY KEY IS THE FIRST FIELD DONT WORRY ABOUT COMMAS AND SPACES
        columnListSOURCE = colName 
        columnListTARGET = "[PreviousId field name]"
    ELSE
        columnListSOURCE = columnListSOURCE & colName
        columnListTARGET = columnListTARGET & colName
    END IF
    
    GetColumns.movenext
    
    loop
    
    GetColumns.close    
    
  3. Remplacez de nouveau les noms de table (à la fois le nom de table cible et le nom de table source); éditez votre where conditions

    SQL = "INSERT INTO TARGET-TABLE-NAME (" & columnListTARGET & ") SELECT " & columnListSOURCE & " FROM SOURCE-TABLE-NAME WHERE (FIELDNAME = FIELDVALUE)" 
    Conn.Execute(SQL)
    
0
répondu Rit Man 2013-01-20 18:33:19

j'ai le même problème où je veux qu'un seul script fonctionne avec une table qui a des colonnes ajoutées périodiquement par d'autres développeurs. Non seulement cela, mais je supporte de nombreuses versions différentes de notre base de données car les clients ne sont peut-être pas tous à jour avec la version actuelle.

J'ai pris la solution de Jonas et je l'ai légèrement modifiée. Cela me permet de faire une copie de la rangée et puis de changer la clé primaire avant de l'ajouter de nouveau dans la table source originale. C'est aussi très pratique pour travailler avec des tables qui n'autorisent pas les valeurs nulles dans les colonnes et vous ne voulez pas avoir à spécifier chaque nom de colonne dans L'INSERT.

ce code copie la ligne pour 'ABC' à' XYZ '

SELECT * INTO #TempRow FROM SourceTable WHERE KeyColumn = 'ABC';
UPDATE #TempRow SET KeyColumn = 'XYZ';
INSERT INTO SourceTable SELECT * FROM #TempRow;
DELETE #TempRow;

une fois que vous avez terminé la baisse de la table de température.

DROP TABLE #TempRow;
0
répondu TonyT 2017-09-05 00:02:29

je sais que ma réponse est en retard à la fête. Mais la façon dont j'ai résolu est peu différente de toutes les réponses.

j'ai eu une situation, je dois cloner une rangée dans une table sauf quelques colonnes. Ces quelques aura de nouvelles valeurs. Ce processus devrait prendre automatiquement en charge les modifications futures de la table. Cela implique de cloner l'enregistrement sans spécifier de nom de colonne.

Mon approche est de,

  1. Requête De Sys.Les colonnes pour obtenir la liste complète des colonnes pour le tableau et inclure les noms des colonnes à sauter dans la clause où.
  2. Convertissez cela en CSV comme noms de colonne.
  3. Construire Sélectionner ... Insérez dans le script basé sur ceci.


declare @columnsToCopyValues varchar(max), @query varchar(max)
SET @columnsToCopyValues = ''

--Get all the columns execpt Identity columns and Other columns to be excluded. Say IndentityColumn, Column1, Column2 Select @columnsToCopyValues = @columnsToCopyValues + [name] + ', ' from sys.columns c where c.object_id = OBJECT_ID('YourTableName') and name not in ('IndentityColumn','Column1','Column2') Select @columnsToCopyValues = SUBSTRING(@columnsToCopyValues, 0, LEN(@columnsToCopyValues)) print @columnsToCopyValues

Select @query = CONCAT('insert into YourTableName (',@columnsToCopyValues,', Column1, Column2) select ', @columnsToCopyValues, ',''Value1'',''Value2'',', ' from YourTableName where IndentityColumn =''' , @searchVariable,'''')

print @query exec (@query)

0
répondu Jeyara 2018-06-18 04:55:26