我有两个与这种结构有一对多关系的表:
meeting meeting_person
+--+------------+ +--+----------+-----------+---------+
|id|meeting_type| |id|meeting_id|person_type|person_id|
+--+------------+ +--+----------+-----------+---------+
|1 | 1 | |1 | 1| 1| 100 |
|2 | 2 | |2 | 1| 1| 101 |
+--+------------+ |3 | 1| 2| 102 |
|4 | 2| 3| 103 |
+--+----------+-----------+---------+
我想要做的是在插入之前检查特定记录是否存在,如果是,则警告用户
问题是,我需要检查是否存在与meeting_type
和person_id
person_type
的会议,以及所有人的会议。
例如,如果使用给定的数据,我想插入meet_type = 1的会议和这样的meeting_persons:
答案 0 :(得分:1)
如上所述,您需要使用触发器。我可能会建议更改数据结构以在meeting_type
中包含meeting_person
。是的,我知道这违反了正常形式。但如果你拥有它,你可以用一个简单的约束强制执行你的逻辑:
alter table meeting_person add constraint unq_meetingperson_person_type
unique (person_id, meeting_type);
你怎么能安全地做到这一点?使用外键关系:
alter table meeting add constraint unq_meeting_type_id
unique (type, id);
alter table meeting_person add constraint fk_meetingperson_meetingtype_id
foreign key (meeting_type, id) references meeting(meeting_type, id);
这会为额外的(不必要的)索引带来额外的空间。它需要在meeting_type
中包含一个额外的列。但它确实允许您在不使用触发器的情况下实现此逻辑。
答案 1 :(得分:1)
您想知道会议类型和相关人员的会议是否已存在。所以加入并计算:
select count(*)
from
(
select m.id
from meeting m
join meeting_persion mp on mp.meeting_id = m.id
where m.meeting_type = 1
and (mp.person_type, mp.person_id) in ((1,100),(1,101),(2,102))
group by m.id
having count(*) = 3
);
此查询会产生匹配会议数(0或更多)。
但是,如果您只对那些人的会议感兴趣,即没有其他人,那么您必须将人员标准从WHERE
移至HAVING
:
select count(*)
from
(
select m.id
from meeting m
join meeting_persion mp on mp.meeting_id = m.id
where m.meeting_type = 1
group by m.id
having count(case when (mp.person_type, mp.person_id) in ((1,100),(1,101),(2,102))
then 1 end) = 3
and count(*) = 3
);
此查询会产生匹配会议的数量(0或1)。
答案 2 :(得分:0)
怎么样:
WITH MEETING(ID, MEETING_TYPE) AS
(SELECT 1, 1 FROM DUAL
UNION SELECT 2, 2 FROM DUAL),
MEETING_PERSON(ID, MEETING_ID, PERSON_TYPE, PERSON_ID) AS
(SELECT 1, 1, 1, 100 FROM DUAL
UNION SELECT 2, 1, 1, 101 FROM DUAL
UNION SELECT 3, 1, 2, 102 FROM DUAL
UNION SELECT 4, 2, 3, 103 FROM DUAL)
SELECT CASE WHEN COUNT(*) = 0 THEN 'Yes' ELSE 'No' END AS show_warning FROM meeting, meeting_person
WHERE meeting.id = meeting_person.meeting_id
AND meeting.meeting_type = 1
AND (person_type, person_id) NOT IN ( (1,100),(1,101),(2,102) ); -- comment this and uncomment second line for second example to check
--AND (person_type, person_id) NOT IN ( (1,100) );