Bir satırı kopyalayıp MySQL'de bir otomatik entrement alanı ile aynı tabloya nasıl ekleyebilirim?


233

MySQL'de bir otomatik yineleme ile bir satır kopyalamaya column ID=1ve yeni bir satırla aynı tabloya veri eklemek çalışıyorum column ID=2.

Bunu tek bir sorguda nasıl yapabilirim?

Yanıtlar:


351

Kullanım INSERT ... SELECT:

insert into your_table (c1, c2, ...)
select c1, c2, ...
from your_table
where id = 1

c1, c2, ...hariç tüm sütunlar nerede id? id2 ile açıkça eklemek istiyorsanız , INSERT sütun listenize ve SELECT'inize ekleyin:

insert into your_table (id, c1, c2, ...)
select 2, c1, c2, ...
from your_table
where id = 1

idTabii ki ikinci durumda 2'nin olası bir kopyasına dikkat etmeniz gerekir .


1
Programsal olarak bilgi sütunlarını daha sonra da BİLGİ_SCHEMA kullanarak alabilirsiniz ... Bunu bir alt sorgu ve bazı dize işlevleri olarak yapabilir miyim acaba? Hmmm ...
Yzmir Ramirez

1
@Yzmir: Sonunda dinamik SQL kullanmak zorunda kalırsınız ve bu genellikle saklı bir prosedür oluşturmayı gerektirir. Zaten kullanışlı bir sütun isimleri listesi olması gerektiğinde daha fazla sorun gibi görünüyor.
mu çok kısa

6
Kabul edildi ... Deneyimimden Saklı Prosedür'e döndüğünüzde geri dönmüyorsunuz - şimdi bu veritabanıyla evlisiniz ve sadece değiştirmek istediğinizde maliyetleri ekliyor.
Yzmir Ramirez

11
@YzmirRamirez, evlilik doğal olarak kötü bir şeymiş gibi geliyor. :)
Prof. Falken

1
Tüm kopyalanan alanlarla sütuna bir özel değer nasıl eklenir?
Manish Kumar

49

IMO, en iyisi sql deyimlerini sadece bu satırı kopyalamak için kullanırken, aynı zamanda sadece ihtiyacınız olan ve değiştirmek istediğiniz sütunlara atıfta bulunur.

CREATE TEMPORARY TABLE temp_table ENGINE=MEMORY

SELECT * FROM your_table WHERE id=1;
UPDATE temp_table SET id=NULL; /* Update other values at will. */

INSERT INTO your_table SELECT * FROM temp_table;
DROP TABLE temp_table;

Ayrıca bkz. Av8n.com - SQL Kaydını Klonlama

Yararları:

  • SQL ifadeleri 2, yalnızca klonlama işlemi sırasında değiştirilmesi gereken alanları belirtir. Diğer alanları bilmiyorlar veya önemsemiyorlar. Diğer alanlar değişmeden sürüşe devam ediyor. Bu, SQL ifadelerinin yazılmasını, okunmasını daha kolay, bakımını daha kolay ve daha genişletilebilir hale getirir.
  • Yalnızca normal MySQL deyimleri kullanılır. Başka bir araç veya programlama dili gerekmez.
  • Bir your_tableatomik işlemde tam olarak doğru bir kayıt eklenir .

3
Dikişler, bu güzel hile (onu sevdim, ama benim için işe yaramadı) TEXT / VARCHAR sütunları içeren tablolarda çalışmaz. Denedim ve aldım: (1163): Kullanılan tablo türü BLOB / TEXT sütunlarını desteklemiyor. Bu tabii ki MySQL üzerinde kullanımı çok sınırlıyor! Gelecekte bu sınırların kaldırılması veya diğer db sistemlerinde işe yaraması olabilir, ancak şimdilik gerçekten sınırlıdır.
Juergen

Geçici tablonun akıllıca kullanılmasını seviyorum. Bir ton sütun içeren tablolar için çok yararlı!
Lasma

1
Güzel görünüyor, ama MySQL'de ilk sorguyu çalıştırdığımda anladım Error Code: 1113. A table must have at least 1 column.
physicalattraction

3
Çok sayıda sütun için en iyi cevap. Ancak SET id=NULLhataya neden olabilir Column 'id' cannot be null. DeğiştirilmelidirUPDATE temp_table SET id = (SELECT MAX(id) + 1 as id FROM your_table);
Modder

1
@physicalattraction ilk iki satırın tek bir ifade olduğundan emin olmanız gerekir.
Samuurai

16

Masanın olduğunu söyle user(id, user_name, user_email).

Bu sorguyu kullanabilirsiniz:

INSERT INTO user (SELECT NULL,user_name, user_email FROM user WHERE id = 1)

29
Sen gerektiğini hep INSERT kullanırken şema değiştiğinde aksi takdirde garip ve ilginç hatalar alacak, sütun adları belirtin.
mu çok kısa

2
Gerçekten garip ve ilginç. : D
sparkyShorts

Sqlite ile çalışmaz. Result: near "SELECT": syntax error
kyb

10

Bu yardımcı oldu ve bir BLOB / METİN sütunlarını destekliyor.

CREATE TEMPORARY TABLE temp_table
AS
SELECT * FROM source_table WHERE id=2;
UPDATE temp_table SET id=NULL WHERE id=2;
INSERT INTO source_table SELECT * FROM temp_table;
DROP TEMPORARY TABLE temp_table;
USE source_table;

Hangi açıdan buradaki diğer cevaplardan daha iyidir?
Smar

3
Sanırım 100 alanlı bir masanız varsa oldukça iyi. Dışında başarısız kılan kimliği boş bir kısıtlama olabilir
Loïc Faure-Lacroix

Hata Kodu: 1136. Sütun sayısı 1. satırdaki değer sayısıyla
eşleşmiyor

100'lü sütun içeren bir tablonuz varsa bu çok daha iyidir.
Tyler S.Loeper

Parvus yıllar önce böyle demedi mi?
ToolmakerSteve

7

Sütunları adlandırmanızı gerektirmeyen hızlı ve temiz bir çözüm için, burada açıklandığı gibi hazırlanmış bir ifade kullanabilirsiniz: https://stackoverflow.com/a/23964285/292677

Bunu sık sık yapabilmeniz için karmaşık bir çözüme ihtiyacınız varsa, bu yordamı kullanabilirsiniz:

DELIMITER $$

CREATE PROCEDURE `duplicateRows`(_schemaName text, _tableName text, _whereClause text, _omitColumns text)
SQL SECURITY INVOKER
BEGIN
  SELECT IF(TRIM(_omitColumns) <> '', CONCAT('id', ',', TRIM(_omitColumns)), 'id') INTO @omitColumns;

  SELECT GROUP_CONCAT(COLUMN_NAME) FROM information_schema.columns 
  WHERE table_schema = _schemaName AND table_name = _tableName AND FIND_IN_SET(COLUMN_NAME,@omitColumns) = 0 ORDER BY ORDINAL_POSITION INTO @columns;

  SET @sql = CONCAT('INSERT INTO ', _tableName, '(', @columns, ')',
  'SELECT ', @columns, 
  ' FROM ', _schemaName, '.', _tableName, ' ',  _whereClause);

  PREPARE stmt1 FROM @sql;
  EXECUTE stmt1;
END

Şununla çalıştırabilirsiniz:

CALL duplicateRows('database', 'table', 'WHERE condition = optional', 'omit_columns_optional');

Örnekler

duplicateRows('acl', 'users', 'WHERE id = 200'); -- will duplicate the row for the user with id 200
duplicateRows('acl', 'users', 'WHERE id = 200', 'created_ts'); -- same as above but will not copy the created_ts column value    
duplicateRows('acl', 'users', 'WHERE id = 200', 'created_ts,updated_ts'); -- same as above but also omits the updated_ts column
duplicateRows('acl', 'users'); -- will duplicate all records in the table

YASAL UYARI: Bu çözüm yalnızca birçok tablodaki satırları sık sık çoğaltacak olan kişiler içindir. Sahte bir kullanıcının elinde tehlikeli olabilir.


3

Otomatik olarak artırılacak sütunun değeri olarak '0' değerini de iletebilirsiniz; kayıt oluşturulduğunda doğru değer kullanılır. Bu geçici tablolardan çok daha kolaydır.

Kaynak: MySQL'deki satırları kopyalama (TRiG tarafından yapılan ikinci yoruma Lore tarafından ilk çözüme bakın)


1
NULL kabul edilemez olduğunda bu yöntem daha yeni MySQL sürümleriyle çalışır.
err

3

Burada bir sürü harika cevap var. Aşağıda, geliştirdiğim bir Web Uygulaması için bu görevi gerçekleştirmek için yazdığım saklı yordamın bir örneği verilmiştir:

-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON

-- Create Temporary Table
SELECT * INTO #tempTable FROM <YourTable> WHERE Id = Id

--To trigger the auto increment
UPDATE #tempTable SET Id = NULL 

