Bir SQL tablosundaki bir kaydı nasıl kopyalarsınız ancak yeni satırın benzersiz kimliğini nasıl değiştirirsiniz?


123

Bu soru ihtiyacım olana yaklaşıyor ama benim senaryom biraz farklı. Kaynak tablo ve hedef tablo aynıdır ve birincil anahtar benzersiz bir tanımlayıcıdır (kılavuz). Bunu denediğimde:

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

Birincil anahtarı kopyalamaya çalıştığım için açıkça bir birincil anahtar kısıtlaması ihlali alıyorum. Aslında, birincil anahtarı hiç kopyalamak istemiyorum. Aksine, yeni bir tane oluşturmak istiyorum. Ek olarak, seçici olarak belirli alanları kopyalamak ve diğerlerini boş bırakmak istiyorum. Sorunları daha karmaşık hale getirmek için, orijinal kaydın birincil anahtarını alıp kopyadaki başka bir alana (Önceki Kimlik alanı) eklemem gerekiyor.

Eminim bunun kolay bir çözümü vardır, ne olduğunu bilmek için yeterli TSQL bilmiyorum.

Yanıtlar:


186

Bunu dene:


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

Belirtilmeyen alanlar varsayılan değerlerini almalıdır (bu, tanımlanmadığında genellikle NULL olur).


2
Muhteşem. Tılsım gibi çalıştı. Bir kez yazdıktan sonra çok açıktı. Teşekkürler!!
Kilhoffer

1
Bu, birkaç sütununuz varsa işe yarar. 20 veya 30 sütun derseniz yine de bu yöntemi kullanabilirsiniz, ancak bu ürkütücü olur. Ayrıca, her seferinde bir sütun eklediğinizde ve bu verileri de kopyalamak istediğinizde, sütunu bu komut dosyasına eklemeniz gerekir. En iyisi, sys tablolarını kullanarak dinamik olarak ekleme oluşturmaktır.
Jeyara

93

Tamam, bunun eski bir sorun olduğunu biliyorum ama yine de cevabımı gönderiyorum.

Bu çözümü beğendim. Sadece kimlik sütun (lar) ını belirtmem gerekiyor.

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;

"İd" sütunu kimlik sütunudur ve belirtmem gereken tek sütun budur. Zaten diğer yoldan daha iyi. :-)

SQL Server kullanıyorum. 1. ve 2. satırda " CREATE TABLE" ve " UPDATE TABLE" kullanmak isteyebilirsiniz . Hmm, onun istediği cevabı gerçekten vermediğimi gördüm. Kimliği başka bir sütuna da kopyalamak istedi. Ancak bu çözüm, yeni bir otomatik kimliğe sahip bir kopya oluşturmak için güzel.

Çözümümü Michael Dibbets'in idéaları ile düzenliyorum.

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;

Birden fazla sütunu bir "," ile ayırarak kaldırabilirsiniz. : İd, kopyalamak istediğiniz satırın kimliğiyle değiştirilmelidir. MyDatabase, MyTable ve IndexField isimlerinizle (tabii ki) değiştirilmelidir.


1
Bu aldatıcı, 3. satırdaki INSERT INTO sırasında doğru kimliği doğru satıra kopyaladığınızdan nasıl emin olabilirsiniz?
Erno

İd sütunu bir kimlik sütunudur (tablomda) bu yüzden değeri umursamıyorum. Sadece "eski" ile aynı değerlere sahip yeni bir rekor istiyorum.
Jonas

9
Çünkü TempTablekullanmak daha iyi olmaz mıydı #TempTable, yani gerçek bir geçici masa mı?
Jess

3
Bunu aşağıdaki biçimde kullanıyorum use MyDatabase; SELECT * INTO #TempTable FROM [TABLE] WHERE [indexfield] = :id; ALTER TABLE #TempTable DROP COLUMN [indexfield]; INSERT INTO [TABLE] SELECT * FROM #TempTable; DROP TABLE #TempTable;Bu şekilde, kesintili bir dosyayı diske yazarken herhangi bir gecikme olmaksızın en kısa sürede temizleneceğini biliyorum.
Tschallacka

3
$identityKimlik sütun adınızı sabit kodlamak istemiyorsanız da kullanabilirsiniz
Factor Mystic

12

Sanırım tüm sütun adlarını yazmaktan kaçınmaya çalışıyorsun. SQL Management Studio kullanıyorsanız, tabloya ve Ek Olarak Komut Dosyası'na kolayca sağ tıklayabilirsiniz .. o zaman sorgunuzu oluşturmak için bu çıktıyla uğraşabilirsiniz.


10

Kimlik alanınız dışındaki tüm alanları belirtin.

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

6

Tek bir komut dosyasının diğer geliştiriciler tarafından periyodik olarak eklenen sütunları olan bir tabloyla çalışmasını istediğimde aynı sorunu yaşıyorum. Sadece bu da değil, müşterilerimiz mevcut sürümle güncel olmayabileceğinden veritabanımızın birçok farklı sürümünü destekliyorum.

