Обменять уникальные индексированные значения столбцов в базе данных
10621 просмотра
12 ответа
У меня есть таблица базы данных, и одно из полей (а не первичный ключ) имеет уникальный индекс. Теперь я хочу обменять значения под этим столбцом на две строки. Как это можно сделать? Два хака, которые я знаю, это:
- Удалите обе строки и снова вставьте их
- Обновляйте строки с помощью другого значения и свопируйте, а затем обновляйте до фактического значения.
Но я не хочу идти за ними, поскольку они, похоже, не являются подходящим решением проблемы. Может ли кто-нибудь помочь мне?
Автор: Ramesh Soni Источник Размещён: 17.05.2019 03:53Ответы (12)
10 плюса
Я думаю, вы должны пойти на решение 2. Нет функции «swap» в любом SQL-варианте, о котором я знаю.
Если вам нужно делать это регулярно, я предлагаю решение 1, в зависимости от того, как другие части программного обеспечения используют эти данные. У вас могут быть проблемы с блокировкой, если вы не будете осторожны.
Но одним словом: нет другого решения, кроме тех, которые вы предоставили.
Автор: Daan Размещён: 03.08.2008 12:2623 плюса
Волшебное слово DEFERRABLE здесь:
DROP TABLE ztable CASCADE;
CREATE TABLE ztable
( id integer NOT NULL PRIMARY KEY
, payload varchar
);
INSERT INTO ztable(id,payload) VALUES (1,'one' ), (2,'two' ), (3,'three' );
SELECT * FROM ztable;
-- This works, because there is no constraint
UPDATE ztable t1
SET payload=t2.payload
FROM ztable t2
WHERE t1.id IN (2,3)
AND t2.id IN (2,3)
AND t1.id <> t2.id
;
SELECT * FROM ztable;
ALTER TABLE ztable ADD CONSTRAINT OMG_WTF UNIQUE (payload)
DEFERRABLE INITIALLY DEFERRED
;
-- This should also work, because the constraint
-- is deferred until "commit time"
UPDATE ztable t1
SET payload=t2.payload
FROM ztable t2
WHERE t1.id IN (2,3)
AND t2.id IN (2,3)
AND t1.id <> t2.id
;
SELECT * FROM ztable;
РЕЗУЛЬТАТ:
DROP TABLE
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "ztable_pkey" for table "ztable"
CREATE TABLE
INSERT 0 3
id | payload
----+---------
1 | one
2 | two
3 | three
(3 rows)
UPDATE 2
id | payload
----+---------
1 | one
2 | three
3 | two
(3 rows)
NOTICE: ALTER TABLE / ADD UNIQUE will create implicit index "omg_wtf" for table "ztable"
ALTER TABLE
UPDATE 2
id | payload
----+---------
1 | one
2 | two
3 | three
(3 rows)
Автор: wildplasser
Размещён: 15.09.2012 12:38
6 плюса
В ответ на ответ Энди Ирвинг
это работало для меня (на SQL Server 2005) в аналогичной ситуации, когда у меня есть составной ключ, и мне нужно поменять поле, которое является частью уникального ограничения.
ключ: pID, LNUM rec1: 10, 0 rec2: 10, 1 rec3: 10, 2
и мне нужно поменять LNUM, чтобы результат
ключ: pID, LNUM rec1: 10, 1 rec2: 10, 2 rec3: 10, 0
SQL необходим:
UPDATE DOCDATA
SET LNUM = CASE LNUM
WHEN 0 THEN 1
WHEN 1 THEN 2
WHEN 2 THEN 0
END
WHERE (pID = 10)
AND (LNUM IN (0, 1, 2))
Автор: MakisCE
Размещён: 10.12.2008 12:19
5 плюса
Существует еще один подход, который работает с SQL Server: используйте команду temp join в нем в вашем заявлении UPDATE.
Проблема возникает из-за наличия двух строк с одинаковым значением в одно и то же время , но если вы обновляете сразу две строки (к их новым, уникальным значениям), нарушение ограничений не происходит.
Псевдо-код:
-- setup initial data values:
insert into data_table(id, name) values(1, 'A')
insert into data_table(id, name) values(2, 'B')
-- create temp table that matches live table
select top 0 * into #tmp_data_table from data_table
-- insert records to be swapped
insert into #tmp_data_table(id, name) values(1, 'B')
insert into #tmp_data_table(id, name) values(2, 'A')
-- update both rows at once! No index violations!
update data_table set name = #tmp_data_table.name
from data_table join #tmp_data_table on (data_table.id = #tmp_data_table.id)
Благодаря Rich H для этой техники. - Отметка
Автор: Mark Gaulin Размещён: 04.04.2012 07:403 плюса
Я также думаю, что # 2 - лучшая ставка, хотя я уверен, что буду обернуть ее транзакцией, если что-то пойдет не так, как в середине обновления.
Альтернативой (с тех пор, как вы просили) обновить значения уникального индекса с разными значениями, было бы обновление всех других значений в строках по сравнению с другими строками. Это означает, что вы можете оставить только уникальные значения индекса, и в итоге вы получите нужные данные. Будьте осторожны, хотя в случае, если какая-либо другая таблица ссылается на эту таблицу в отношении внешнего ключа, все отношения в БД остаются нетронутыми.
Автор: Yaakov Ellis Размещён: 03.08.2008 01:222 плюса
У меня та же проблема. Вот мой предложенный подход в PostgreSQL. В моем случае мой уникальный индекс - это значение последовательности, определяющее явный порядок пользователей в моих строках. Пользователь будет перемешать строки в веб-приложении, а затем отправить изменения.
Я планирую добавить триггер «до». В этом триггере, когда мое уникальное значение индекса обновляется, я посмотрю, будет ли какая-либо другая строка уже содержать мое новое значение. Если это так, я дам им свою старую ценность и эффективно украсть у них ценность.
Я надеюсь, что PostgreSQL позволит мне сделать это в случайном порядке.
Я отправлю обратно и дам вам знать свой пробег.
Автор: the.jxc Размещён: 24.06.2009 03:582 плюса
Предполагая, что вы знаете PK двух строк, которые вы хотите обновить ... Это работает в SQL Server, не может говорить о других продуктах. SQL (предположительно) является атомом на уровне инструкции:
CREATE TABLE testing
(
cola int NOT NULL,
colb CHAR(1) NOT NULL
);
CREATE UNIQUE INDEX UIX_testing_a ON testing(colb);
INSERT INTO testing VALUES (1, 'b');
INSERT INTO testing VALUES (2, 'a');
SELECT * FROM testing;
UPDATE testing
SET colb = CASE cola WHEN 1 THEN 'a'
WHEN 2 THEN 'b'
END
WHERE cola IN (1,2);
SELECT * FROM testing;
поэтому вы перейдете от:
cola colb
------------
1 b
2 a
чтобы:
cola colb
------------
1 a
2 b
Автор: Andy Irving
Размещён: 16.09.2008 02:57
1 плюс
Oracle имеет отложенную проверку целостности, которая решает именно это, но она недоступна ни в SQL Server, ни в MySQL.
Автор: BlueRaja - Danny Pflughoeft Размещён: 19.03.2010 07:291 плюс
В SQL Server оператор MERGE может обновлять строки, которые обычно ломают UNIQUE KEY / INDEX. (Просто испытал это, потому что мне было любопытно.)
Однако вам нужно будет использовать временную таблицу / переменную для подачи MERGE с необходимыми строками.
Автор: Ben Mosher Размещён: 20.04.2012 07:121 плюс
Для Oracle есть опция DEFERRED, но вы должны добавить ее к своему ограничению.
SET CONSTRAINT emp_no_fk_par DEFERRED;
Чтобы отложить все ограничения, которые откладываются в течение всего сеанса, вы можете использовать инструкцию ALTER SESSION SET = DEFERRED.
Автор: TheBakker Размещён: 27.04.2016 02:150 плюса
Я обычно думаю о ценности, которая не может иметь никакого индекса в моей таблице. Обычно - для уникальных значений столбцов - это очень просто. Например, для значений столбца «позиция» (информация о порядке нескольких элементов) это 0.
Затем вы можете скопировать значение A в переменную, обновить ее со значением B и затем установить значение B из вашей переменной. Два запроса, однако я не знаю лучшего решения.
Автор: Lis Размещён: 18.03.2017 06:000 плюса
1) Напишите запрос для переключения идентификаторов для студентов, которые находятся рядом друг с другом? Вот пример ввода.
id student
1 Abbot
2 Doris
3 Emerson
4 Green
5 Jeames
Для ввода образца выходной сигнал:
id student
1 Doris
2 Abbot
3 Green
4 Emerson
5 Jeames
Обратите внимание, что если общее количество мест нечетное, идентификатор для последнего остается неизменным.
«в случае, если число рядов, как обойдется ...»
Автор: shyam Размещён: 06.11.2018 08:56Вопросы из категории :
- sql Проверить наличие изменений в таблице SQL Server?
- sql Обменять уникальные индексированные значения столбцов в базе данных
- sql Как работает индексация базы данных?
- sql Как индексировать столбец базы данных
- sql Как разбить строку, чтобы я мог получить доступ к элементу x?
- sql Удалить все таблицы, имена которых начинаются с определенной строки
- sql В какой момент кто-то решит переключить системы баз данных
- sql Как выбрать n-ую строку в таблице базы данных SQL?
- sql Как запросить случайную строку в SQL?
- sql Лучший способ инкапсулировать сложную логику курсора Oracle PL / SQL в виде представления?
- database Двоичные данные в MySQL
- database Насколько большой может быть база данных MySQL до того, как производительность начнет снижаться
- database Хранение изображений в БД - да или нет?
- database Хранить файл в базе данных в отличие от файловой системы?
- database MyISAM против InnoDB