【发布时间】:2011-05-19 04:55:30
【问题描述】:
我有一些结构良好的数据,如下所示:
CREATE TABLE SourceBodyPartColors
(
person_ID INTEGER NOT NULL,
body_part_name VARCHAR(5) NOT NULL
CHECK (body_part_name IN ('hair', 'eye', 'teeth')),
color VARCHAR(20) NOT NULL,
UNIQUE (color, body_part_name, person_ID)
);
INSERT INTO SourceBodyPartColors (person_ID, body_part_name, color)
VALUES (1, 'eye', 'blue'),
(1, 'hair', 'blond'),
(1, 'teeth', 'white'),
(2, 'hair', 'white'),
(2, 'teeth', 'yellow'),
(3, 'hair', 'red');
遗憾的是,目标结构并没有那么好,看起来更像这样:
CREATE TABLE TargetBodyPartColors
(
person_ID INTEGER NOT NULL UNIQUE,
eye_color VARCHAR(20),
hair_color VARCHAR(20),
teeth_color VARCHAR(20)
);
INSERT INTO TargetBodyPartColors (person_ID)
VALUES (1), (2), (3);
我可以像这样写一个 SQL-92 UPDATE:
UPDATE TargetBodyPartColors
SET eye_color = (
SELECT S1.color
FROM SourceBodyPartColors AS S1
WHERE S1.person_ID
= TargetBodyPartColors.person_ID
AND S1.body_part_name = 'eye'
),
hair_color = (
SELECT S1.color
FROM SourceBodyPartColors AS S1
WHERE S1.person_ID
= TargetBodyPartColors.person_ID
AND S1.body_part_name = 'hair'
),
teeth_color = (
SELECT S1.color
FROM SourceBodyPartColors AS S1
WHERE S1.person_ID
= TargetBodyPartColors.person_ID
AND S1.body_part_name = 'teeth'
);
...但是重复的代码困扰着我。
我认为使用MERGE 进行简化是一个很好的候选人,但我想不出任何合理的东西。
任何想法如何使用MERGE 处理此数据。 (注意:我想避免专有的UPDATE..FROM syntax,谢谢。)
【问题讨论】:
-
AFAIK,MERGE 是 SQL:2003,真的更好吗?
-
@marc_s:我明白为什么您可能认为它是 EAV,但实际上并非如此。请参阅有关第一范式 (en.wikipedia.org/wiki/First_normal_form) 的 Wikipedia 文章:“目标”结构类似于子标题“跨列重复组”下显示的
Customer表(即违反 1NF)。 “源”结构更像是在“符合 1NF 的设计”子标题下显示的Customer Telephone Table表。 -
@onedaywhen - 我不同意这一点。我违反 1NF 的经验法则是,您可以交换列值并最终得到语义相同的东西。如果您可以交换
tel1和tel2并且语义不变,那么这显然不在1NF 中。参考文献Facts and Fallacies about First Normal Form -
@Martin:您对 1NF 有自己的个人定义?!嗯,嗯,......我想这一定会让你感到安慰:)
-
@Martin:说真的。我认识到我快速起草的数据存在缺陷,例如“发色”和“眼色”不是同一个领域……谁有金色的眼睛?! :)
标签: sql tsql sql-server-2008 merge standards-compliance