Neils
Neils

Reputation: 1513

Mysql FETCH CURSOR result ununderstood

I've been Googleing around for a while and I am sure that the problem is that I don't understand clearly how CURSORs in MySQL work.

A short explanation of the problem: I'm writing such function (simplified):

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;

So, we insert a new row in this table, based upon some calculations from the previously selected rows and updating these rows meanwhile.

The problem is with the avg_price variable, which should be calculated based on the net_pr variable which is FETCH'ed from the cursor. But somehow, instead of being FETCH'ed from the SELECT, the net_pr variable takes the value of the price input parameter of my function! How is that possible?

My guesses have been so far:

I'd apreciate any ideas.

Upvotes: 1

Views: 10191

Answers (1)

ethrbunny
ethrbunny

Reputation: 10469

Two things that I can see:

1) Don't update the table that you're using in the cursor. MySQL says the cursor is read only but I wouldn't trust this. Set your value, exit the cursor, and then update the table.

2) Using the same name for a variable in the proc definition and a column in a select gives a conflict: http://dev.mysql.com/doc/refman/5.0/en/local-variable-scope.html

"A local variable should not have the same name as a table column. If an SQL statement, such as a SELECT ... INTO statement, contains a reference to a column and a declared local variable with the same name, MySQL currently interprets the reference as the name of a variable. "

Upvotes: 2

Related Questions