存储过程中的 CTE 问题

问题描述 投票:0回答:1

我有一个这样的存储过程。

DROP PROCEDURE IF EXISTS get_leave_deduction;
DELIMITER $$
CREATE PROCEDURE get_leave_deduction(
    IN emp_ID VARCHAR(255),
    IN month_ INT,
    IN year_ YEAR
)

BEGIN
DECLARE last_date DATE;
SET last_date = LAST_DAY(DATE(CONCAT_WS('-', year_, month_, 1)));

WITH tmp_table AS (

    SELECT *
    CASE
        WHEN tl.end_date > last_date THEN datediff(last_date, tl.start_date)
        ELSE datediff(tl.end_date, tl.start_date)
    END AS 'num_days'
    FROM takes_leave AS tl
    WHERE tl.emp_ID = emp_ID and month(tl.start_date)<=month_ and year(tl.start_date)=year_;
    )
    
    SELECT * FROM tmp_table;
END$$
DELIMITER ;

CALL get_leave_deduction("8", 11, 2023)

当我尝试运行 MYSQL Workbench 时,出现以下错误:您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,了解在 'CASE 附近使用的正确语法 当 tl.end_date > last_date 那么 datediff(last_date, tl.start_date)

当我在 tmp_table CTE 中注释 WHERE 和 CASE 语句时,Workbench 不会显示此错误。所以我猜测该错误与无法在 CTE 内使用输入参数有关。 我想在存储过程中使用此 CTE 的内容来创建另一个查询。

mysql mysql-workbench
1个回答
1
投票
WITH tmp_table AS (

SELECT *
        ^^ you need a comma between items in the select-list
CASE
    WHEN tl.end_date > last_date THEN datediff(last_date, tl.start_date)
    ELSE datediff(tl.end_date, tl.start_date)
END AS 'num_days'
FROM takes_leave AS tl
WHERE tl.emp_ID = emp_ID 
    and month(tl.start_date)<=month_ 
    and year(tl.start_date)=year_;
                                 ^^ do not use a semicolon 
                                    inside subquery or CTE
)

SELECT * FROM tmp_table;

另外,不要将过程参数命名为与表中的列名称相同。当您在查询中使用过程变量时,您指的是变量还是列会变得不明确。在本例中,

emp_ID
是同一个名称。使用限定标识符可能有助于解决歧义,但如果您确保变量名称与列名称不同,您的代码将更加清晰且更易于调试。

不要依赖 MySQL Workbench 的语法提示。如果您对语法有疑问,请学习阅读参考文档。

© www.soinside.com 2019 - 2024. All rights reserved.