Свопинг значений столбцов в MySQL

Пожалуйста, смотрите его обсуждение в youTrack Jetbrain . Версия Ubuntu и Java должна быть 32-битной или 64-битной. Если они различаются, произойдет ошибка выше. Поэтому убедитесь, что вы используете те же ароматы.

119
задан 01.09.2008, 12:54

9 ответов

Я просто должен был иметь дело с тем же, и я буду суммировать свои результаты.

  1. Эти UPDATE table SET X=Y, Y=X подход, очевидно, не работает, поскольку он просто установит оба значения к Y.

  2. Вот метод, который использует временную переменную. Благодаря Antony из комментариев http://beerpla.net/2009/02/17/swapping-column-values-in-mysql/ для "ЯВЛЯЕТСЯ NOT NULL" тонкая настройка. Без него запрос работает непредсказуемо. См. схему таблицы в конце сообщения. Этот метод не подкачивает значения, если один из них является ПУСТЫМ. Используйте метод № 3, который не имеет этого ограничения.

    UPDATE swap_test SET x=y, y=@temp WHERE (@temp:=x) IS NOT NULL;

  3. Этот метод предлагался Dipin в, все снова и снова, комментарии http://beerpla.net/2009/02/17/swapping-column-values-in-mysql/ . Я думаю it’s самое изящное и чистое решение. Это работает и с ПУСТЫМИ и с ненулевыми значениями.

    UPDATE swap_test SET x=(@temp:=x), x = y, y = @temp;

  4. Другой подход я придумал, который, кажется, работает:

    UPDATE swap_test s1, swap_test s2 SET s1.x=s1.y, s1.y=s2.x WHERE s1.id=s2.id;

По существу, 1-я таблица является обновляемой той, и 2-й используется для получения по запросу старых данных из.
Примечание, что этот подход требует, чтобы первичный ключ присутствовал.

Это - моя тестовая схема:

CREATE TABLE `swap_test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `x` varchar(255) DEFAULT NULL,
  `y` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

INSERT INTO `swap_test` VALUES ('1', 'a', '10');
INSERT INTO `swap_test` VALUES ('2', NULL, '20');
INSERT INTO `swap_test` VALUES ('3', 'c', NULL);
184
ответ дан 05.11.2019, 10:27

Я не попробовал его, но

UPDATE tbl SET @temp=X, X=Y, Y=@temp

Мог бы сделать это.

Mark

1
ответ дан 05.11.2019, 10:27

ALTER TABLE table ADD COLUMN tmp;
UPDATE table SET tmp = X;
UPDATE table SET X = Y;
UPDATE table SET Y = tmp;
ALTER TABLE table DROP COLUMN tmp;
Что-то вроде этого?

Редактирование: О комментарии Greg: Нет, это не работает:

mysql> select * from test;
+------+------+
| x    | y    |
+------+------+
|    1 |    2 |
|    3 |    4 |
+------+------+
2 rows in set (0.00 sec)

mysql> обновляют набор тестов x=y, y=x; Запрос хорошо, 2 затронутые строки (0,00 секунды) строки соответствовал: 2 Измененных: 2 Предупреждения: 0

mysql> выбирают * из теста; +------+------+ | x | y | +------+------+ | 2 | 2 | | 4 | 4 | +------+------+ 2 строки в наборе (0,00 секунды)

4
ответ дан 05.11.2019, 10:27

Принятие Вас имеет целые числа со знаком в Ваших столбцах, Вы, возможно, должны использовать БРОСОК (^ b ПОДПИСАННЫЙ AS), так как результатом ^ оператора является неподписанное 64-разрядное целое число в MySQL.

В случае, если это помогает любому, вот метод, я раньше подкачивал тот же столбец между двумя данными строками:

SELECT BIT_XOR(foo) FROM table WHERE key = $1 OR key = $2

UPDATE table SET foo = CAST(foo ^ $3 AS SIGNED) WHERE key = $1 OR key = $2

то, где 1$ и 2$ являются ключами двух строк и 3$, является результатом первого запроса.

1
ответ дан 05.11.2019, 10:27

Две альтернативы 1. Используйте временную таблицу 2. Займитесь расследованиями алгоритм XOR

4
ответ дан 05.11.2019, 10:27

Хорошо, поэтому только для забавы, Вы могли сделать это! (принятие Вы подкачиваете строковые значения)

mysql> select * from swapper;
+------+------+
| foo  | bar  |
+------+------+
| 6    | 1    | 
| 5    | 2    | 
| 4    | 3    | 
+------+------+
3 rows in set (0.00 sec)

mysql> update swapper set 
    -> foo = concat(foo, "###", bar),
    -> bar = replace(foo, concat("###", bar), ""),
    -> foo = replace(foo, concat(bar, "###"), "");

Query OK, 3 rows affected (0.00 sec)
Rows matched: 3  Changed: 3  Warnings: 0

mysql> select * from swapper;
+------+------+
| foo  | bar  |
+------+------+
| 1    | 6    | 
| 2    | 5    | 
| 3    | 4    | 
+------+------+
3 rows in set (0.00 sec)

А хороший бит забавы, злоупотребляя слева направо процесс оценки в MySQL.

, С другой стороны, просто использование XOR, если они - числа. Вы упомянули координаты, у Вас есть прекрасные целочисленные значения или сложные строки?

Редактирование: XOR наполняют работы как это между прочим:

update swapper set foo = foo ^ bar, bar = foo ^ bar, foo = foo ^ bar;
5
ответ дан 05.11.2019, 10:27

настольный приемник ОБНОВЛЕНИЯ X=Y, Y=X сделает точно, что Вы хотите (редактирование: в PostgreSQL, не MySQL, посмотрите ниже). Значения приняты от старой строки и присвоены новой копии той же строки, тогда старая строка заменяется. Вы не должны обращаться к использованию временной таблицы, временного столбца или других приемов подкачки.

@D4V360:Ясно. это является шокирующим и неожиданным. Я использую PostgreSQL, и мой ответ работает правильно там (я попробовал его). Посмотрите документы ОБНОВЛЕНИЯ PostgreSQL (под Параметрами, выражением), где оно упоминает, что выражения на правой стороне пунктов НАБОРА явно используют старые значения столбцов. Я вижу, что соответствие документы MySQL UPDATE содержат оператор "Single-table UPDATE assignments are generally evaluated from left to right", который подразумевает поведение, которое Вы описываете.

Хороший для знания.

10
ответ дан 05.11.2019, 10:27

Это, конечно, работает! Мне только что был нужен он для свопинга Евро и ценовых столбцов SKK.:)

UPDATE tbl SET X=Y, Y=@temp where @temp:=X;

Вышеупомянутое не будет работать (ОШИБКА 1064 (42000): у Вас есть ошибка в Вашем синтаксисе SQL)

2
ответ дан 05.11.2019, 10:27

Следующий код работает на все сценарии в моем быстром тестировании:

UPDATE table swap_test
   SET x=(@temp:=x), x = y, y = @temp
23
ответ дан 05.11.2019, 10:27

Теги

Похожие вопросы