1

私はしばらくの間 Google で検索してきましたが、問題は、MySQL の CURSOR がどのように機能するかを明確に理解していないことだと確信しています。

問題の簡単な説明: 私はそのような関数を書いています (簡略化):

CREATE DEFINER=`me`@`localhost` FUNCTION `product_move`(prID INT, tr_type VARCHAR(2), clID INT, am INT, dnID INT, usrID INT, price FLOAT(10,2), ti DATETIME, barc TINYTEXT, cmt TINYTEXT, lnID INT)
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE cur_id INT;
    DECLARE net_pr FLOAT(10,2);
    DECLARE cur_r INT;
    DECLARE remaind INT DEFAULT 0;
    DECLARE avg_price FLOAT(10,2) DEFAULT 0;
    DECLARE curs CURSOR FOR SELECT  `products_transactionsID`,
                                                `price`,
                                                `remains`
                                        FROM `products_transactions`
                                        WHERE `productID`=prID AND `remains`>0 AND `type`='V'
                                        ORDER BY `products_transactionsID` ASC;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
 OPEN curs;
           SET remaind=am;
           read_loop:LOOP
                FETCH curs INTO cur_id,net_pr,cur_r;
                 IF done THEN
                  LEAVE read_loop;
                END IF;
                IF (cur_r>=remaind) THEN
                    SET avg_price = avg_price + (net_pr * remaind);
                    UPDATE `products_transactions` SET `remains`=`remains`-remaind WHERE products_transactionsID=cur_id;
                    LEAVE read_loop;
                ELSE

                    SET avg_price = avg_price + (net_pr * cur_r);
                    SET remaind=remaind-cur_r;
                    UPDATE `products_transactions` SET `remains`=0 WHERE products_transactionsID=cur_id;
                END IF;
           END LOOP;

CLOSE curs;
           SET avg_price=avg_price/am;
 INSERT INTO products_transactions
                       (`products_transactionsID`,`clientID`,`date_created`,`delivery_notesID`,`type`,`productID`,`amountIN`,`amountOUT`,`barcodes`,`in_stock`,`out_stock`,`out_repair`,`out_loss`,`booked`,`ordered`,`userID`,`price`,`comments`,`fifo_buy_price`)
                   SELECT NULL, clID, ti, dnID , tr_type, prID, 0, am, barc, products_transactions.in_stock-am, products_transactions.out_stock,
                       products_transactions.out_repair, products_transactions.out_loss, products_transactions.booked, products_transactions.ordered,usrID,price,cmt,avg_price
                   FROM
                       products_transactions WHERE productID=prID ORDER BY products_transactionsID DESC LIMIT 1;

そのため、以前に選択した行からのいくつかの計算に基づいて、このテーブルに新しい行を挿入し、その間にこれらの行を更新します。

問題は変数にあり、カーソルからフェッチさavg_priceれた変数に基づいて計算する必要があります。しかし、どういうわけか、変数はnet_prSELECT から FETCH されるのではなく、関数の入力パラメーターの値を取ります! そんなことがあるものか?net_prprice

私の推測はこれまでのところ:

  • 変数名の競合?コードを検索しましたが、見つかりません。

  • LOOP 内でテーブルを更新すると、CURSOR の位置が失われる可能性がありますか? それは理にかなっていますが、それはこれにもなりません...

どんなアイデアでも大歓迎です。

4

1 に答える 1

2

私が見ることができる2つのこと:

1) カーソルで使用しているテーブルを更新しないでください。MySQL はカーソルが読み取り専用であると言っていますが、私はこれを信用しません。値を設定し、カーソルを終了してから、テーブルを更新します。

2) proc 定義の変数と select の列に同じ名前を使用すると競合が発生します: http://dev.mysql.com/doc/refman/5.0/en/local-variable-scope.html

「ローカル変数は、テーブル列と同じ名前を持つべきではありません。SELECT ... INTO ステートメントなどの SQL ステートメントに、列への参照と同じ名前の宣言されたローカル変数が含まれている場合、MySQL は現在、変数の名前として参照します。」

于 2012-11-23T14:18:23.003 に答える