Çözümü Jonas'tan aldım ve biraz değiştirdim. Bu, satırın bir kopyasını oluşturmama ve ardından onu orijinal kaynak tabloya geri eklemeden önce birincil anahtarı değiştirmeme izin veriyor. Bu aynı zamanda sütunlarda NULL değerlere izin vermeyen tablolarla çalışmak için gerçekten kullanışlıdır ve INSERT'te her sütun adını belirtmek zorunda kalmak istemezsiniz.

Bu kod, 'ABC' satırını 'XYZ'ye kopyalar

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

Bitirdiğinizde geçici tabloyu bırakın.

DROP TABLE #TempRow;

4

Cevabımın partiye geç olduğunu biliyorum. Ama çözme şeklim tüm cevaplardan biraz farklı.

Bir durum yaşadım, birkaç sütun dışında bir tabloda bir satırı klonlamam gerekiyor. Bu azınlığın yeni değerleri olacak. Bu işlem, tablodaki gelecekteki değişiklikleri otomatik olarak desteklemelidir. Bu, herhangi bir sütun adı belirtmeden kaydı klonlayın.

Benim yaklaşımım,

  1. Sys.Columns sorgusu, tablo için sütunların tam listesini almak ve where cümlesinde atlanacak sütunların adlarını dahil etmek için.
  2. Bunu CSV'ye sütun adları olarak dönüştürün.
  3. Oluştur Seç ... Buna göre komut dosyasına ekleyin.


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)


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

1

PK alanınız "anahtar" ise ve otonümerikse.

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

orijinal kayıttan alan1 ve alan2'yi kopyalayarak yeni bir kayıt oluşturacaktır


1

Masamda 100 alan var ve sadece çalışmak için bir sorguya ihtiyacım vardı. Şimdi bazı temel koşullu mantıkla herhangi bir sayıda alanı değiştirebilirim ve sıralı konumu hakkında endişelenmem.

  1. Aşağıdaki tablo adını tablo adınızla değiştirin

    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. Orijinal kimlik alanı adını PK alan adınızla değiştirin

    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. Tablo adlarını yeniden değiştirin (hem hedef tablo adı hem de kaynak tablo adı); wherekoşullarınızı düzenleyin

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

0

Bunu beğenebilirsin:

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

Orada 112 yerine maksimum kimliği DENI / FRIEN01P tablosuna koymalısınız.


0

İşte ASP klasik kullanarak bunu nasıl yaptım ve yukarıdaki cevaplarla tam olarak çalışmasını sağlayamadım ve sistemimizdeki bir ürünü yeni bir product_id'ye kopyalayabilmek istedim ve bizde bile çalışabilmesi için ihtiyacım vardı. tabloya daha fazla sütun ekleyin.

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")

Bunu tamamlamak için 5 ayrı SQL komutu vermeniz gerektiğini sanmıyorum. Ayrıca 2. komutta ürün kimliğinin 34567 olması gerektiğini kimi belirliyorsunuz?
Jeyara

34567 sadece bir örnektir. Bunu bir değişkene veya istediğiniz gibi ayarlayabilirsiniz. Bunu ASP Classic'te yapmanın daha iyi bir yolu varsa, bana bildirin. :)
Daniel Nordh

tüm bunları tek satırda çalıştırmak için depolanmış bir işlem yazabilirsiniz. Ayrıca, genellikle PK otomatik bir artış değeriydi. Bu yüzden kendinize atamak iyi bir fikir değil.
Jeyara

Söz konusu prosedürü nasıl yazarsınız? Lütfen beni aydınlat. PK? Makale kimliklerini kastediyorsanız, sistemimizde onları hangi mağazada sattığımıza bağlı olarak ürün kimlikleri kullanırız. Örneğin, oyuncak mağazamızın hepsinin 30 ile başlayan ürün numarası vardır ve spor mağazamız 60 ile başlar. Ayrıca, eğer biz yeni bir renk alın, örneğin, aynı türden diğerlerinin yanında bir makale kimliğine sahip olabiliriz. Dediğim gibi, bu benim sistemimizde çalışan çözümümdü. Değişkenleri nasıl belirlediğiniz o kadar önemli değildir ve çoğu programcı kendileri ve sistemleri için neyin işe yaradığını anlayacaktır.
Daniel Nordh

PK, birincil anahtar anlamına gelir. Sizin durumunuzda '12345'. Nasıl yapılacağını bilmiyorsanız, Klasik ASP'de depolanan proc'u nasıl kullanacağınız için stackoverflow.com/questions/21561657/… sayfasına bakın . Bunu yapmak için, hepsini depolanan bir proc'a taşıyın ve '12345'i parametre olarak iletin. Bu günlerde çalışma şekliniz ancak parametreli Betikler önerilir.
Jeyara
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.