Sql 检查一对多表中是否存在特定记录

Sql 检查一对多表中是否存在特定记录,sql,oracle,Sql,Oracle,我有两个表与这种结构有一对多的关系: meeting meeting_person +--+------------+ +--+----------+-----------+---------+ |id|meeting_type| |id|meeting_id|person_type|person_id| +--+------------+ +--+----------+-----------+---------+ |1 | 1 |

我有两个表与这种结构有一对多的关系:

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 |
                     +--+----------+-----------+---------+
我要做的是在插入之前检查特定记录是否存在,如果存在,则向用户发出警告。
问题是,我需要检查是否存在具有
会议类型
人员id
人员类型
的会议,以及是否存在适用于所有人员的会议。
例如,如果使用给定数据,我希望插入meeting_type=1的会议以及此类会议_人员:

  • 人员类型=1,人员id=100
  • 人员类型=1,人员id=101
  • 人员类型=2,人员id=102
    然后用户将看到警告。
    但是,如果我想插入与meeting_type=1的会议以及此类会议人员:
  • 人员类型=1,人员id=100
    然后用户不应看到警告,应插入记录。
    我就是想不出办法,怎么检查这个

按照措辞,您需要为此使用触发器。我可能建议更改数据结构,将
会议类型
包含在
会议人员
中。是的,我知道这违反了标准形式。但如果你有它,你可以用一个简单的约束来强制你的逻辑:

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);

这会为额外的(不必要的)索引带来额外的空间。它确实需要在
会议类型中包含一个额外的列。但是,它确实允许您在不使用触发器的情况下实现此逻辑。

如前所述,您需要为此使用触发器。我可能建议更改数据结构,将
会议类型
包含在
会议人员
中。是的,我知道这违反了标准形式。但如果你有它,你可以用一个简单的约束来强制你的逻辑:

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);
这会为额外的(不必要的)索引带来额外的空间。它确实需要在
会议类型中包含一个额外的列。但它确实允许您在不使用触发器的情况下实现此逻辑。

如何:

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) );
那么:

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) );

您想知道是否已经存在具有会议类型和相关人员的会议。因此,加入并计数:

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)。

您想知道是否已经存在具有会议类型和相关人员的会议。因此,加入并计数:

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)。

因为只有当所有条件相同时,即所有具有该类型的人员都匹配时,才应发出警告。在第一个示例中,我尝试插入精确的值,而在第二个示例中,我尝试只插入现有值的子集,这些值被视为不同的值,因此应该插入。我已更新了答案。请检查这是否符合您的需要。因为只有在所有条件相同时,即所有具有该类型的人员都匹配时,才应发出警告。在第一个示例中,我尝试插入精确的值,而在第二个示例中,我尝试只插入现有值的子集,这些值被视为不同的值,因此应该插入。我已更新了答案。请检查这是否适合您的需要。这些问题似乎适合我的需要。你能解释一下“计数(*)=3”(这3是从哪里来的)吗?因为我需要动态地构建这个查询。本例中有三个人。如果你想找两个或四个或其他什么,你必须调整这个数字。这些查询似乎适合我的需要。你能解释一下“计数(*)=3”(这3是从哪里来的)吗?因为我需要动态地构建这个查询。本例中有三个人。如果你想找两个或四个或其他什么,你必须调整这个数字。