我有一个MySQL函数,可以检索每个客户的库存.该函数运行得很好,但最近我需要向函数添加第三个参数.

My current working function:

CREATE FUNCTION getStock (productId INT, customerId INT) RETURNS INT(11)
BEGIN 
    DECLARE qty INT(11) DEFAULT 0;
    
    IF (customerId = 0)
        THEN
            SELECT (......) INTO qty 
            WHERE product_id = productId;
        ELSE
            SELECT (...) INTO QTY 
            WHERE product_id = productId AND customer_id = customerId;
    ENDIF;
    
    RETURN qty;
END;

问题是,现在我需要重构该查询并使用三个参数.我想申请一个更好的条件,比如:

CREATE FUNCTION getStock (productId INT, forceCustomerId INT, ignoreCustomerId INT) RETURNS INT(11)
BEGIN                 
    DECLARE qty INT(11) DEFAULT 0;
    DECLARE query VARCHAR(255);

    // Something like this
    SET query = SELECT (...) INTO qty
        WHERE product_id = productId;

    IF (forceCustomerId IS NOT NULL and forceCustomerId != 0)
        SET query &= AND customer_id = forceCustomerId;

    IF (ignoreCustomerId IS NOT NULL and ignoreCustomerId != 0)
        SET query &= AND customer_id != ignoreCustomerId;
        
    RETURN qty;
END;

我怎么才能做到这样的事情呢?

推荐答案

您必须使用PREPARE和EXECUTE在WHERE子句中使用可变数量的术语进行查询,但是...

https://dev.mysql.com/doc/mysql-reslimits-excerpt/en/stored-program-restrictions.html

SQL准备语句(PREPARE、EXECUTE、DEALLOCATE PREPARE)可以在存储过程中使用,但不能在存储函数或触发器中使用.因此,存储函数和触发器不能使用动态SQL(在动态SQL中,将语句构造为字符串,然后执行它们).

因此,您必须使用一个固定的查询来完成此操作.类似这样的东西(尽管我还没有测试过它):

CREATE FUNCTION getStock (productId INT, forceCustomerId INT,
    ignoreCustomerId INT) RETURNS INT(11)
BEGIN                 
    SELECT (...) INTO qty
    FROM ...
    WHERE product_id = productId
     AND (forceCustomerId IS NULL OR customer_id = forceCustomerId)
     AND (ignoreCustomerId IS NULL OR customerId != ignoreCustomerId);
        
    RETURN qty;
END;

Mysql相关问答推荐

LaravelEloquent ToSql()缺少连接表

如何防止程序中计数器出错

在MySQL中查找包含无效正则表达式的行

根据现有行 Select 月份日期

MySQL - 事务绑定多个存储过程调用和回滚的简单方法?

SQL查询以查找两个特定行的总和

如何在 axios 请求中将更新的设置状态值作为参数传递

提取 MySQL 5.7 连续值的差异

Golang Gorm:相同的查询构造不同,抛出不同的结果

MySQL如何通过外键ID Select 多行?

MySQL中两个时间字段的分钟差

MySQL:如何多次加入同一张表?

在 Android 上运行 AMP (apache mysql php)

MySQL触发器在某些条件下防止INSERT

MySQL Partitioning / Sharding / Splitting - 走哪条路?

WHERE 子句中的条件顺序会影响 MySQL 性能吗?

使用 PHP 和 MySQL 存储和显示 unicode 字符串 (हिन्दी)

MySQL 实用程序 - ~/.my.cnf 选项文件

使用 mysqldriver 连接数据库时出错

将数据库从 Postgres 迁移到 MySQL