存储过程中的准备语句不起作用
prepared statement inside stored procedure not working
我正在尝试在存储过程中执行准备好的语句。
但我遇到了问题。
存储过程如下:
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `getAllUserLunchReport`(IN `start_date` DATETIME, IN `end_date` DATETIME)
BEGIN
SET GLOBAL group_concat_max_len=4294967295;
SET @SQL = NULL;
SET @start_date = DATE(start_date);
SET @end_date = DATE(end_date);
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'SUM(CASE WHEN date = "',DATE(issuedDateTime),'" THEN lunchStatus ELSE 0 END) AS `',DATE(issuedDateTime),'`'
)
) INTO @SQL
FROM `lunch_status`
WHERE DATE(issuedDateTime) BETWEEN @start_date AND @end_date;
SET @SQL
= CONCAT('SELECT userId, ', @SQL, '
FROM
(
SELECT userId, lunchStatus, DATE(issuedDateTime) as date
FROM `lunch_status`
WHERE DATE(issuedDateTime) BETWEEN "',@start_date,'" AND "',@end_date,'"
) as a
GROUP BY userId;');
PREPARE stmt FROM @SQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$$
DELIMITER ;
这里是错误:
PDOStatement: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'NULL' at line 1
这是控制器:
public function weeklyLunchReport($date1=null, $date2=null)
{
$user = AclHelper::getCurrentUser();
$default_userID = intval($user['user_id']);
$defDate = new DateTime();
$default_date = $defDate->format('Y-m-d');
$date1 = (isset($date1) && $date1 != '') ? $date1 : $default_date;
$date2 = (isset($date2) && $date2 != '') ? $date2 : $default_date;
$records = $this->db->exec("CALL getAllUserLunchReport ('$date1','$date2')");
return $records;
}
还有:
这是 SQL 变量的值:
SELECT userId,
SUM(CASE WHEN date = "2018-06-03" THEN lunchStatus ELSE 0 END) AS `2018-06-03`,
SUM(CASE WHEN date = "2018-06-04" THEN lunchStatus ELSE 0 END) AS `2018-06-04`,
SUM(CASE WHEN date = "2018-06-06" THEN lunchStatus ELSE 0 END) AS `2018-06-06`,
SUM(CASE WHEN date = "2018-06-07" THEN lunchStatus ELSE 0 END) AS `2018-06-07`,
SUM(CASE WHEN date = "2018-06-08" THEN lunchStatus ELSE 0 END) AS `2018-06-08`
FROM
(
SELECT userId, lunchStatus, DATE(issuedDateTime) as date
FROM `lunch_status`
WHERE DATE(issuedDateTime) BETWEEN "2018-06-03" AND "2018-06-09"
) as a
GROUP BY userId;
运行 这个查询字符串分别给出了预期的结果集。
查询好像没问题,就是不知道哪里出错了
非常感谢任何帮助。提前致谢。
我在 mysql 客户端中尝试了您的程序,因此要排除问题与 PHP:
有关的任何可能性
mysql> create table lunch_status (userId int, lunchstatus int, issueddatetime datetime);
mysql> DELIMITER $$
mysql> CREATE DEFINER=`root`@`localhost` PROCEDURE `getAllUserLunchReport`(IN `start_date` DATETIME, IN `end_date` DATETIME)
-> BEGIN ...
mysql> CALL getAllUserLunchReport ('2018-06-17','2018-06-17');
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NULL' at line 1
mysql> select @SQL;
+------+
| @SQL |
+------+
| NULL |
+------+
但是当我尝试插入日期范围内的行时:
mysql> insert into lunch_status values (123, 1, now());
Query OK, 1 row affected (0.02 sec)
mysql> CALL getAllUserLunchReport ('2018-06-17','2018-06-17');
+--------+------------+
| userId | 2018-06-17 |
+--------+------------+
| 123 | 1 |
+--------+------------+
问题是当您要搜索的日期范围内没有行时,您的 GROUP_CONCAT()
会为数据透视表-table 列列表生成 NULL。
然后您将 NULL CONCAT() 到完整的 SELECT 语句中,但是 CONCAT('SELECT ...', NULL, 'FROM ...')
产生 NULL,因为将任何字符串与 NULL 连接会产生 NULL。
您需要确保您的 GROUP_CONCAT()
默认为一些非 NULL 字符串:
SELECT
COALESCE(GROUP_CONCAT(DISTINCT
CONCAT(
'SUM(CASE WHEN date = "',DATE(issuedDateTime),'" THEN lunchStatus ELSE 0 END) AS `',DATE(issuedDateTime),'`'
)
), '0 as `NoMatchingRows`') INTO @SQL
调用该过程仍然return 没有结果集,因为 table 中没有与您提供的日期范围匹配的日期。但至少当你尝试准备 NULL 时它不会出现语法错误。
我正在尝试在存储过程中执行准备好的语句。
但我遇到了问题。
存储过程如下:
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `getAllUserLunchReport`(IN `start_date` DATETIME, IN `end_date` DATETIME)
BEGIN
SET GLOBAL group_concat_max_len=4294967295;
SET @SQL = NULL;
SET @start_date = DATE(start_date);
SET @end_date = DATE(end_date);
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'SUM(CASE WHEN date = "',DATE(issuedDateTime),'" THEN lunchStatus ELSE 0 END) AS `',DATE(issuedDateTime),'`'
)
) INTO @SQL
FROM `lunch_status`
WHERE DATE(issuedDateTime) BETWEEN @start_date AND @end_date;
SET @SQL
= CONCAT('SELECT userId, ', @SQL, '
FROM
(
SELECT userId, lunchStatus, DATE(issuedDateTime) as date
FROM `lunch_status`
WHERE DATE(issuedDateTime) BETWEEN "',@start_date,'" AND "',@end_date,'"
) as a
GROUP BY userId;');
PREPARE stmt FROM @SQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$$
DELIMITER ;
这里是错误:
PDOStatement: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'NULL' at line 1
这是控制器:
public function weeklyLunchReport($date1=null, $date2=null)
{
$user = AclHelper::getCurrentUser();
$default_userID = intval($user['user_id']);
$defDate = new DateTime();
$default_date = $defDate->format('Y-m-d');
$date1 = (isset($date1) && $date1 != '') ? $date1 : $default_date;
$date2 = (isset($date2) && $date2 != '') ? $date2 : $default_date;
$records = $this->db->exec("CALL getAllUserLunchReport ('$date1','$date2')");
return $records;
}
还有: 这是 SQL 变量的值:
SELECT userId,
SUM(CASE WHEN date = "2018-06-03" THEN lunchStatus ELSE 0 END) AS `2018-06-03`,
SUM(CASE WHEN date = "2018-06-04" THEN lunchStatus ELSE 0 END) AS `2018-06-04`,
SUM(CASE WHEN date = "2018-06-06" THEN lunchStatus ELSE 0 END) AS `2018-06-06`,
SUM(CASE WHEN date = "2018-06-07" THEN lunchStatus ELSE 0 END) AS `2018-06-07`,
SUM(CASE WHEN date = "2018-06-08" THEN lunchStatus ELSE 0 END) AS `2018-06-08`
FROM
(
SELECT userId, lunchStatus, DATE(issuedDateTime) as date
FROM `lunch_status`
WHERE DATE(issuedDateTime) BETWEEN "2018-06-03" AND "2018-06-09"
) as a
GROUP BY userId;
运行 这个查询字符串分别给出了预期的结果集。
查询好像没问题,就是不知道哪里出错了
非常感谢任何帮助。提前致谢。
我在 mysql 客户端中尝试了您的程序,因此要排除问题与 PHP:
有关的任何可能性mysql> create table lunch_status (userId int, lunchstatus int, issueddatetime datetime);
mysql> DELIMITER $$
mysql> CREATE DEFINER=`root`@`localhost` PROCEDURE `getAllUserLunchReport`(IN `start_date` DATETIME, IN `end_date` DATETIME)
-> BEGIN ...
mysql> CALL getAllUserLunchReport ('2018-06-17','2018-06-17');
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NULL' at line 1
mysql> select @SQL;
+------+
| @SQL |
+------+
| NULL |
+------+
但是当我尝试插入日期范围内的行时:
mysql> insert into lunch_status values (123, 1, now());
Query OK, 1 row affected (0.02 sec)
mysql> CALL getAllUserLunchReport ('2018-06-17','2018-06-17');
+--------+------------+
| userId | 2018-06-17 |
+--------+------------+
| 123 | 1 |
+--------+------------+
问题是当您要搜索的日期范围内没有行时,您的 GROUP_CONCAT()
会为数据透视表-table 列列表生成 NULL。
然后您将 NULL CONCAT() 到完整的 SELECT 语句中,但是 CONCAT('SELECT ...', NULL, 'FROM ...')
产生 NULL,因为将任何字符串与 NULL 连接会产生 NULL。
您需要确保您的 GROUP_CONCAT()
默认为一些非 NULL 字符串:
SELECT
COALESCE(GROUP_CONCAT(DISTINCT
CONCAT(
'SUM(CASE WHEN date = "',DATE(issuedDateTime),'" THEN lunchStatus ELSE 0 END) AS `',DATE(issuedDateTime),'`'
)
), '0 as `NoMatchingRows`') INTO @SQL
调用该过程仍然return 没有结果集,因为 table 中没有与您提供的日期范围匹配的日期。但至少当你尝试准备 NULL 时它不会出现语法错误。