Удалить из разных таблиц в одном запросе с подготовленными утверждениями - PullRequest
0 голосов
/ 17 мая 2018

Я хочу удалить несколько записей с указанным значением (не уникальным) в одной таблице и удалить запись с тем же заданным значением (уникальным) в другой таблице, используя подготовленный оператор.Вот что я получил,

$stmt = $conn->prepare("DELETE FROM Books WHERE Genre_ID=? AND FROM Library WHERE Genre_ID=?");
$stmt->bind_param("ii", $genreID, $genreID);    

Целью запроса было бы удалить указанный жанр из таблицы библиотеки по его идентификатору и, конечно же, удалить все книги из таблицы книг с этим идентификатором..

1 Ответ

0 голосов
/ 17 мая 2018

Лучше всего с двумя утверждениями ... одно удалить из Книги, а другое удалить из Библиотеки.

Чтобы сделать это одним оператором, мы могли бы использовать операцию соединения. Но есть проблема с «пропущенными» строками.

Мое предложение:

Сначала напишите оператор SELECT, протестируйте его, а затем преобразуйте в оператор DELETE.

 SELECT b.*
      , l.*
   FROM `Books` b
   JOIN `Library` l 
     ON l.genre_id = b.genre_id 
  WHERE b.genre_id = ? 

Но этот оператор не будет возвращать любых строк, если в Книгах и Библиотеке нет хотя бы одной строки с совпадающим genre_id.

Мы можем частично исправить это с помощью внешнего соединения.

 SELECT b.*
      , l.*
   FROM `Library` l 
   LEFT
   JOIN `Books` b
     ON b.genre_id = l.genre_id 
  WHERE l.genre_id = ?

Если в Библиотеке есть хотя бы одна строка с указанным genre_id, мы получим все Книги с тем же genre_id. Но он не будет возвращать никаких строк, если в библиотеке нет подходящей строки.

И MySQL не поддерживает полные внешние объединения, так что это все, что мы получаем. Мы можем сделать либо Библиотеку, либо Книгу движущей таблицей ... мы можем обрабатывать «пропущенные строки» из одной таблицы или другой.


РЕДАКТИРОВАТЬ

Как уродливый обходной путь

SELECT b.*
     , l.*
  FROM ( SELECT rb.genre_id
           FROM Books rb
          WHERE rb.genre_id = ?
          GROUP BY rb.genre_id
          UNION
         SELECT rl.genre_id
           FROM Library rl
          WHERE rl.genre_id = ?
          GROUP BY rl.genre_id
       ) r
  LEFT
  JOIN Books b
    ON b.genre_id = r.genre_id
  LEFT
  JOIN Library l
    ON l.genre_id = r.genre_id

Затем мы можем преобразовать это в оператор DELETE, заменив SELECT на DELETE

с проблемой пропущенных строк:

 DELETE b.*
      , l.*
   FROM `Library` l
   LEFT
   JOIN `Books` b
     ON b.genre_id = l.genre_id 
  WHERE l.genre_id = ?

Обратите внимание на ту же проблему ... это не удалит строки из Books, если в Library.

нет хотя бы одной подходящей строки.

EDIT

или с уродливым обходным решением. преобразовать SELECT в DELETE:

DELETE b.*
     , l.*
  FROM ( SELECT rb.genre_id
           FROM Books rb
          WHERE rb.genre_id = ?
          GROUP BY rb.genre_id
          UNION
         SELECT rl.genre_id
           FROM Library rl
          WHERE rl.genre_id = ?
          GROUP BY rl.genre_id
       ) r
  LEFT
  JOIN Books b
    ON b.genre_id = r.genre_id
  LEFT
  JOIN Library l
    ON l.genre_id = r.genre_id

Опять же, я рекомендую, чтобы эта операция выполнялась как два отдельных оператора: один для удаления строк из Книги, а другой для удаления строк из Библиотеки.

Я подозреваю, что между этими двумя таблицами нет ограничений по внешнему ключу. Если бы был, порядок выполнения этих удалений был бы важен.


Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...