MySQL:使存储过程多个参数可选

标签 mysql stored-procedures

我想创建一个具有多个输入可选参数的存储过程。如果至少给出了其中一个字段的参数,我仍然希望得到一些符合条件的结果。

这是我的表定义:

CREATE TABLE `tblinquiries` (
  `UID` varchar(50) DEFAULT NULL,
  `ReviewDate` date NOT NULL,
  `InquiryId` varchar(50) NOT NULL,
  `AuditStatus` varchar(50) DEFAULT NULL,
  `AssignedTo` varchar(50) DEFAULT NULL,
  `Result` int(2) DEFAULT NULL,
  `ResultCategories` int(2) DEFAULT NULL,
  `AuditBy` varchar(50) DEFAULT NULL,
  `Remarks` varchar(200) DEFAULT NULL,
  `StartTime` datetime DEFAULT NULL,
  `EndTime` datetime DEFAULT NULL,
   PRIMARY KEY (InquiryId)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

这是一个示例数据集:

INSERT INTO `tblinquiries` (`UID`, `ReviewDate`, `InquiryId`, `AuditStatus`, `AssignedTo`, `Result`, `ResultCategories`, `AuditBy`, `Remarks`, `StartTime`, `EndTime`) VALUES
('user1', '2018-07-07', '109933881', 'Assigned', 'auditor1', NULL, NULL, NULL, NULL, '2018-07-15 08:03:47', NULL),
('user2', '2018-07-07', '109933885', 'Assigned', 'auditor2', NULL, NULL, NULL, NULL, '2018-07-15 08:04:13', NULL),
('user3', '2018-07-07', '109933909', 'Complete', 'auditor3', 1, auditor3, NULL, NULL, '2018-07-15 08:06:42', '2018-07-15 08:10:42'),
('user4', '2018-07-08', '109933916', 'Check', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
('user5', '2018-07-08', '109933917', 'Check', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
('user6', '2018-07-08', '8790804', 'Complete', 'auditor1', 1, NULL, 'auditor1', NULL, '2018-07-14 21:19:25', '2018-07-14 21:21:29');

这是我的存储过程:

DROP procedure IF EXISTS `spInquiries`;

DELIMITER $$
CREATE PROCEDURE `spInquiries` (IN `pReviewStartDate` DATE, IN `pReviewEndDate` DATE, IN `pAuditStartDate` DATE, IN `pAuditEndDate` DATE)
BEGIN
SELECT * FROM tblinquiries
  WHERE
  (ReviewDate BETWEEN pReviewStartDate AND pReviewEndDate)
  AND (DATE(EndTime) BETWEEN pAuditStartDate AND pAuditEndDate);
END$$

DELIMITER ;

经过大量研究,我发现this stackoverflow question这有一些相似之处。但我不知道如何使 WHERE 子句的 2 个参数(例如 - pAuditStartDate、pAuditEndDate)为 null。

我添加了一个 SQL fiddle here .

我想要这两个命令的一些结果:

CALL spInquiries('', '', '2018-07-01', '2018-07-31');
CALL spInquiries('2018-07-01', '2018-07-31', '', '');

我怎样才能实现这一目标?

最佳答案

MySQL 自动从字符串转换为 date 类型,因此您可以使用字符串而不是 date 参数。顺便说一句,空日期 ('') 作为 MySQL 日期值无效。

之后您可以更改该值,如果比较是从较低日期开始,则使用 '1900-01-01' 作为默认值,使用 now() 作为较高范围.

DELIMITER $$
drop procedure if exists `spInquiries`$$
CREATE PROCEDURE `spInquiries` (IN `pReviewStartDate` varchar(30), IN `pReviewEndDate` varchar(30),
                              IN `pAuditStartDate` varchar(30), IN `pAuditEndDate` varchar(30))
BEGIN

  -- sanitize the date ranges
  if pReviewStartDate = '' then 
    set pReviewStartDate = '1900-01-01';
  end if;
  if pAuditStartDate = '' then 
    set pAuditStartDate = '1900-01-01';
  end if;

  if pReviewEndDate = '' then 
    set pReviewEndDate = now();
  end if;

  if pAuditEndDate = '' then 
    set pAuditEndDate = now();
  end if;

  -- now you can run the query without problems

  SELECT * FROM tblinquiries
   WHERE
    (ReviewDate BETWEEN pReviewStartDate AND pReviewEndDate)
     AND (DATE(EndTime) BETWEEN pAuditStartDate AND pAuditEndDate);
END$$

结果:

mysql> CALL spInquiries('', '', '2018-07-01', '2018-07-31');
+-------+------------+-----------+-------------+------------+--------+------------------+----------+---------+---------------------+---------------------+
| UID   | ReviewDate | InquiryId | AuditStatus | AssignedTo | Result | ResultCategories | AuditBy  | Remarks | StartTime           | EndTime             |
+-------+------------+-----------+-------------+------------+--------+------------------+----------+---------+---------------------+---------------------+
| user3 | 2018-07-07 | 109933909 | Complete    | auditor3   |      1 |                0 | NULL     | NULL    | 2018-07-15 08:06:42 | 2018-07-15 08:10:42 |
| user6 | 2018-07-08 | 8790804   | Complete    | auditor1   |      1 |             NULL | auditor1 | NULL    | 2018-07-14 21:19:25 | 2018-07-14 21:21:29 |
+-------+------------+-----------+-------------+------------+--------+------------------+----------+---------+---------------------+---------------------+


mysql> CALL spInquiries('2018-07-01', '2018-07-31', '', '');
+-------+------------+-----------+-------------+------------+--------+------------------+----------+---------+---------------------+---------------------+
| UID   | ReviewDate | InquiryId | AuditStatus | AssignedTo | Result | ResultCategories | AuditBy  | Remarks | StartTime           | EndTime             |
+-------+------------+-----------+-------------+------------+--------+------------------+----------+---------+---------------------+---------------------+
| user3 | 2018-07-07 | 109933909 | Complete    | auditor3   |      1 |                0 | NULL     | NULL    | 2018-07-15 08:06:42 | 2018-07-15 08:10:42 |
| user6 | 2018-07-08 | 8790804   | Complete    | auditor1   |      1 |             NULL | auditor1 | NULL    | 2018-07-14 21:19:25 | 2018-07-14 21:21:29 |
+-------+------------+-----------+-------------+------------+--------+------------------+----------+---------+---------------------+---------------------+

更新:

我更改存储过程以满足新参数

DELIMITER $$
drop procedure if exists `spInquiries`$$
CREATE PROCEDURE `spInquiries` (IN `pReviewStartDate` varchar(30), IN `pReviewEndDate` varchar(30),
                                IN `pAuditStartDate` varchar(30), IN `pAuditEndDate` varchar(30), 
                                pInquiryId VARCHAR(30))
BEGIN

  if pReviewStartDate = '' then 
    set @pReviewStartDate = '1900-01-01';
  else
    set @pReviewStartDate = pReviewStartDate;
  end if;
  if pAuditStartDate = '' then 
    set @pAuditStartDate = '1900-01-01';
  else
    set @pAuditStartDate = pAuditStartDate;
  end if;

  if pReviewEndDate = '' then 
    set @pReviewEndDate = now();
  else
    set @pReviewEndDate = pReviewEndDate;
  end if;

  if pAuditEndDate = '' then 
    set @pAuditEndDate = now();
  else
    set @pAuditEndDate = pAuditEndDate;
  end if;

  set @sql = 'SELECT * FROM tblinquiries WHERE 
            (ReviewDate BETWEEN ? AND ?)
             AND (DATE(EndTime) BETWEEN ? AND ?) ';

  if pInquiryId = '' then
    set @sql = concat(@sql,"AND InquiryId IS NULL");
  else
    set @sql = concat(@sql,"AND InquiryId =  '", pInquiryId,"'");
  end if; 

  PREPARE myquery FROM @sql;
  EXECUTE myquery using @pReviewStartDate,@pReviewEndDate,@pAuditStartDate,@pAuditEndDate;

END$$

DELIMITER ;

关于MySQL:使存储过程多个参数可选,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51381003/

相关文章:

MySql SP 不工作

MySQL - 杀死所有 sleep 连接

MySQL 和 PostgreSQL 引用字段名称之间的 PHP PDO 兼容性

mysql - iReport中的员工考勤日历报表设计

mysql - 如何使用 date > NOW() ASC 和其余 DESC 对 SQL 结果进行排序?

oracle - ROWID 作为 PL/SQL 中的参数

tsql - 经典 ASP - 如何获取所有 T-SQL 存储过程行集

sql-server - 顺序执行 SQL Server 存储过程

mysql - 使用 SQL 基于当前行值对数据子集进行聚合函数

php - Codeigniter:获取页面上的所有查询