我想创建一个具有多个输入可选参数的存储过程。如果至少给出了至少一个字段的参数,我仍然希望某些结果符合条件。
这是我的表定义:
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)为空。
我添加了一个SQL提琴here。
两个命令都需要一些结果:
CALL spInquiries('', '', '2018-07-01', '2018-07-31');
CALL spInquiries('2018-07-01', '2018-07-31', '', '');
我该如何实现?
答案 0 :(得分:1)
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 ;