【问题标题】:MySQL: Making stored procedure multiple parameters optionalMySQL:使存储过程多个参数可选
【发布时间】:2018-07-17 12:08:10
【问题描述】:

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

这是我的表定义:

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 fiddle here

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

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

我怎样才能做到这一点?

【问题讨论】:

    标签: mysql stored-procedures


    【解决方案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 ;
    

    【讨论】:

    • @Ivan 它有效,但我想添加另一个参数 IN pInquiryId varchar(30) 并像这样添加。 SELECT * FROM tblinquiries WHERE (ReviewDate BETWEEN pReviewStartDate AND pReviewEndDate) AND (DATE(EndTime) BETWEEN pAuditStartDate AND pAuditEndDate) AND (pInquiryId IS NULL OR InquiryId = pInquiryId); 它给出命令 CALL spInquiries 的错误('2018-07-01', '2018-07-31', '', '', '');怎么了?
    • 那么,当 pInquiryId = '' 时,是否要选择所有 InquiryId = NULL 的记录?
    • 是的,这正是我想要的。我该怎么做?
    • 我对存储过程添加了一些更改,在这种情况下,NULL 比较并不简单。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多