MySQL 中带有 Date 参数的存储过程中的动态查询
Dynamic query in stored procedure with a Date parameter in MySQL
我正在 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 ;
我打算用下面所示的签名重写这个程序。这将提供比较日期的正确逻辑。
DROP PROCEDURE IF EXISTS test;
DELIMITER //
CREATE PROCEDURE test(
IN STATUS VARCHAR(20),
IN CREATED_ON1 DATE
)
主要问题是;如何将带有日期的谓词连接到 @query?
尝试使用 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 ;
请注意,您不必使用动态 SQL。使用普通存储过程将使您的代码更具可读性和更易于维护:
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
假设您的 STATUS 和 CREATED_ON 将始终包含值。
我正在 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 ;
我打算用下面所示的签名重写这个程序。这将提供比较日期的正确逻辑。
DROP PROCEDURE IF EXISTS test;
DELIMITER //
CREATE PROCEDURE test(
IN STATUS VARCHAR(20),
IN CREATED_ON1 DATE
)
主要问题是;如何将带有日期的谓词连接到 @query?
尝试使用 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 ;
请注意,您不必使用动态 SQL。使用普通存储过程将使您的代码更具可读性和更易于维护:
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
假设您的 STATUS 和 CREATED_ON 将始终包含值。