Как скопировать запись в таблицу SQL, но поменять уникальный идентификатор новой строки? - PullRequest
112 голосов
/ 29 сентября 2008

Этот вопрос приближается к тому, что мне нужно, но мой сценарий немного отличается. Исходная таблица и таблица назначения совпадают, а первичный ключ - это уникальный идентификатор (guid). Когда я пытаюсь это:

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

Я, очевидно, получаю нарушение ограничения первичного ключа, так как пытаюсь скопировать первичный ключ. На самом деле, я не хочу копировать первичный ключ вообще. Скорее, я хочу создать новый. Кроме того, я хотел бы выборочно копировать определенные поля, а остальные оставить пустыми. Чтобы усложнить задачу, мне нужно взять первичный ключ исходной записи и вставить его в другое поле копии (поле PreviousId).

Я уверен, что есть простое решение, я просто не знаю достаточно TSQL, чтобы понять, что это такое.

Ответы [ 11 ]

171 голосов
/ 29 сентября 2008

Попробуйте это:

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

Любые поля, не указанные, должны получить значение по умолчанию (которое обычно не равно NULL, если оно не определено).

81 голосов
/ 22 февраля 2013

Хорошо, я знаю, что это старая проблема, но я все равно публикую свой ответ.

Мне нравится это решение. Мне нужно только указать идентификационные столбцы.

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;

Столбец "id" - это столбец идентификаторов, и это единственный столбец, который мне нужно указать. В любом случае это лучше, чем наоборот. : -)

Я использую SQL Server. Вы можете использовать «CREATE TABLE» и «UPDATE TABLE» в строках 1 и 2. Хм, я видел, что я действительно не дал ответ, который он хотел. Он хотел скопировать идентификатор также в другой столбец. Но это решение подходит для копирования с новым автоматическим идентификатором.

Я редактирую свое решение с помощью идей Майкла Диббетса.

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;

Вы можете удалить несколько столбцов, разделив их знаком ",". Замените: id на id строки, которую вы хотите скопировать. MyDatabase, MyTable и IndexField должны быть заменены вашими именами (конечно).

11 голосов
/ 21 мая 2009

Полагаю, вы пытаетесь избежать записи всех имен столбцов. Если вы используете SQL Management Studio, вы можете легко щелкнуть правой кнопкой мыши по таблице и «Сценарий как вставка ...», после чего вы можете возиться с этим выводом, чтобы создать запрос.

10 голосов
/ 29 сентября 2008

Укажите все поля, кроме вашего поля идентификатора.

INSERT INTO MyTable (FIELD2, FIELD3, ..., FIELD529, PreviousId)
SELECT FIELD2, NULL, ..., FIELD529, FIELD1
FROM MyTable
WHERE FIELD1 = @Id;
3 голосов
/ 05 сентября 2017

У меня та же проблема, когда я хочу, чтобы один скрипт работал с таблицей, столбцы которой периодически добавлялись другими разработчиками. Мало того, я поддерживаю много разных версий нашей базы данных, так как клиенты могут не все быть в курсе текущей версии.

Я взял решение Джонаса и немного его изменил. Это позволяет мне сделать копию строки, а затем изменить первичный ключ, прежде чем добавить его обратно в исходную исходную таблицу. Это также очень удобно для работы с таблицами, которые не допускают значения NULL в столбцах, и вам не нужно указывать имя каждого столбца в INSERT.

Этот код копирует строку для 'ABC' в 'XYZ'

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

Как только вы закончите, удалите временную таблицу.

DROP TABLE #TempRow;
2 голосов
/ 29 сентября 2008
insert into MyTable (uniqueId, column1, column2, referencedUniqueId)
select NewGuid(), // don't know this syntax, sorry
  column1,
  column2,
  uniqueId,
from MyTable where uniqueId = @Id
1 голос
/ 18 июня 2018

Я знаю, что мой ответ опоздал на вечеринку. Но способ, который я решил, немного отличается от всех ответов.

У меня была ситуация, мне нужно клонировать строку в таблице, за исключением нескольких столбцов. У тех немногих будут новые ценности. Этот процесс должен автоматически поддерживать будущие изменения в таблице. Это подразумевает клонирование записи без указания имен столбцов.

Мой подход к,

  1. Запрос Sys.Columns для получения полного списка столбцов для таблицы и включения имен столбцов для пропуска в где предложение.
  2. Преобразуйте это в CSV как имена столбцов.
  3. Build Select ... Вставить в скрипт на основе этого.

<code>
declare @columnsToCopyValues varchar(max), @query varchar(max)
SET @columnsToCopyValues = ''</p>

<p>--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</p>

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

<p>print @query
exec (@query)
1 голос
/ 20 января 2013

В моей таблице 100 полей, и мне нужен был запрос, чтобы просто работать. Теперь я могу переключать любое количество полей с некоторой базовой условной логикой и не беспокоиться о ее порядковом положении.

  1. Замените приведенное ниже имя таблицы на имя вашей таблицы

    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. Замените исходное имя поля идентификатора на имя вашего поля 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. Заменить имена таблиц снова (как имя целевой таблицы, так и имя исходной таблицы); измените where условия

    SQL = "INSERT INTO TARGET-TABLE-NAME (" & columnListTARGET & ") SELECT " & columnListSOURCE & " FROM SOURCE-TABLE-NAME WHERE (FIELDNAME = FIELDVALUE)" 
    Conn.Execute(SQL)
    
1 голос
/ 29 сентября 2008

Если «ключ» - это ваше поле PK, и оно является числовым.

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

создаст новую запись, скопировав field1 и field2 из исходной записи

0 голосов
/ 17 января 2019

Вот как я это сделал, используя ASP classic, и не смог заставить его работать с ответами, приведенными выше, и я хотел иметь возможность скопировать продукт в нашей системе в новый product_id, и мне нужно было, чтобы он работал даже когда мы добавляем в таблицу больше столбцов.

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")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...