--Update new data row in #tempTable here!

--Insert duplicate row with modified data back into your table
INSERT INTO <YourTable> SELECT * FROM #tempTable

-- Drop Temporary Table
DROP TABLE #tempTable

MariaDB / MySQL ayarının geçerli sürümünde id = null değeri # 1048 verir - 'id' sütunu boş olamaz, id = 0 ayarı çalışır;
shelbypereira

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

3
Buradaki diğer cevaplardan nasıl daha iyi?
Smar

1
@smar imo anlamak daha temiz
Satbir Kira

2

MySQL Workbench'i kullanabiliyorsanız, satırı sağ tıklayıp 'Satırı kopyala'yı seçip ardından boş satırı sağ tıklayıp' Satırı yapıştır 'seçeneğini belirleyip kimliği değiştirerek yapabilirsiniz. 'Uygula'yı tıklayın.

Satırı kopyalayın:

resim açıklamasını buraya girin

Kopyalanan satırı boş satıra yapıştırın:

resim açıklamasını buraya girin

Kimliği değiştirin:

resim açıklamasını buraya girin

Uygulamak:

resim açıklamasını buraya girin


0

Aynı özelliği arıyordum ama MySQL kullanmıyorum. Tabii ki birincil anahtar (id) hariç TÜM alanları kopyalamak istedim. Bu, herhangi bir komut dosyasında veya kodda kullanılmamak için tek seferlik bir sorguydu.

PL / SQL ile yolumu buldum ama başka bir SQL IDE'nin yapacağından eminim. Basit yaptım

SELECT * 
FROM mytable 
WHERE id=42;

Sonra bulabileceğim bir SQL dosyasına aktarın

INSERT INTO table (col1, col2, col3, ... , col42) 
VALUES (1, 2, 3, ..., 42);

Sadece düzenledim ve kullandım:

INSERT INTO table (col1, col2, col3, ... , col42) 
VALUES (mysequence.nextval, 2, 3, ..., 42);

0

Ben çok kısa bir süre içinde yayınlanan mu bir varyasyon kullanma eğilimindedir:

INSERT INTO something_log
SELECT NULL, s.*
FROM something AS s
WHERE s.id = 1;

Tablolar aynı alanlara sahip olduğu sürece (günlük tablosundaki otomatik artış hariç), bu iyi çalışır.

Saklı yordamları mümkün olduğunca kullandığım için (veritabanlarına çok aşina olmayan diğer programcılarda hayatı kolaylaştırmak için), tabloya her yeni alan eklediğinizde geri dönüp yordamları güncelleştirme sorununu çözer.

Ayrıca, bir tabloya yeni alanlar eklerseniz, veritabanı sorgularınızı güncellemek zorunda kalmadan hemen günlük tablosunda görünmeye başlayabilmelerini sağlar (tabii ki bir alanı açıkça ayarlayan bazılarınız yoksa)

Uyarı: Alan sırasının aynı kalması için her iki tabloya da aynı anda yeni alanlar eklediğinizden emin olmak istersiniz ... aksi takdirde tuhaf hatalar almaya başlarsınız. Veritabanı arayüzleri yazan tek kişi iseniz VE çok dikkatli iseniz o zaman bu güzel çalışıyor. Aksi takdirde, tüm alanlarınızı adlandırmaya devam edin.

Not: İkinci bir düşüncede, solo bir proje üzerinde çalışmadığınız sürece, başkalarının üzerinde çalıştığından emin olmadığınız sürece, tüm alan adlarını açıkça listelemeye ve şemanız değiştikçe günlük ifadelerinizi güncelleyin. Bu kısayol muhtemelen neden olabileceği uzun vadeli baş ağrısına değmez ... özellikle bir üretim sisteminde.


0
DbMyDataBase'e ekle.`tblMyTable` 
(
    `IdAutoincrement`, 
    `Column2`, 
    `Column3`, 
    `Column4` 
) 

SEÇ 
    BOŞ,  
    `Column2`, 
    `Column3`, 
    'CustomValue' AS Sütun4 
DbMyDataBase'TAN.`tblMyTable` 
NEREDEN `tblMyTable`.`Column2` = 'UniqueValueOfTheKey' 
; 
/ * mySQL 5.6 * /

3
Daha ayrıntılı bir açıklama veya bunun diğer yanıtlarda nasıl genişlediğini eklemeyi deneyin
Azsgy

-1

Sql istediğiniz satırı dökümü ve sonra oluşturulan SQL kullanın, geri almak için kimlik sütunu daha az.

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.