Як ви скопіюєте запис у таблицю SQL, але замініть унікальний ідентифікатор нового рядка?


123

Це питання наближається до того, що мені потрібно, але мій сценарій дещо інший. Таблиця джерела та таблиця призначення однакові, а первинний ключ є унікальним ідентифікатором (орієнтиром). Коли я спробую це:

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

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

Я впевнений, що для цього є просте рішення, я просто не знаю достатньо TSQL, щоб знати, що це таке.

Відповіді:


186

Спробуйте це:


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

Будь-які поля, не вказані, повинні отримувати значення за замовчуванням (яке, як правило, NULL, якщо воно не визначене).


2
Дивовижно. Працював як шарм. Це було так очевидно, як тільки ви його виписали. Дякую!!
Кілхоффер

1
Це спрацює, якщо у вас є кілька стовпців. Якщо у вас є, наприклад, 20 або 30 стовпців, ви все одно можете скористатися цим методом, але це було б неприємно. Крім того, кожного разу, коли ви додаєте стовпець і хочете скопіювати ці дані, потрібно додавати стовпець до цього сценарію. Найкраще динамічно створювати вставки, використовуючи таблиці sys.
Джеяра

93

Гаразд, я знаю, що це старе питання, але я все-таки публікую свою відповідь.

Мені подобається це рішення. Мені залишається лише вказати стовпці особи.

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;

Ви можете опустити більше одного стовпця, відокремивши їх знаками ",". Ідентифікатор: слід замінити ідентифікатором рядка, який потрібно скопіювати. MyDatabase, MyTable та IndexField слід замінити вашими іменами (звичайно).


1
Це складно, як ви можете бути впевнені, що ви копіюєте правильний ідентифікатор у правильний рядок під час INSERT INTO у рядку 3?
Ерно

Стовпець id - це стовпець ідентичності (у моїй таблиці), тому я не переймаюся значенням. Я просто хочу, щоб новий запис мав ті самі значення, що і "старий".
Йонас

9
Бо TempTableхіба не було б краще використовувати #TempTable, тож це справжня тимчасова таблиця?
Джесс

3
Я використовую це в наступному форматі. 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;Таким чином, я знаю, що він буде очищений якнайшвидше, без будь-яких затримок із записом переривчастого файлу на диск.
Цхаллачка

3
Ви також можете використати, $identityякщо не хочете жорстко кодувати своє ім'я стовпця особи
Factor Mystic

12

Я здогадуюсь, що ви намагаєтеся уникати виписування всіх назв стовпців. Якщо ви використовуєте SQL Management Studio, ви можете легко натиснути правою кнопкою миші на таблицю та сценарій як вставити .., тоді ви можете зіпсуватись із цим результатом, щоб створити свій запит.


10

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

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

6

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

Я взяв рішення Йонас і трохи змінив його. Це дозволяє мені зробити копію рядка, а потім змінити первинний ключ перед тим, як додати його назад до вихідної таблиці джерела. Це також дуже зручно для роботи з таблицями, які не дозволяють 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;

4

Я знаю, що моя відповідь запізнилася на вечірку. Але спосіб, який я вирішив, трохи відрізняється від усіх відповідей.

У мене виникла ситуація, мені потрібно клонувати рядок у таблиці, за винятком кількох стовпців. У тих небагатьох будуть нові значення. Цей процес повинен підтримуватись автоматично для майбутніх змін до таблиці. Це означає, клонуйте запис, не вказуючи імен стовпців.

Мій підхід до:

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


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

Якщо "ключ" - це ваше поле ПК і воно є автономерним.

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

він генерує новий запис, копіюючи поле1 та поле2 з початкового запису


1

У моїй таблиці 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. Замініть оригінальну назву поля ідентичності на ім'я поля ПК

    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)

0

Ви можете зробити так:

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

Там замість 112 слід ввести число максимального ідентифікатора в таблиці DENI / FRIEN01P.


0

Ось як я це зробив за допомогою 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")

Я не думаю, що вам потрібно видати 5 окремих команд SQL, щоб виконати це. А також, кого ви визначаєте у другій команді, що ідентифікатор продукту має бути 34567?
Джеяра

34567 - лише приклад. Ви можете встановити його на змінну або що завгодно. Якщо у вас є кращий спосіб зробити це в ASP Classic, дайте мені знати. :)
Даніель Норд

Ви можете написати збережену програму, щоб запустити все це в одному рядку. Також зазвичай ПК збільшується як значення автоматичного збільшення. Тож призначати собі - це не дуже гарна ідея.
Джеяра

Як би ви написали вказану процедуру? Будь ласка, просвіти мене. ПК? Якщо ви маєте на увазі ідентифікатори артикулів, у нашій системі ми використовуємо ідентифікатори артикулів, залежно від того, в якому магазині ми їх продаємо. Наприклад, у нашому магазині іграшок є номер артикулу, починаючи з 30, а в нашому спортивному магазині починається з 60. Плюс ми заощаджуємо місця, так що якщо ми щоб отримати новий колір, наприклад, ми можемо мати ідентифікатор статті поруч з іншими аналогічними видами. Як було сказано, це було моє рішення, яке працює в нашій системі. Налаштування змінних не так важливо, і більшість програмістів зрозуміли, що працює для них та їхньої системи.
Даніель Норд

PK означає первинний ключ. У вашому випадку його "12345". Дивіться stackoverflow.com/questions/21561657/… про те, як використовувати збережений Proc в Classic ASP, якщо ви не знаєте, як це зробити. Для цього перемістіть усіх, хто перебуває в одній збереженій програмі, і введіть свій параметр "12345". У цей час рекомендується працювати так, як параметризовані сценарії.
Джеяра
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.