在加载到数据库或使用数据库之前规范化数据?
Normalize data before loading to database or use database?
我有一些数据想添加到现有的 mysql 数据库中。新数据可能有条目,这些条目已经保存在数据库中。由于我的某些专栏是唯一的,因此我得到了预期的 ER_DUP_ENTRY 错误。
批量插入
假设我想使用以下语句在 table mytable
的 names
列中保存“A”、“B”和“C”,而“A”是已经保存在那里了。
insert into mytable (names) values ("A"), ("B"), ("C");
有没有办法直接用bulk insert
保存“B”和“C”而忽略“A”?或者我是否必须为每个新行构建一个 insert
语句?这就引出了另一个问题:
标准化数据
我是否应该确保在 实际 insert
声明之前 不上传重复的条目?在我的例子中,我需要 select
来自数据库的数据,消除重复项,然后执行上面看到的 insert
。还是应该由数据库完成的任务?
如果您有阻止导入的 UNIQUE 约束,您有几种方法可以解决这个问题:
INSERT IGNORE INTO mytable ...
如果任何单独的行违反了 UNIQUE 约束,它们将被跳过。插入其他行。
REPLACE INTO mytable ...
如果有任何行违反了 UNIQUE 约束,则删除现有行,然后插入新行。请记住这样做的副作用,例如,如果您有外键在引用已删除行的删除时级联。或者如果 INSERT 生成一个新的自增 id。
INSERT INTO mytable ... ON DUPLICATE KEY UPDATE ...
更大的灵活性。这不会删除原始行,但允许您根据具体情况为您选择的任何列设置新值。另请参阅我对 "INSERT IGNORE" vs "INSERT ... ON DUPLICATE KEY UPDATE"
的回答
如果您想使用 mysqlimport
或 SQL 等效语句 LOAD DATA INFILE
的批量加载,有一些选项与 INSERT IGNORE 或 REPLACE 解决方案相匹配,但与 INSERT 不匹配...关于重复密钥更新解决方案。
阅读文档了解更多信息:
在某些情况下,我喜欢这样做:
LOAD DATA
进入临时 table
- 清理数据
- 根据需要进行标准化。 (每列需要规范化 2 SQLs -- details)
- 扩充摘要 table(s) (
INSERT .. ON DUPLICATE KEY .. SELECT x, y, count(*), sum(z), .. GROUP BY x,y
)
- 将干净的数据从临时 table 复制到实际 table(s) ("Fact" table)。 (
INSERT [IGNORE] .. SELECT [DISTINCT] ..
或带 SELECT
的 IODKU。)
关于规范化的更多信息:
- 我在任何交易之外进行。这样做更好的原因有很多。
- 在最坏的情况下(由于其他失败),我偶尔会在规范化中抛出一个未使用的条目 table。没什么大不了的。
- 不燃烧
AUTO_INCREMENT
个 ID(边缘情况除外)。
- 非常快。
因为REPLACE
是DELETE
加上INSERT
所以几乎可以保证比IODKU差。但是,当行存在时,两者都会刻录 ID。
如果可能的话,不要"loop"逐行;而是找到 SQL 语句来一次处理它们。
根据具体情况,在第 2 步(如果有很多重复项)或第 5 步(重复项不常见)中删除重复项。
我有一些数据想添加到现有的 mysql 数据库中。新数据可能有条目,这些条目已经保存在数据库中。由于我的某些专栏是唯一的,因此我得到了预期的 ER_DUP_ENTRY 错误。
批量插入
假设我想使用以下语句在 table mytable
的 names
列中保存“A”、“B”和“C”,而“A”是已经保存在那里了。
insert into mytable (names) values ("A"), ("B"), ("C");
有没有办法直接用bulk insert
保存“B”和“C”而忽略“A”?或者我是否必须为每个新行构建一个 insert
语句?这就引出了另一个问题:
标准化数据
我是否应该确保在 实际 insert
声明之前 不上传重复的条目?在我的例子中,我需要 select
来自数据库的数据,消除重复项,然后执行上面看到的 insert
。还是应该由数据库完成的任务?
如果您有阻止导入的 UNIQUE 约束,您有几种方法可以解决这个问题:
INSERT IGNORE INTO mytable ...
如果任何单独的行违反了 UNIQUE 约束,它们将被跳过。插入其他行。
REPLACE INTO mytable ...
如果有任何行违反了 UNIQUE 约束,则删除现有行,然后插入新行。请记住这样做的副作用,例如,如果您有外键在引用已删除行的删除时级联。或者如果 INSERT 生成一个新的自增 id。
INSERT INTO mytable ... ON DUPLICATE KEY UPDATE ...
更大的灵活性。这不会删除原始行,但允许您根据具体情况为您选择的任何列设置新值。另请参阅我对 "INSERT IGNORE" vs "INSERT ... ON DUPLICATE KEY UPDATE"
的回答如果您想使用 mysqlimport
或 SQL 等效语句 LOAD DATA INFILE
的批量加载,有一些选项与 INSERT IGNORE 或 REPLACE 解决方案相匹配,但与 INSERT 不匹配...关于重复密钥更新解决方案。
阅读文档了解更多信息:
在某些情况下,我喜欢这样做:
LOAD DATA
进入临时 table- 清理数据
- 根据需要进行标准化。 (每列需要规范化 2 SQLs -- details)
- 扩充摘要 table(s) (
INSERT .. ON DUPLICATE KEY .. SELECT x, y, count(*), sum(z), .. GROUP BY x,y
) - 将干净的数据从临时 table 复制到实际 table(s) ("Fact" table)。 (
INSERT [IGNORE] .. SELECT [DISTINCT] ..
或带SELECT
的 IODKU。)
关于规范化的更多信息:
- 我在任何交易之外进行。这样做更好的原因有很多。
- 在最坏的情况下(由于其他失败),我偶尔会在规范化中抛出一个未使用的条目 table。没什么大不了的。
- 不燃烧
AUTO_INCREMENT
个 ID(边缘情况除外)。 - 非常快。
因为REPLACE
是DELETE
加上INSERT
所以几乎可以保证比IODKU差。但是,当行存在时,两者都会刻录 ID。
如果可能的话,不要"loop"逐行;而是找到 SQL 语句来一次处理它们。
根据具体情况,在第 2 步(如果有很多重复项)或第 5 步(重复项不常见)中删除重复项。