【问题标题】:Can I reuse a where clause with many conditions in MySQL?我可以在 MySQL 中重用具有许多条件的 where 子句吗?
【发布时间】:2019-10-24 21:32:04
【问题描述】:

我正在将许多 MySQL 查询从 Node.js 应用程序中的硬编码迁移到存储过程(用于 Java 应用程序)。在最初的 Node 应用程序中,有一个 SQL 条件保存为常量字符串,该字符串作为 where 子句的一部分替换到许多不同的 SQL 函数中,我不知道如何使用 MySQL 存储函数来完成同样的事情。

该常量是一个 SQL 字符串,用于检查用户对象的各种属性是否为空:

const USER_INFO_NOT_NULL = `u.id IS NOT NULL \
  AND u.email IS NOT NULL \
  AND u.gender IS NOT NULL \
  AND u.date_of_birth IS NOT NULL \
  AND u.first_name IS NOT NULL \
  AND u.last_name IS NOT NULL`

此 SQL 语句被替换为许多不同的查询,作为其WHERE 语句中的条件之一。

例如:

SELECT COUNT(*) count
    FROM User u
    WHERE ${USER_INFO_NOT_NULL} 
        AND some_other_condition
        AND another_condition
...

不幸的是,并不是所有的查询都像上面的那样简单,要重写每一个都需要大量的工作。

我尝试过使用存储函数,但是,存储函数只能将标量值作为参数,因此我无法传递用户行。

我还尝试让函数获取用户 ID(不理想,因为查询已经查询了用户),查询该用户并根据上述条件返回一个布尔值。但是,我不确定如何在存储函数中将 SELECTRETURN 结合起来(你可以这样做吗?)。

我研究了准备好的语句,但是,它们似乎不能以这种方式工作,因为它们只支持有限数量的 SQL 命令。

那么,有没有办法只使用 MySQL 功能来做类似于 Node.js 应用程序中已有的事情?

【问题讨论】:

    标签: mysql


    【解决方案1】:

    你可以定义一个视图。

    CREATE VIEW user_info_not_null 
    SELECT *
    FROM User u
    WHERE u.id IS NOT NULL 
      AND u.email IS NOT NULL 
      AND u.gender IS NOT NULL 
      AND u.date_of_birth IS NOT NULL 
      AND u.first_name IS NOT NULL 
      AND u.last_name IS NOT NULL;
    

    然后你可以像使用表格一样使用视图:

    SELECT COUNT(*) count
    FROM user_info_not_null
    WHERE some_other_condition
    AND another_condition
    

    在存储过程中,您应该能够使用准备好的语句来执行此操作。

    SET user_info_not_null = 'u.id IS NOT NULL 
      AND u.email IS NOT NULL 
      AND u.gender IS NOT NULL 
      AND u.date_of_birth IS NOT NULL 
      AND u.first_name IS NOT NULL 
      AND u.last_name IS NOT NULL';
    SET @sql = CONCAT('SELECT COUNT(*) count
        FROM User u
        WHERE ', user_info_not_null, '
            AND some_other_condition
            AND another_condition');
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
    

    您也可以将WHERE 子句替换为模板:

    set template_sql = 'SELECT COUNT(*) count
        FROM User u
        WHERE ${user_info_not_null}
            AND some_other_condition
            AND another_condition';
    set @sql = REPLACE(template_sql, '${user_info_not_null}', user_info_not_null);
    

    【讨论】:

    • 这可行,但需要对每个查询进行大量重写才能使用视图。例如,一个特别长的查询具有该单个 WHERE 子句的三个实例以及多个嵌套的 SELECT 语句。同样,我想避免重写一堆查询...优化不在此任务的范围内。
    • 你谈到了使用存储函数,那不就是重写吗?
    • 不,我只是将现有的硬编码 SQL 查询复制/粘贴到用于创建存储过程的模板中。问题是某些查询使用 JS 字符串替换来构造具有多个条件的复杂 where 子句。如果可能的话,我希望能够重用 where 子句条件,这样我就不必自己将字符串复制/粘贴到每个查询中,这将使它成为一场噩梦。
    • 这两种方法似乎都可行。是否可以将user_info_not_null 设置为用户定义的变量,以便我可以从多个查询中访问它?此外,将这些方法中的任何一种与准备好的程序一起使用会导致问题吗?
    • 顺便说一句,您可能应该在常见的 where 子句周围加上括号,以避免与 OR 条件混合时出现问题。
    猜你喜欢
    • 2012-03-01
    • 2013-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-10
    • 1970-01-01
    • 2017-07-18
    • 2017-05-07
    相关资源
    最近更新 更多