使用Case在MYSQL中动态选择存储过程中的列

时间:2014-08-19 18:43:00

标签: mysql sql database stored-procedures

SQL Fiddle with the table schema

我正在关注this thread以创建用于动态选择列的存储过程。我想知道是否有任何解决方案可以在more条件中选择多个字段。在对列名称进行别名并在more条件中放置多个列时,我遇到语法错误,并且我已经读过我在MySQL中无法进行以下尝试。我想知道是否有任何有关

效果的工作声明
      CASE choose_field
           WHEN 'one' THEN COUNT(*) AS Count
           WHEN 'more' THEN n.id,pmu.name sender,pm.message, m.modify_id,ps.submit_id
      END

这是完整的命令,当每个条件中只指定了一个字段而不使用别名时,该命令有效:

DELIMITER//
CREATE PROCEDURE notification(IN choose_field varchar(4),IN user varchar(10))
BEGIN
    SELECT
      CASE choose_field
           WHEN 'one' THEN COUNT(*)
           WHEN 'more' THEN n.modification_id
      END
    FROM
      `notification` n
    LEFT JOIN user_modification m ON (n.modification_id = m.modification_id)
    LEFT JOIN pm ON (n.pm_id = pm.pm_id)
    LEFT JOIN users pmu ON (pm.recipent_id = pmu.user_id)
    LEFT JOIN users pmus ON (pm.sender_id = pmus.user_id)
    LEFT JOIN users pmm ON (m.user_id = pmm.user_id)
    WHERE
    (pmu.name = user OR 
     pmm.name = user) AND
    n.is_read = 0;
 END//

然后我用Call notification('one','Peter')

调用该程序

表架构

CREATE TABLE notification
    (`id` int, `modification_id` int,`pm_id` int,`is_read` int)
;

INSERT INTO notification
    (`id`,`modification_id`,`pm_id`,`is_read`)
VALUES
    (1,1,NULL,0),
    (2,NULL,1,0),
    (3,2,NULL,0)
;

CREATE TABLE user_modification
    (`modification_id` int, `user_id` int,`page_id` int, `is_approved` int)
;

INSERT INTO user_modification
    (`modification_id`,`user_id`,`page_id`,`is_approved`)
VALUES
    (1,1,5,1),
    (2,2,2,1),
    (3,3,3,0)

;

CREATE TABLE pm
    (`pm_id` int, `sender_id` int,`recipent_id` int,`msg` varchar(200))
;

INSERT INTO pm
    (`pm_id`,`sender_id`,`recipent_id`,`msg`)
VALUES
    (1,1,2,'Hello');

CREATE TABLE users
    (`user_id` int, `name`varchar(20))
;

INSERT INTO users
    (`user_id`,`name`)
VALUES
    (1,'Tom'),
    (2,'Peter'),
    (3,'David')
;

2 个答案:

答案 0 :(得分:1)

我认为你试图在一个声明中做的比你应该/想做的更多。几个解决方案:

  • 动态SQL可以处理这个...使用存储过程构建一个sql语句然后执行该变量。不确定我是否建议

  • 创建一个if语句,该语句读取变量并运行两个select语句中的一个,具体取决于它是什么

  • 创建2个额外的存储过程,一个用于计数,一个用于'更多'。使用主存储过程来评估法规(一个或多个)并运行正确的存储过程。

返回不同列数的一个语句有点困难。

答案 1 :(得分:1)

我会把它改成像这样的东西

DELIMITER//
CREATE PROCEDURE notification(IN choose_field varchar(4),IN user varchar(10))
BEGIN
    IF choose_field = 'one' THEN
        SELECT
            COUNT(*)
        FROM
          `notification` n
        LEFT JOIN user_modification m ON (n.modification_id = m.modification_id)
        LEFT JOIN pm ON (n.pm_id = pm.pm_id)
        LEFT JOIN users pmu ON (pm.recipent_id = pmu.user_id)
        LEFT JOIN users pmus ON (pm.sender_id = pmus.user_id)
        LEFT JOIN users pmm ON (m.user_id = pmm.user_id)
        WHERE
        (pmu.name = user OR 
         pmm.name = user) AND
        n.is_read = 0;
    ELSE -- # -- could also be -- ELSEIF choose_field = 'more'
        SELECT
            n.id,pmu.name sender,pm.message, m.modify_id,ps.submit_id
        FROM
          `notification` n
        LEFT JOIN user_modification m ON (n.modification_id = m.modification_id)
        LEFT JOIN pm ON (n.pm_id = pm.pm_id)
        LEFT JOIN users pmu ON (pm.recipent_id = pmu.user_id)
        LEFT JOIN users pmus ON (pm.sender_id = pmus.user_id)
        LEFT JOIN users pmm ON (m.user_id = pmm.user_id)
        WHERE
        (pmu.name = user OR 
         pmm.name = user) AND
        n.is_read = 0;
    END IF;

 END//

基本上只是使用你的存储过程中的if来检查你的查询并运行一个或另一个查询...你可以通过设置用户定义的变量等于你想要选择的部分和concat来做到这一点它也是一个查询。