是否需要使用游标来实现以下查询?

时间:2014-05-14 03:13:24

标签: mysql database cursor

考虑数据库:

  • 公司拥有零个或多个分公司
  • 公司有零个或多个电子邮件
  • 分支机构有零个或多个电子邮件

并考虑该数据库的以下实例:

  • 1公司有2个分支
  • 公司有1封电子邮件
  • 每个分支都有2封电子邮件

(总共5封电子邮件)

如果您愿意,请检查该实例的graphical representation


查询

我想查询(MySQL),检索与给定公司相关的所有电子邮件(在示例中为5)。我无法找到解决方案,所以经过一番谷歌搜索后我发现有一个名为cursor的东西。


问题

  • 是否需要使用游标来实现上述查询?这是一个很好的解决方案吗?您对上述查询的解决方案是什么?

(表格定义如下)


我的想法是检索给定公司的所有分支(我可以提出的查询),但从那里我不知道如何通过分支迭代(查询结果)并获得所有的电子邮件。


MySQL中的表定义

-- Database tables
CREATE TABLE `company` (

        `c_id`          INT(11) NOT NULL AUTO_INCREMENT,
        `c_name`        VARCHAR(45) NOT NULL,

        PRIMARY KEY (`c_name`),
        UNIQUE KEY `c_id` (`c_id`)

) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8


CREATE TABLE `branch` (

        `b_id`          INT(11) NOT NULL AUTO_INCREMENT,
        `c_id`          INT(11) NOT NULL,
        `b_name` VARCHAR(45) NOT NULL,

        PRIMARY KEY (`b_name`),
        UNIQUE KEY `b_id` (`b_id`),
        KEY `c_id` (`c_id`),

        CONSTRAINT `branch_ibfk_1` FOREIGN KEY (`c_id`)
                REFERENCES `company` (`c_id`)
                ON DELETE CASCADE
                ON UPDATE CASCADE

) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8


CREATE TABLE `email` (

        `e_id`          INT(11) NOT NULL AUTO_INCREMENT,
        `e_addr`        VARCHAR(45) NOT NULL,

        PRIMARY KEY (`e_addr`),
        UNIQUE KEY `e_id` (`e_id`)

) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8


CREATE TABLE `c_email` (

        `c_id`          INT(11) NOT NULL,
        `e_id`          INT(11) NOT NULL,

        PRIMARY KEY (`c_id`,`e_id`),
        KEY `e_id` (`e_id`),

        CONSTRAINT `c_email_ibfk_1` FOREIGN KEY (`c_id`)
                REFERENCES `company` (`c_id`)
                ON DELETE CASCADE
                ON UPDATE CASCADE,

        CONSTRAINT `c_email_ibfk_2` FOREIGN KEY (`e_id`)
                REFERENCES `email` (`e_id`)
                ON DELETE CASCADE
                ON UPDATE CASCADE

) ENGINE=InnoDB DEFAULT CHARSET=utf8


CREATE TABLE `b_email` (

        `b_id`          INT(11) NOT NULL,
        `e_id`          INT(11) NOT NULL,

        PRIMARY KEY (`b_id`,`e_id`),
        KEY `e_id` (`e_id`),

        CONSTRAINT `b_email_ibfk_1` FOREIGN KEY (`b_id`)
                REFERENCES `branch` (`b_id`)
                ON DELETE CASCADE
                ON UPDATE CASCADE,

        CONSTRAINT `b_email_ibfk_2` FOREIGN KEY (`e_id`)
                REFERENCES `email` (`e_id`)    
                ON DELETE CASCADE
                ON UPDATE CASCADE

) ENGINE=InnoDB DEFAULT CHARSET=utf8


-- Example of query
-- Retrieving all e-mails of a given branch
SELECT e_addr
        FROM email      AS _em
        JOIN b_email    AS _be ON _be.e_id = _em.e_id
        JOIN branch     AS _br ON _br.b_id = _be.b_id
        WHERE b_name = @bra2;

-- How to retrieve all e-mails related to a given company
-- (e-mails from the company itself and also from all of its branches)?
-- ?

1 个答案:

答案 0 :(得分:2)

不,你不需要光标。你可以用SQL做到这一点 - 比光标好得多。它类似于:

select *
from ((select ce.c_id, e.email
       from c_email ce join
            email e
            on e.e_id = ce.e_id
      ) union all
      (select b.c_id, e.email
       from branch b join
            b_email be
            on b.b_id = be.b_id join
            email e
            on be.e_id = e.e_id
      )
     ) e
where ce.c_id = X;

编辑:

您可以将b_id添加到第二个子查询中,但不能添加到第一个子查询中。也许你可以做到:

select *
from ((select ce.c_id, e.email, NULL as b_id
       from c_email ce join
            email e
            on e.e_id = ce.e_id
      ) union all
      (select b.c_id, e.email, b.b_id
       from branch b join
            b_email be
            on b.b_id = be.b_id join
            email e
            on be.e_id = e.e_id
      )
     ) e
where ce.c_id = X
order by c_id, b_id;