简体   繁体   English

在MySQL中使用Date参数在存储过程中进行动态查询

[英]Dynamic query in stored procedure with a Date parameter in MySQL

I am writing a stored procedure in MySQL with a dynamic query as shown below: 我正在用动态查询在MySQL中编写存储过程,如下所示:

DROP PROCEDURE IF EXISTS test;
DELIMITER //
CREATE PROCEDURE test(
IN STATUS VARCHAR(20),
IN CREATED_ON1 VARCHAR(10)
) 
BEGIN

SET @query="SELECT STATUS, COUNT(*) FROM CONTROL WHERE ID=ID";

IF STATUS IS NOT NULL THEN
 SET @query=CONCAT(@query, " AND STATUS='",STATUS,"'");
END IF;

IF CREATED_ON1 IS NOT NULL THEN
 SET @query=CONCAT(@query, " AND DATE_FORMAT(CREATED_ON,'%d-%m-%Y')>='", 
CREATED_ON1, "'");
END IF;

SET @query=CONCAT(@query, " GROUP BY STATUS");

PREPARE stmt FROM @query;
EXECUTE stmt; 
DEALLOCATE PREPARE stmt;

END //
DELIMITER ;

I intend to rewrite this procedure with the signature shown below. 我打算用下面显示的签名重写此过程。 This will provide the right logic in comparing the dates. 这将提供比较日期的正确逻辑。

DROP PROCEDURE IF EXISTS test;
DELIMITER //
CREATE PROCEDURE test(
IN STATUS VARCHAR(20),
IN CREATED_ON1 DATE
)

The main question is; 主要问题是; how do I concatenate the predicate with date to the @query? 如何将带日期的谓词连接到@query?

Try using a CASE and pass the parameters: 尝试使用CASE并传递参数:

DROP PROCEDURE IF EXISTS test;
DELIMITER //
CREATE PROCEDURE test(
IN IN_STATUS VARCHAR(20),
IN IN_CREATED_ON1 DATE
)

BEGIN
SET @v_and    = ' AND ';
SET @v_where  = ' WHERE ';
SET @v_query  = 'SELECT STATUS, COUNT(*) FROM CONTROL';
SET @v_status = ' STATUS=? ';
SET @v_date   = ' CREATED_ON >= ? ';
SET @v_group  = ' GROUP BY STATUS';

CASE 

WHEN IN_STATUS IS NOT NULL && IN_CREATED_ON1 IS NOT NULL THEN
    SET @v_query = CONCAT(@v_query,@v_where,@v_status,@v_and,@v_date,@v_group);
    PREPARE stmt FROM @v_query;
    EXECUTE stmt USING @IN_STATUS, @IN_CREATED_ON1; 
WHEN IN_STATUS IS NOT NULL THEN
    SET @v_query = CONCAT(@v_query,@v_where,@v_status,@v_group);
    PREPARE stmt FROM @v_query;
    EXECUTE stmt USING @IN_STATUS; 
WHEN IN_CREATED_ON1 IS NOT NULL THEN
    SET @v_query = CONCAT(@v_query,@v_where,@v_date,@v_group);
    PREPARE stmt FROM @v_query;
    EXECUTE stmt USING @IN_CREATED_ON1; 
ELSE
    SET @v_query = CONCAT (@v_query,@v_group);
    PREPARE stmt FROM @v_query;
    EXECUTE stmt; 
END CASE;

DEALLOCATE PREPARE stmt;
END//

DELIMITER ;

Note that you do not have to use dynamic SQL. 请注意,您不必使用动态SQL。 Using normal stored procedure would make your code much more readable and easier to maintain: 使用普通的存储过程将使您的代码更具可读性,并且更易于维护:

CREATE PROCEDURE test(
IN_STATUS VARCHAR(20),
IN_CREATED_ON DATE
) 
BEGIN

SELECT STATUS, COUNT(*) 
FROM CONTROL 
WHERE STATUS=IFNULL(IN_STATUS, STATUS) AND CREATED_ON>=IFNULL(IN_CREATED_ON,CREATED_ON)
GROUP BY STATUS;

END

Assuming your STATUS and CREATED_ON would always contain value. 假设您的STATUS和CREATED_ON将始终包含值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM