- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
曾几何时,我有一张这样的 table :
CREATE TABLE `Events` (
`EvtId` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`AlarmId` INT UNSIGNED,
-- Other fields omitted for brevity
PRIMARY KEY (`EvtId`)
);
AlarmId
被允许为 NULL
。
现在,因为我想从每个事件的零个或一个警报扩展到每个事件的零个或多个警报,所以在软件更新中,我正在更改我的数据库实例以改为拥有这个:
CREATE TABLE `Events` (
`EvtId` INT UNSIGNED NOT NULL AUTO_INCREMENT,
-- Other fields omitted for brevity
PRIMARY KEY (`EvtId`)
);
CREATE TABLE `EventAlarms` (
`EvtId` INT UNSIGNED NOT NULL,
`AlarmId` INT UNSIGNED NOT NULL,
PRIMARY KEY (`EvtId`, `AlarmId`),
CONSTRAINT `fk_evt` FOREIGN KEY (`EvtId`) REFERENCES `Events` (`EvtId`)
ON DELETE CASCADE ON UPDATE CASCADE
);
到目前为止一切顺利。
数据也很容易迁移:
INSERT INTO `EventAlarms`
SELECT `EvtId`, `AlarmId` FROM `Events` WHERE `AlarmId` IS NOT NULL;
ALTER TABLE `Events` DROP COLUMN `AlarmId`;
问题是,我的系统要求降级也是可能的。我承认降级有时会在数据方面造成损失,这没关系。但是,它们确实需要在可能的情况下工作,并导致旧的数据库结构,同时尽最大努力尽可能多地保留原始数据。
在这种情况下,这意味着从每个事件零个或多个警报变为每个事件零个或一个警报。我可以这样做:
ALTER TABLE `Events` ADD COLUMN `AlarmId` INT UNSIGNED;
UPDATE `Events`
LEFT JOIN `EventAlarms` USING(`EvtId`)
SET `Events`.`AlarmId` = `EventAlarms`.`AlarmId`;
DROP TABLE `EventAlarms`;
... 这很好,因为我真的不在乎保留哪一个(这是尽力而为,记住)。但是,如警告的那样,这不利于复制,因为结果可能无法预测:
> SHOW WARNINGS;
Unsafe statement written to the binary log using statement format since
BINLOG_FORMAT = STATEMENT. Statements writing to a table with an auto-
increment column after selecting from another table are unsafe because the
order in which rows are retrieved determines what (if any) rows will be
written. This order cannot be predicted and may differ on master and the
slave.
有没有办法以某种方式“命令”或“限制”更新中的加入,或者我应该跳过整个企业并停止尝试变得聪明?如果是后者,我如何才能将降级后的 AlarmId
保留为 NULL
iff 新表中有多行我们无法安全地区分?如果只有一个,我确实想迁移 AlarmId
。
由于降级是“一次性”维护操作,因此不必完全实时,但速度会很好。两个表都可能有数千行。
(CentOS 7 上的 MariaDB 5.5.56,但也必须适用于 CentOS 6 附带的任何产品。)
最佳答案
首先,我们可以使用自连接执行一些分析:
SELECT `A`.`EvtId`, COUNT(`B`.`EvtId`) AS `N`
FROM `EventAlarms` AS `A`
LEFT JOIN `EventAlarms` AS `B` ON (`A`.`EvtId` = `B`.`EvtId`)
GROUP BY `B`.`EvtId`
结果看起来像这样:
EvtId N
--------------
370 1
371 1
372 4
379 1
380 1
382 16
383 1
384 1
现在,如果您愿意,您可以删除所有表示映射到多个警报的事件的行(您建议将其作为后备解决方案;我认为这是有道理的,尽管您可以修改下面的内容以保留其中一个如果你真的想要,就到位)。
不过,与其实际DELETE
ing 任何东西,不如引入一个新表,使用上面显示的自连接查询填充:
CREATE TEMPORARY TABLE `_migrate` (
`EvtId` INT UNSIGNED,
`n` INT UNSIGNED,
PRIMARY KEY (`EvtId`),
KEY `idx_n` (`n`)
);
INSERT INTO `_migrate`
SELECT `A`.`EvtId`, COUNT(`B`.`EvtId`) AS `n`
FROM `EventAlarms` AS `A`
LEFT JOIN `EventAlarms` AS `B` ON(`A`.`EvtId` = `B`.`EvtId`)
GROUP BY `B`.`EvtId`;
然后你的更新变成:
UPDATE `Events`
LEFT JOIN `_migrate` ON (`Events`.`EvtId` = `_migrate`.`EvtId` AND `_migrate`.`n` = 1)
LEFT JOIN `EventAlarms` ON (`_migrate`.`EvtId` = `EventAlarms`.`EvtId`)
SET `Events`.`AlarmId` = `EventAlarms`.`AlarmId`
WHERE `EventAlarms`.`AlarmId` IS NOT NULL
最后,清理一下自己:
DROP TABLE `_migrate`;
DROP TABLE `EventAlarms`;
MySQL 仍然会发出与之前相同的警告,但由于知道最多会从源表中提取一个值,所以我们基本上可以忽略它。
它甚至应该相当高效,正如我们可以从等效的 EXPLAIN SELECT
中看出的那样:
EXPLAIN SELECT `Events`.`EvtId` FROM `Events`
LEFT JOIN `_migrate` ON (`Events`.`EvtId` = `_migrate`.`EvtId` AND `_migrate`.`n` = 1)
LEFT JOIN `EventAlarms` ON (`_migrate`.`EvtId` = `EventAlarms`.`EvtId`)
WHERE `EventAlarms`.`AlarmId` IS NOT NULL
id select_type table type possible_keys key key_len ref rows Extra
---------------------------------------------------------------------------------------------------------------------
1 SIMPLE _migrate ref PRIMARY,idx_n idx_n 5 const 6 Using index
1 SIMPLE EventAlarms ref PRIMARY,fk_AlarmId PRIMARY 8 db._migrate.EvtId 1 Using where; Using index
1 SIMPLE Events eq_ref PRIMARY PRIMARY 8 db._migrate.EvtId 1 Using where; Using index
关于mysql - 我可以控制在 UPDATE 中使用哪个 JOINed 行吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48389094/
有人知道 1u 在这个函数中的作用吗?以下函数接受一个整数并打印出它的位。我试图弄清楚的线是 putchar 线。我看到它需要一个无符号整数作为参数,并在二进制数大小的循环中迭代 1 或 0,这恰好发
我有一个 MySQL 数据库,存储了一个长而详细的时间序列(即,每分钟采样多次的多年测量值)。当我将此数据提供给客户端进行显示时,我想对数据进行下采样,这样我就不会向图表发送大量数据。例如,如果客户端
我有一个记录文章浏览量的表格。它有以下列: id, article_id, day, month, year, views_count. 假设我想跟踪每篇文章的每日浏览量/每一天。如果我有 1,000
写一个很长(200多行)的测试方法是不是太糟糕了?或者我应该把它分解成更小的方法? 最佳答案 您不应该(总体上)创建任何 200 行长的方法。如果你能打破它,就去做。 你在 200 行中做什么?单元测
我正在使用 SQL Server 2008-R2,但我也对更通用的答案感兴趣...... 我有一个包含数亿行的表,每行都有一个“DateModified”字段 (datetime2(7)) 现在我经常
SwiftMailer 需要一个电子邮件地址数组,可能包括名称作为数组的值: $message->setTo([ 'person1@example.org', 'person2@example
这个问题已经有答案了: MySQL - how many rows can I insert in one single INSERT statement? (8 个回答) 已关闭 3 年前。 我需要
我需要一个只有 n 行的 mysql 表。是否可以?有 1 行表的解决方案,但无法找到 n 行的任何内容。 最佳答案 如果您确实想在 mysql 中执行此操作,则必须编写一个触发器,每当插入行时都会调
我的日志文件很长,是否可以要求 grep 只搜索前 10 行? 最佳答案 管道的魔力; head -10 log.txt | grep 关于bash - 我可以只 grep 文件的前 n 行吗?,我
曾几何时,我有一张这样的 table : CREATE TABLE `Events` ( `EvtId` INT UNSIGNED NOT NULL AUTO_INCREMENT, `Al
我最近发现 dask旨在成为易于使用的python并行处理模块的模块。对我来说最大的卖点是它适用于 pandas。 在其手册页上阅读了一下之后,我找不到一种方法来完成这个琐碎的可并行化任务: ts.a
我刚刚安装并设置了一个 Doxygen 实例,但开箱即用时,它只能在代码中找到 TODO 标记,当标记在如下块中时: /** * @todo Foo */ 它似乎没有找到: // TODO Foo
我想知道这里有什么最佳实践。我正在制作一个表单,该表单具有通过 form-group 类分组的控件。这具有水平分组的控件,例如一行中的标题、名字、姓氏,然后下一行可以有日、月、年输入。 为了在一行中实
我想执行一个 MySQL 查询: SELECT * FROM table_A JOIN table_B on table_A.id = table_B.foreign_key …但我想返回表_B 中表
行不通,而嵌套
我一般不会嵌套像这样: The following: one two 我将使用 像那样嵌套反而。但是今天我用了但似乎 Emacs 和 Google Chrome 都会考虑外部 一看
我有这个代码 my $tmp = $q->param('owner'); $tmp =~ s/\s*//g; # remove white space from string my @owners
我有这些 div,每个都有相同的类 .onediv 和不同的 ID div1、div2、div3 我想使用 jquery 来改变它们的 css di
我正在阅读此文档:http://software.intel.com/en-us/articles/interactive-ray-tracing 我偶然发现了这三行代码: The SIMD vers
我需要通过调用 API 端点和数据格式为 JSON 来消耗大量数据(比如超过 100000 行)并将它们显示在 react 页面中。我正在使用 React-Table 开发逻辑,但想听听专家的意见,以
我正在尝试添加一条 GeoJSON 线来显示 A 点和 B 点之间的汽车方向(就像在 mapbox-gl-js 的官方文档中那样(https://www.mapbox.com/mapbox-gl-js
我是一名优秀的程序员,十分优秀!