Обновление SQL для 3 таблиц — Где проблема с предложением (?)

Нам нужно обновить различные столбцы в 3 разных таблицах через форму ввода. большая часть этого работает, однако, когда мы пытаемся обновить две другие таблицы, которые были объединены (издатель и категория), он обновляет эту запись и все остальные записи с тем же вводом.

(например, если мы изменим жанр с металла на джаз, то все металлические диски также изменятся на джаз)

Ниже приведен код для обновления.

$sql = "UPDATE nmc_cd, nmc_category, nmc_publisher
SET CDTitle ='$title', CDYear = '$year', nmc_publisher.pubID = '$publisherID', nmc_category.catID = '$categoryID', CDPrice = '$price', pubName ='$pubName', catDesc='$catDesc'
WHERE CDID = $id
AND nmc_category.catID = nmc_cd.catID
AND nmc_publisher.pubID = nmc_cd.pubID";

Я относительно новичок в этом сайте, поэтому, пожалуйста, если что-то, например, код, имена переменных / функций и т. Д. Необходимо, пожалуйста, скажите, и я отредактирую свой пост или ответ.

Заранее спасибо!

0

Решение

Пара рекомендаций.

1) квалифицировать все ссылки на столбцы в операторе SQL, которые ссылаются на несколько таблиц, даже если ссылки на столбцы не являются неоднозначными для MySQL. (Также рассмотрите возможность присвоения короткого псевдонима каждой таблице.) Несколько причин для этого, но одна большая из них заключается в том, что он позволяет читателю узнать, в какой таблице находится каждый столбец, на который ссылаются.

2) отказаться от оператора запятой старой школы для операций соединения и использовать JOIN ключевое слово. Также переместите предикаты соединения из WHERE пункт к соответствующему ON пункт.

3) для множественного обновления, сначала напишите SELECT утверждение, получить, что работает и проверено, а затем преобразовать это в UPDATE заявление

4) избегать уязвимостей SQL-инъекций. Предпочтительным шаблоном является использование подготовленных операторов с заполнителями связывания. Или (менее оптимально) как минимум, все потенциально небезопасные значения, включенные в текст SQL, должны быть должным образом экранированы.


Игнорирование уязвимостей SQL-инъекций (при условии, что содержимое переменных уже правильно экранировано) …

Сначала я написал бы инструкцию SELECT, которая возвращает текущие значения столбцов, которые мы планируем обновить, а также новые значения, которые мы планируем назначить этим столбцам. Например:

 SELECT cd.cdtitle      AS old_cd_cdtitle
, '$title'        AS new_cd_cdtitle

, cd.cdyear       AS old_cdyear
, '$year'         AS new_cdyear

, pub.pubid       AS old_pub_pubid
, '$publisherID'  AS new_pub_pubid

, cat.catid       AS old_cat_catid
, '$categoryID'   AS new_cat_catid

, cd.cdprice      AS old_cd_cdprice
, '$price'        AS new_cd_cdprice

, pub.pubName     AS old_pub_pubname
, '$pubName'      AS new_pub_pubname

, cat.catDesc     AS old_cat_catdesc
, '$catDesc'      AS new_cat_catdesc

FROM nmc_cd cd
JOIN nmc_category cat
ON cat.catID = cd.catid
JOIN nmc_publisher pub
ON pub.pubID = cd.pubid
WHERE cd.cdid = $id

(Это всего лишь предположение, я не уверен, чего вы на самом деле пытаетесь достичь.)

Кажется действительно странным присвоить новое значение catid столбец, на который ссылается предикат соединения. Чтобы сохранить отношения между строками в cd а также cat, catid в столбце в обеих таблицах нужно будет обновить, если мы не зависим от ON UPDATE CASCADE Правило распространять изменения.

Без понимания того, чего пытается достичь это утверждение, невозможно рекомендовать какое-либо конкретное утверждение.

С точки зрения преобразования SELECT в UPDATE заявление, заменить SELECT ... FROM с ключевым словом UPDATE,

И до WHERE пункт, добавить SET заявление. Взяв выражения для old_cd_cdyear и new_cd_cdyear из списка SELECT, преобразуйте это в предложение SET следующим образом:

    SET cd.cdyear       = '$year'

При последующих назначениях вместо ключевого слова SET используйте запятую, например,

      , cd.cdprice      = '$price'
0

Другие решения

Других решений пока нет …