这是一个名为code
的表。
p_code
列是父代码
存储过程应该返回一组由p_code
组合的记录;
除了第一次之外,程序运行良好(在重新连接MYSQL之后,它返回null!)。怎么了?
这是存储过程。
BEGIN
DECLARE _CODE bigint(20);
DECLARE _P_CODE bigint(20);
DECLARE _SORT bigint(20);
DECLARE _pre_P_CODE bigint(20);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET @CODE = NULL;
SET _P_CODE = @CODE;
SET _CODE = '';
SET _SORT = 0;
SET _pre_P_CODE = '';
IF @CODE IS NULL THEN
RETURN NULL;
END IF;
LOOP
SELECT CODE, P_CODE, SORT, CODE_NAME, CODE_LEVEL
INTO @CODE, @P_CODE, @SORT, @CODE_NAME, @CODE_LEVEL
FROM CODE
WHERE LANGUAGE = @LANGUAGE
AND P_CODE = _P_CODE
AND SORT > _SORT
ORDER BY SORT limit 1;
IF @CODE IS NOT NULL OR _P_CODE = @start_with THEN
SET @level = @level + 1;
RETURN @CODE;
END IF;
SET @level := @level - 1;
SELECT CODE, P_CODE, SORT
INTO _CODE, _P_CODE, _SORT
FROM CODE
WHERE CODE = _P_CODE;
END LOOP;
END
这个程序就像这样。这个SQL将返回上面的第二张图片。
SELECT
menu_connect_by_p_code() AS CODE,
@level as level,
@P_CODE as p_code,
@SORT as sort,
@CODE_NAME as CODE_NAME,
@CODE_LEVEL as CODE_LEVEL
FROM (
SELECT
@start_with := 6001,@LANGUAGE := 'en' ,
@CODE := @start_with,
@level := 0
) vars, code
WHERE @CODE IS NOT NULL
我不明白为什么第一次返回null 。 MYSQL的程序或错误有什么问题吗?
------------------------------- edit --------------- ---------------------
RolandoMySQLDBA,rsanchez,我尝试了你的选择,但保持不变。它返回多行,有些列为空。
------------------------------- edit2 --------------- ---------------------
您可以在此处看到:http://sqlfiddle.com/#!2/aa033/1
答案 0 :(得分:2)
作为一般规则,您不应该为用户变量赋值并在同一语句中读取值。您可能会得到您期望的结果,但这不能保证。涉及用户变量的表达式的评估顺序是未定义的,可能会根据给定语句中包含的元素进行更改;此外,MySQL服务器版本之间的订单不保证相同。
因此您可能想要更改:
SELECT
@start_with := 6001,@LANGUAGE := 'en' ,
@CODE := @start_with,
@level := 0
由:
SELECT
@start_with := 6001,@LANGUAGE := 'en' ,
@CODE := 6001,
@level := 0
答案 1 :(得分:2)
我看到了进步的自然顺序
这是您的查询
SELECT
menu_connect_by_p_code() AS CODE,
@level as level,
@P_CODE as p_code,
@SORT as sort,
@CODE_NAME as CODE_NAME,
@CODE_LEVEL as CODE_LEVEL
FROM (
SELECT
@start_with := 6001,@LANGUAGE := 'en' ,
@CODE := @start_with,
@level := 0
) vars, code
WHERE @CODE IS NOT NULL
@CODE很早就是NULL的唯一方法是在调用内部SELECT查询之前首先评估存储过程。
也许您可以重新排列变量初始化的顺序
SET @start_with := 6001;
SET @LANGUAGE := 'en';
SET @CODE := @start_with;
SET @level := 0;
SELECT
menu_connect_by_p_code() AS CODE,
@level as level,
@P_CODE as p_code,
@SORT as sort,
@CODE_NAME as CODE_NAME,
@CODE_LEVEL as CODE_LEVEL
FROM code
WHERE @CODE IS NOT NULL;
试一试!!!
问题在于存储过程的这一部分:
IF @CODE IS NULL THEN
RETURN NULL;
END IF;
尝试评论这些行,看看会发生什么!!!
答案 2 :(得分:1)
首先,这不是一个程序。
嗯我尝试了小提琴 - 它似乎在每次交替执行时都为空。
@CODE为NULL,因此在函数调用后发生赋值时,输出为null。这可能是正在发生的事情。
如果罗兰多的方式不起作用那么你就可以做到这一点。那么这将为你的执行增加一些时间,实际上更像是一个黑客。这应该工作,因为现在@Code不能转为null
SELECT * FROM
(SELECT
menu_connect_by_p_code() AS CODE,
@level as level,
@P_CODE as p_code,
@SORT as sort,
@CODE_NAME as CODE_NAME,
@CODE_LEVEL as CODE_LEVEL
FROM (
SELECT
@start_with := 6001,
@CODE := @start_with,
@level := 0
) vars, code
WHERE @CODE IS NOT NULL) InnerQuery
可能是一个非常微不足道的问题,但可以使用更多的调查
答案 3 :(得分:0)
根据rsanchez回答中给出的事实,函数调用在SAME语句中,“@ level为level,...”,因此不保证函数调用将在该部分之前。
以下声明可能有效:
select
CODE,
@level as level,
@P_CODE as p_code,
@SORT as sort,
@CODE_NAME as CODE_NAME,
@CODE_LEVEL as CODE_LEVEL
from (
SELECT
menu_connect_by_p_code() AS CODE,
FROM (
SELECT
@start_with := 6001,@LANGUAGE := 'en' ,
@CODE := @start_with,
@level := 0
) vars, code
WHERE @CODE IS NOT NULL
) a