wake-up-neo.com

Wie kopieren Sie einen Datensatz in einer SQL-Tabelle, aber die eindeutige ID der neuen Zeile auslagern?

Diese Frage kommt nahe an das, was ich brauche, aber mein Szenario ist etwas anders. Die Quelltabelle und die Zieltabelle sind identisch und der Primärschlüssel ist ein eindeutiger Bezeichner (GUID). Wenn ich das versuche:

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

Ich bekomme offensichtlich eine Verletzung der Primärschlüsselbeschränkung, da ich versuche, den Primärschlüssel zu kopieren. Eigentlich möchte ich den Primärschlüssel überhaupt nicht kopieren. Ich möchte vielmehr eine neue erstellen. Außerdem möchte ich bestimmte Felder selektiv kopieren und die anderen Felder leer lassen. Um die Angelegenheit komplexer zu gestalten, muss ich den Primärschlüssel des ursprünglichen Datensatzes nehmen und ihn in ein anderes Feld der Kopie einfügen (PreviousId-Feld).

Ich bin sicher, dass es eine einfache Lösung dafür gibt, ich weiß einfach nicht genug TSQL, um zu wissen, was es ist.

110
Kilhoffer

Versuche dies:


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

Alle nicht angegebenen Felder sollten ihren Standardwert erhalten (normalerweise NULL, wenn sie nicht definiert sind).

168
AaronSieb

Ok, ich weiß, dass es eine alte Frage ist, aber ich poste meine Antwort trotzdem.

Ich mag diese Lösung. Ich muss nur die Identitätsspalte (n) angeben.

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;

Die "id" -Spalte ist die Identitätsspalte und dies ist die einzige Spalte, die ich angeben muss. Es ist sowieso besser als umgekehrt. :-)

Ich benutze SQL Server. Sie können "CREATE TABLE" und "UPDATE TABLE" in Zeile 1 und 2 verwenden. Hmm, ich habe gesehen, dass ich nicht wirklich die Antwort gab, die er wollte. Er wollte die ID auch in eine andere Spalte kopieren. Diese Lösung ist jedoch nett, wenn Sie eine Kopie mit einer neuen Auto-ID erstellen.

Ich bearbeite meine Lösung mit den Ideen von 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;

Sie können mehr als eine Spalte löschen, indem Sie sie durch ein "," ..__ trennen. Die: ID sollte durch die ID der Zeile ersetzt werden, die Sie kopieren möchten . MyDatabase, MyTable und IndexField sollten durch Ihre Namen ersetzt werden (Na sicher). 

75
Jonas

Geben Sie alle Felder außer Ihrem ID-Feld an.

INSERT INTO MyTable (FIELD2, FIELD3, ..., FIELD529, PreviousId)
SELECT FIELD2, NULL, ..., FIELD529, FIELD1
FROM MyTable
WHERE FIELD1 = @Id;
9
Scott Bevington

Ich vermute, Sie versuchen zu vermeiden, alle Spaltennamen aufzuschreiben. Wenn Sie SQL Management Studio verwenden, können Sie einfach mit der rechten Maustaste auf die Tabelle und auf Skript als Einfügen klicken. Dann können Sie mit dieser Ausgabe herumspielen, um Ihre Abfrage zu erstellen.

9
Matt Hinze
insert into MyTable (uniqueId, column1, column2, referencedUniqueId)
select NewGuid(), // don't know this syntax, sorry
  column1,
  column2,
  uniqueId,
from MyTable where uniqueId = @Id
2

Wenn "key" Ihr PK-Feld ist und es automatisch ist.

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

es wird ein neuer Datensatz erstellt, wobei Feld1 und Feld2 aus dem ursprünglichen Datensatz kopiert werden

1

Ich weiß, dass meine Antwort zu spät zur Party kommt. Aber die Art, wie ich sie gelöst habe, ist etwas anders als alle Antworten.

Ich hatte eine Situation, ich muss eine Zeile in einer Tabelle außer einigen Spalten klonen. Diese wenigen werden neue Werte haben. Dieser Prozess sollte automatisch für zukünftige Änderungen an der Tabelle unterstützen. Dies bedeutet, dass Sie den Datensatz klonen, ohne Spaltennamen anzugeben. 

Mein Ansatz ist zu

  1. Fragen Sie Sys.Columns ab, um die vollständige Liste der Spalten für die Tabelle abzurufen, und geben Sie die Namen der Spalten ein, die in der where-Klausel übersprungen werden sollen.
  2. Konvertieren Sie das in CSV als Spaltennamen. 
  3. Build Select ... In dieses Skript einfügen.


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
Jeyara

Das kannst du so machen: 

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

Dort anstelle von 112 sollten Sie die maximale ID in der Tabelle DENI/FRIEN01P angeben.

0
Denis Kutlubaev

Ich habe das gleiche Problem, wo ein einzelnes Skript mit einer Tabelle funktionieren soll, deren Spalten regelmäßig von anderen Entwicklern hinzugefügt werden. Nicht nur das, ich unterstütze viele verschiedene Versionen unserer Datenbank, da die Kunden unter Umständen nicht alle mit der aktuellen Version auf dem neuesten Stand sind.

Ich habe die Lösung von Jonas genommen und etwas modifiziert. Dadurch kann ich eine Kopie der Zeile erstellen und dann den Primärschlüssel ändern, bevor er wieder in die ursprüngliche Quelltabelle eingefügt wird. Dies ist auch sehr praktisch für das Arbeiten mit Tabellen, die keine NULL-Werte in Spalten zulassen, und Sie müssen nicht jeden Spaltennamen in INSERT angeben müssen.

Dieser Code kopiert die Zeile für 'ABC' nach 'XYZ'

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

Wenn Sie mit dem Ablegen der Temp-Tabelle fertig sind.

DROP TABLE #TempRow;
0
TonyT

So habe ich es mit ASP classic gemacht und konnte nicht mit den obigen Antworten arbeiten. Ich wollte ein Produkt in unserem System auf eine neue product_id kopieren können und brauchte es selbst wenn wir der Tabelle mehr Spalten hinzufügen.

Cn.Execute("CREATE TEMPORARY TABLE temprow AS SELECT * FROM product WHERE product_id = '12345'")
Cn.Execute("UPDATE temprow SET product_id = '34567'")
Cn.Execute("INSERT INTO product SELECT * FROM temprow")
Cn.Execute("DELETE temprow")
Cn.Execute("DROP TABLE temprow")
0
Daniel Nordh

Meine Tabelle enthält 100 Felder, und ich brauchte eine Abfrage, um nur arbeiten zu können. Jetzt kann ich mit einer grundlegenden bedingten Logik eine beliebige Anzahl von Feldern ausschalten und muss mich nicht um die Ordnungsposition kümmern. 

  1. Ersetzen Sie den folgenden Tabellennamen durch Ihren Tabellennamen

    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. Ersetzen Sie den ursprünglichen Identitätsfeldnamen durch Ihren PK-Feldnamen

    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. Ersetzen Sie die Tabellennamen erneut (sowohl den Zieltabellennamen als auch den Namen der Quellentabelle). Bearbeiten Sie Ihre where-Bedingungen

    SQL = "INSERT INTO TARGET-TABLE-NAME (" & columnListTARGET & ") SELECT " & columnListSOURCE & " FROM SOURCE-TABLE-NAME WHERE (FIELDNAME = FIELDVALUE)" 
    Conn.Execute(SQL)
    
0
Rit Man