4

という名前のテーブルがあります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 は、上の 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

最初に null を返す理由がわかりません。MYSQL の手順やバグのようなもので何か問題がありますか?

- - - - - - - - - - - - - - - - 編集 - - - - - - - - - ------------------

RolandoMySQLDBA、rsanchez、あなたのオプションを試しましたが、同じままです。複数の行を返し、一部の列は null です。

ここに画像の説明を入力

------------------------------- edit2 ------------------ ------------------

ここで見ることができます:http://sqlfiddle.com/#!2/aa033/1

4

4 に答える 4

3

MySQLリファレンスマニュアルから:

原則として、ユーザー変数に値を割り当てたり、同じステートメント内で値を読み取ったりしないでください。期待どおりの結果が得られる可能性がありますが、これは保証されません。ユーザー変数を含む式の評価順序は定義されておらず、特定のステートメント内に含まれる要素に基づいて変わる場合があります。さらに、この順序は、MySQL サーバーのリリース間で同じであるとは限りません。

したがって、次のように変更することをお勧めします。

SELECT
    @start_with := 6001,@LANGUAGE := 'en' ,
    @CODE := @start_with,
    @level := 0

に:

SELECT
    @start_with := 6001,@LANGUAGE := 'en' ,
    @CODE := 6001,
    @level := 0
于 2013-01-24T23:36:23.697 に答える
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;

試してみる !!!

更新 2013-02-01 16:18 EDT

問題は、ストアド プロシージャの次の部分にあります。

IF @CODE IS NULL THEN
  RETURN NULL;
END IF;

これらの行をコメントアウトして、何が起こるか見てみましょう!!!

于 2013-01-26T03:54:30.200 に答える
1

まず、これはプロシージャではなく関数です。

さて、私はフィドルを試しました-それはすべての代替実行でnullになるようです。

@CODEはNULLであるため、関数呼び出しの後に割り当てが行われると、出力はnullになります。おそらくこれが起こっていることです。

Rolandoの方法が機能しない場合は、これを行うことができます。さて、これはあなたの実行にいくらかの時間を追加し、実際にはもっとハックです。@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

本当に些細な問題かもしれませんが、より多くの調査を使用することができます

于 2013-01-30T19:30:37.837 に答える
0

rsanchez の回答で与えられた事実に基づいて、関数呼び出しは "@level as level, ..." を含む SAME ステートメントにあるため、関数呼び出しがその部分に先行することは保証されません。

次のステートメントが機能する可能性があります。

    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
于 2013-01-31T08:04:12.630 に答える