gpt4 book ai didi

多列上的MySQL外键?

转载 作者:行者123 更新时间:2023-11-30 23:19:12 25 4
gpt4 key购买 nike

我还在学习MySQL,所以请多多包涵...

我有几个表(概述如下),我想为它们记录错误消息。我指的不是查询错误,而是我的消息,例如“站点连接失败”、“站点 xyz 卡读取错误”等...

我想有一个表“error_logs”来跟踪我的错误,只有三列:

  • 编号
  • 错误消息
  • 活跃

然而,我遇到的问题是每个错误都与“卡片”、“门”或“站点”表中的记录有关,我想跟踪哪条记录(来自各种表) 消息属于。

那么,我的问题是解决这个问题的最佳方法是什么?我考虑过添加两个额外的列,“record_id”(将引用另一个表中的 id)和“table”(它将跟踪消息属于哪个表)。另外,另一个警告是, future 很可能会有更多的“主要”表。

这是我到目前为止的表格:

CREATE TABLE `statuses` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1$$;

INSERT INTO statuses SET name = 'error';
INSERT INTO statuses SET name = 'pre-install';
INSERT INTO statuses SET name = 'validate';
INSERT INTO statuses SET name = 'active';
INSERT INTO statuses SET name = 'disabled';

CREATE TABLE `sites` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
`status_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `sites_status_id_idx` (`status_id`),
CONSTRAINT `sites_status_id` FOREIGN KEY (`status_id`) REFERENCES `statuses` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1$$;

CREATE TABLE `doors` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`description` varchar(255) NOT NULL,
`site_id` int(11) NOT NULL,
`status_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `doors_site_id_idx` (`site_id`),
KEY `doors_status_id_idx` (`status_id`),
CONSTRAINT `doors_status_id` FOREIGN KEY (`status_id`) REFERENCES `statuses` (`id`) ON UPDATE CASCADE,
CONSTRAINT `doors_site_id` FOREIGN KEY (`site_id`) REFERENCES `sites` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1$$;

CREATE TABLE `card_types` (
`id` int(11) NOT NULL,
`manufacturer` varchar(45) DEFAULT NULL,
`sequance` varchar(32) DEFAULT NULL,
`auth_code` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1$$;

CREATE TABLE `cards` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`number` int(11) NOT NULL,
`type_id` int(11) NOT NULL,
`status_id` int(11) NOT NULL,
`is_oem` bit(1) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `number_UNIQUE` (`number`),
KEY `cards_type_id_idx` (`type_id`),
KEY `cards_status_id_idx` (`status_id`),
CONSTRAINT `cards_status_id` FOREIGN KEY (`status_id`) REFERENCES `statuses` (`id`) ON UPDATE CASCADE,
CONSTRAINT `cards_type_id` FOREIGN KEY (`type_id`) REFERENCES `card_types` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1$$;

CREATE TABLE `card_assignments` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`door_id` int(11) NOT NULL,
`status_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `card_assignments_door_id_idx` (`door_id`),
KEY `card_assignments_status_id_idx` (`status_id`),
CONSTRAINT `card_assignments_door_id` FOREIGN KEY (`door_id`) REFERENCES `doors` (`id`) ON UPDATE CASCADE,
CONSTRAINT `card_assignments_status_id` FOREIGN KEY (`status_id`) REFERENCES `statuses` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1$$;

最佳答案

我认为你的建议是完全正确的。请务必选择一个 enumtable_name 字段的数据类型;这样,不同的表名得到通过 MySQL 透明地映射到整数值。这将使用比 VARCHAR 字段更少的内存与特定表相关的 SELECTing 错误会更快。额外的INDEX/KEY over table_name record_id 将进一步提高性能。您可以按如下方式创建表格:

CREATE TABLE IF NOT EXISTS `error_logs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`table_name` enum('sites','tables','doors') CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`record_id` int(11) NOT NULL DEFAULT '0',
`error_message` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`is_active` tinyint(4) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
KEY `table_name` (`table_name`,`record_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ;

通过 table_name 选择错误就像:

SELECT * FROM error_logs WHERE table_name = 'sites'

如前所述添加其他实体和表时,请记住适本地扩展table_name enum

我发现在您的情况下有些劣势的替代方案是为每个主表使用单独的 id 字段:

CREATE TABLE IF NOT EXISTS `error_logs2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`cards_id` int(11) DEFAULT NULL,
`doors_id` int(11) DEFAULT NULL,
`sites_id` int(11) DEFAULT NULL,
`error_message` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`is_active` tinyint(4) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
KEY `cards_id` (`cards_id`),
KEY `doors_id` (`doors_id`),
KEY `sites_id` (`sites_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

在这里,只有一个 id 字段将包含一个值,另外两个将是 NULL。用于插入与站点表和记录 ID 1 相关的错误:

INSERT INTO `error_logs2` (`id`, `cards_id`, `doors_id`, `sites_id`, `error_message`, `is_active`)
VALUES (NULL, NULL, NULL, '1', 'Exception has occurred: Division by zero.', '1')

SELECTing 站点错误将按如下方式工作:

SELECT * FROM error_logs2 WHERE sites_id IS NOT NULL

但是,为了能够将错误与新实体相关联,您必须向 error_logs2 表中添加一个新列。但是,为一个特定的实体和 id 选择错误只需要一个字段比较,例如:

SELECT * FROM error_logs2 WHERE cards_id = 5

关于多列上的MySQL外键?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16305909/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com