Ограничения внешнего ключа MySQL, каскадное удаление

Если вы выбираете текст, вам не нужно отключать состояние, это самый простой способ. Для поддержки копирования вы можете использовать внешний объект - Button - для выполнения задания. Всякий раз, когда пользователь нажимает кнопку, содержимое Text будет скопировано в буфер обмена. Tk имеет встроенную поддержку обработки буфера обмена (см. здесь ), поэтому эмуляция поведения Ctrl-C является легкой задачей. Если вы строите, скажем, консоль, на которой записаны сообщения журнала, вы можете пойти дальше и добавить Entry, где пользователь может указать количество сообщений журнала, которые он хочет скопировать.

147
задан Cudos 27 May 2010 в 07:24
поделиться

2 ответа

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

CREATE TABLE categories (
    id int unsigned not null primary key,
    name VARCHAR(255) default null
)Engine=InnoDB;

CREATE TABLE products (
    id int unsigned not null primary key,
    name VARCHAR(255) default null
)Engine=InnoDB;

CREATE TABLE categories_products (
    category_id int unsigned not null,
    product_id int unsigned not null,
    PRIMARY KEY (category_id, product_id),
    KEY pkey (product_id),
    FOREIGN KEY (category_id) REFERENCES categories (id)
       ON DELETE CASCADE
       ON UPDATE CASCADE,
    FOREIGN KEY (product_id) REFERENCES products (id)
       ON DELETE CASCADE
       ON UPDATE CASCADE
)Engine=InnoDB;

Таким образом, вы можете удалить продукт ИЛИ категорию, и только связанные записи в категориях_products погибнут вместе. Каскад не продвигается дальше по дереву и не удаляет родительскую таблицу товаров / категорий.

например.

products: boots, mittens, hats, coats
categories: red, green, blue, white, black

prod/cats: red boots, green mittens, red coats, black hats

Если вы удалите «красную» категорию, то погибнет только «красная» запись в таблице категорий, а также две записи prod / cats: «красные сапоги» и «красные пальто».

Удаление не будет происходить дальше и не удалит категории «ботинки» и «пальто».

продолжение комментария:

вы все еще не понимаете, как работает каскадное удаление. Они влияют только на таблицы, в которых определен каскад «при удалении». В этом случае каскад задается в таблице «Categories_products». Если вы удалите «красную» категорию, единственные записи, которые будут каскадно удалять в категориях_продукты, - это те, у которых идентификатор_категории = красный .Он не будет касаться записей, где 'category_id = blue', и не будет перемещаться дальше в таблицу «products», потому что в этой таблице не определен внешний ключ.

Вот более конкретный пример:

categories:     products:
+----+------+   +----+---------+
| id | name |   | id | name    |
+----+------+   +----+---------+
| 1  | red  |   | 1  | mittens |
| 2  | blue |   | 2  | boots   |
+---++------+   +----+---------+

products_categories:
+------------+-------------+
| product_id | category_id |
+------------+-------------+
| 1          | 1           | // red mittens
| 1          | 2           | // blue mittens
| 2          | 1           | // red boots
| 2          | 2           | // blue boots
+------------+-------------+

Допустим, вы удаляете категорию № 2 (синюю):

DELETE FROM categories WHERE (id = 2);

СУБД просматривает все таблицы, внешний ключ которых указывает на таблицу «категорий», и удаляет записи, в которых совпадающий идентификатор равен 2. Поскольку мы только определили отношения внешнего ключа в products_categories , вы получите эту таблицу после завершения удаления:

+------------+-------------+
| product_id | category_id |
+------------+-------------+
| 1          | 1           | // red mittens
| 2          | 1           | // red boots
+------------+-------------+

В продуктах нет внешнего ключа, определенного , поэтому каскад там работать не будет, значит, у вас все еще указаны ботинки и рукавицы. Больше нет ни «синих сапог», ни «синих варежек».

373
ответ дан 23 November 2019 в 22:08
поделиться

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

CREATE PROCEDURE `DeleteCategory` (IN category_ID INT)
LANGUAGE SQL
NOT DETERMINISTIC
MODIFIES SQL DATA
SQL SECURITY DEFINER
BEGIN

DELETE FROM
    `products`
WHERE
    `id` IN (
        SELECT `products_id`
        FROM `categories_products`
        WHERE `categories_id` = category_ID
    )
;

DELETE FROM `categories`
WHERE `id` = category_ID;

END

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

ALTER TABLE `categories_products` ADD
    CONSTRAINT `Constr_categoriesproducts_categories_fk`
    FOREIGN KEY `categories_fk` (`categories_id`) REFERENCES `categories` (`id`)
    ON DELETE CASCADE ON UPDATE CASCADE,
    CONSTRAINT `Constr_categoriesproducts_products_fk`
    FOREIGN KEY `products_fk` (`products_id`) REFERENCES `products` (`id`)
    ON DELETE CASCADE ON UPDATE CASCADE

Предложение CONSTRAINT, конечно, также может появиться в операторе CREATE TABLE.

Создав эти объекты схемы, вы можете удалить категорию и получить желаемое поведение, выполнив CALL DeleteCategory (category_ID) (где category_ID - это категория, которую нужно удалить), и она будет вести себя так, как вы хотеть.Но не выполняйте обычный запрос УДАЛИТЬ ИЗ , если вы не хотите более стандартного поведения (т.е. удалить только из таблицы связывания и оставить только таблицу продукты ).

8
ответ дан 23 November 2019 в 22:08
поделиться
Другие вопросы по тегам:

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