powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Помогите, пожалуйста, с UPDATE
11 сообщений из 11, страница 1 из 1
Помогите, пожалуйста, с UPDATE
    #39855202
LiYing
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Имеется три таблицы:
1. Справочник улиц
Код: sql
1.
2.
3.
4.
5.
6.
CREATE TABLE `streets` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(30) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `i_name` (`name`)
) ENGINE=InnoDB;


2. Справочник домов, использующий улицы
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
CREATE TABLE `mkd` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `id_street` int(11) DEFAULT NULL,
  `addr_building` varchar(5) DEFAULT NULL,
  `addr_letter` varchar(3) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `mk_sbl` (`id_street`,`addr_building`,`addr_letter`),
  KEY `fk_street` (`id_street`),
  CONSTRAINT `fk_street` FOREIGN KEY (`id_street`) REFERENCES `streets` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB; 


3. И таблица, в которой надо обновить поле `id_mkd` (=id из спр-ка домов) на основании трех полей из нее же: `addr_street`, `addr_building`, `addr_letter`
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
CREATE TABLE `csv_1` (
  `id_mkd` int(11) DEFAULT '0',
  `addr_street` varchar(30) DEFAULT NULL,
  `addr_building` varchar(5) DEFAULT NULL,
  `addr_letter` varchar(3) DEFAULT NULL,
  `addr_flat` varchar(8) DEFAULT NULL,
  KEY `mk` (`addr_street`,`addr_building`,`addr_letter`)
) ENGINE=InnoDB;


Написал так:
Код: sql
1.
2.
3.
4.
UPDATE csv_1 c SET id_mkd=(
	SELECT id FROM mkd m 
	WHERE (id_street=(SELECT id FROM streets WHERE name=addr_street)) AND (m.addr_building=c.addr_building) AND (m.addr_letter=c.addr_letter)
)


но > Affected rows: 0
В чем ошибка?
...
Рейтинг: 0 / 0
Помогите, пожалуйста, с UPDATE
    #39855233
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LiYingВ чем ошибка?В том, что надо читать документацию на используемую СУБД, а не писать запросы по старой привычке.

https://dev.mysql.com/doc/refman/8.0/en/update.html
Multiple-table syntax
И последний пример.
...
Рейтинг: 0 / 0
Помогите, пожалуйста, с UPDATE
    #39855242
LiYing
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Akina,
ммм, но что писать в WHERE?
Код: sql
1.
2.
UPDATE csv_1,mkd SET csv_1.id_mkd=mkd.id
WHERE ...
...
Рейтинг: 0 / 0
Помогите, пожалуйста, с UPDATE
    #39855259
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LiYingчто писать в WHERE?
Ну собственно все условия соответствия. Типа

Код: sql
1.
2.
3.
4.
5.
6.
UPDATE csv_1 c, mkd m, streets s
SET c.id_mkd=m.id
WHERE c.addr_street = s.name
  AND c.addr_building = m.addr_building
  AND c.addr_letter = m.addr_letter
  AND s.id = m.id_street
...
Рейтинг: 0 / 0
Помогите, пожалуйста, с UPDATE
    #39855260
LiYing
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот такой работает без последнего условия AND (mkd.addr_letter=csv_1.addr_letter)
Код: sql
1.
2.
UPDATE csv_1,mkd SET csv_1.id_mkd=mkd.id
WHERE (mkd.id_street=(SELECT id FROM streets WHERE name=csv_1.addr_street)) AND (mkd.addr_building=csv_1.addr_building) AND (mkd.addr_letter=csv_1.addr_letter)


Подозреваю, это из-за того, что `addr_letter` может быть NULL, в то время как другие поля никогда не NULL. И как это победить? Разве проверка AND (NULL=NULL) не равно true?
...
Рейтинг: 0 / 0
Помогите, пожалуйста, с UPDATE
    #39855262
LiYing
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Akina,

Ваш запрос тоже не сработал, видимо из-за той же проблемы с NULL
...
Рейтинг: 0 / 0
Помогите, пожалуйста, с UPDATE
    #39855269
LiYing
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Akina,
А вот так работает. Это корректно или можно/нужно по другому?
Код: sql
1.
2.
3.
4.
5.
6.
UPDATE csv_1 c, mkd m, streets s
SET c.id_mkd=m.id
WHERE c.addr_street = s.name
  AND c.addr_building = m.addr_building
  AND IFNULL(c.addr_letter,0) = IFNULL(m.addr_letter,0)
  AND s.id = m.id_street
...
Рейтинг: 0 / 0
Помогите, пожалуйста, с UPDATE
    #39855282
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LiYingА вот так работает.А addr_letter может быть NULL в обеих таблицах? И если в обеих NULL, то это - соответствие? тогда используйте NULL-safe equial оператор:
Код: sql
1.
  AND c.addr_letter <=> m.addr_letter
...
Рейтинг: 0 / 0
Помогите, пожалуйста, с UPDATE
    #39855429
LiYing
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
AkinaА addr_letter может быть NULL в обеих таблицах? И если в обеих NULL, то это - соответствие?
Да, верно. Оператор <=> работает. В очередной раз благодарю за профессиональную помощь!

А можете пояснить, пожалуйста, почему для таблицы csv_2 с 18757 строками и запросом, использующем IFNULL, получается такой explain:


А запрос использующий <=>, такой:


Почему rows для UPDATE в 1-м случае равно кол-ву строк таблицы, а 2-м всего лишь 71 (и 63*4*71=17892)?
...
Рейтинг: 0 / 0
Помогите, пожалуйста, с UPDATE
    #39855435
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Простой оператор сравнения (в том числе и NULL-safe) полей может использовать индекс. А если используется функция от поля - нет, выполняется fullscan. Именно поэтому во всех условиях выражения стараются строить от констант, а не от полей.

Того же эффекта можно добиться, если в структуру ввести хранимое вычисляемое поле с используемым функциональным выражением, и проиндексировать его.
...
Рейтинг: 0 / 0
Помогите, пожалуйста, с UPDATE
    #39855436
LiYing
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Akina,

Спасибо за ликбез!
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Помогите, пожалуйста, с UPDATE
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]