如果第二次调用创建其他列,则过程失败

时间:2014-01-30 16:41:39

标签: mysql stored-procedures mysql-error-1054 dynamic-tables

Stack Exchange的居民,

我目前正在尝试创建一个以非常重要的方式重新格式化数据的过程。我得到了关于门票的数据列表(随机月份的摘要)。输入视图始终具有相同的列,但由于我必须将月份显示为列(通常在视图的Monat列中输入值)。 Sooo,经过一些重大的研究,试验和错误以及许多令人头疼的问题,我得让它发挥作用。该过程接受单个票号并“返回”该单个票证上的所有统计信息。

我是这样做的:

  1. 遍历每个不同的月份,构建一个CREATE TEMPORARY TABLE语句。
  2. 执行该语句,然后取消分配语句
  3. 遍历每个票证值,使用INSERT INTO ON DUPLICATE KEY UPDATE语句将其排序到临时表中(我会重新构建,执行和释放每次迭代)
  4. 再次迭代每个不同的月份,构建最后一次更新以填充摘要列(我知道,我可以将其合并到第1步,但我尝试将步骤尽可能分开,只是为了让它更容易阅读,我可以根据我的需要进行优化。
  5. 选择临时表,以便返回
  6. 清理一些松散的头,因为我是一个习惯性的整洁人。
  7. 好事:它有效! 坏事:它仅适用于一个输入值。每当我将其更改为另一个票号时,这将需要不同月份的列,它会失败,并显示“错误代码1054,字段列表中的未知列”,指的是当前查询不应具有的旧列(月)。 我可以根据需要多次运行该过程,只要临时表的列相同即可。 每当我删除并重新创建过程或创建新连接时,此行为都会重置。

    显然,我忘了在整个过程中的某个地方做一个清理步骤,而且我对SQL一般都是新手,特别是MySQL可能甚至不知道要找它:(。

    非常感谢帮助,谢谢, 佛瑞德

    DELIMITER //
    CREATE PROCEDURE proc_get_relevant_tickets(bID VARCHAR(10))
    DETERMINISTIC
    READS SQL DATA
    BEGIN
    # Declare storage vairables for withdrawing data from view
    DECLARE ID, FiID, ZVB, ZNVB, ZGes, WVB, WNVB, WGes INTEGER;
    DECLARE Mon VARCHAR(50);
    DECLARE RowVerb, RowNVerb, RowGes, Counter INTEGER;
    DECLARE verbucht, nichtverbucht, gesamt VARCHAR(50);
    DECLARE currentticket INTEGER;
    DECLARE statezges, statewges LONGTEXT;
    
    # Declare runtime stuff
    DECLARE done INT DEFAULT FALSE;
    DECLARE declaration LONGTEXT;
    DECLARE temptext VARCHAR(50);
    DECLARE Months CURSOR FOR SELECT DISTINCT Monat FROM view_list_of_tickets t WHERE bID = t.ID;
    DECLARE `Values` CURSOR FOR SELECT * FROM view_list_of_tickets t WHERE bID = t.ID;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
    
    # Clean up in case something interrupted last execution
    DROP TEMPORARY TABLE IF EXISTS temp_storage_5437485;
    
    # If there are any entries to work upon
    IF (SELECT COUNT(t.ID) FROM view_list_of_tickets t WHERE bID = t.ID > 0)
    THEN
        # Create temporary table to put the values into
        SET declaration = 'CREATE TEMPORARY TABLE `temp_storage_5437485` (ID INTEGER PRIMARY KEY, TicketNr INTEGER, Category VARCHAR(50), ';
    
        SET done = FALSE;
        OPEN Months;
        read_loop: LOOP
            FETCH Months INTO temptext;
            IF done THEN
                LEAVE read_loop;
            END IF;
            SET declaration = CONCAT(declaration, '`', temptext, ' Zeit` INTEGER DEFAULT 0, ');
            SET declaration = CONCAT(declaration, '`', temptext, ' Wert` INTEGER DEFAULT 0, ');
        END LOOP;
        CLOSE Months;
    
        SET declaration = CONCAT(declaration, '`Gesamt Zeit` INTEGER, `Gesamt Wert` INTEGER);');
        SELECT declaration INTO @declaration;
        PREPARE stmt FROM @declaration;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
        # End of creating the storage container
    
        # Cycle through values and input into temporary table
        SET done = FALSE;
        SET verbucht = 'Verbucht';
        SET nichtverbucht = 'Nicht Verbucht';
        SET gesamt = 'Gesamt';
        SET currentticket = 0;
        SET Counter = 0;
        SET RowVerb = 1;
        SET RowNVerb = 2;
        SET RowGes = 3;
        OPEN `Values`;
        read_values: LOOP
            FETCH `Values` INTO ID, FiID, ZVB, ZNVB, ZGes, WVB, WNVB, WGes, Mon;
            IF done THEN
                LEAVE read_values;
            END IF;
    
            # If a new ticket has been arrived at, increment the counters
            IF currentticket > 0 AND ID <> currentticket THEN
                SET currentticket = ID;
                SET Counter = Counter + 1;
                SET RowVerb = RowVerb + 3;
                SET RowNVerb = RowNVerb + 3;
                SET RowGes = RowGes + 3;
            END IF;
    
            IF currentticket = 0 AND ID <> currentticket THEN
                SET currentticket = ID;
            END IF;
    
            # Insert first (Verbucht) row
            SET declaration = CONCAT('INSERT INTO `temp_storage_5437485` (`ID`, `TicketNr`, `', Mon, ' Zeit`, `', Mon, ' Wert`) VALUES (');
            SET declaration = CONCAT(declaration, RowVerb, ', ', ID, ', ', ZVB, ', ', WVB, ') ON DUPLICATE KEY UPDATE ');
            SET declaration = CONCAT(declaration, '`', Mon, ' Zeit`=', ZVB, ', `', Mon, ' Wert`=', WVB, ';');
            SELECT declaration INTO @declaration;
            PREPARE stmt FROM @declaration;
            EXECUTE stmt;
            DEALLOCATE PREPARE stmt;
    
            # Insert second (Nicht Verbucht) row
            SET declaration = CONCAT('INSERT INTO `temp_storage_5437485` (`ID`, `TicketNr`, `', Mon, ' Zeit`, `', Mon, ' Wert`) VALUES (');
            SET declaration = CONCAT(declaration, RowNVerb, ', ', ID, ', ', ZNVB, ', ', WNVB, ') ON DUPLICATE KEY UPDATE ');
            SET declaration = CONCAT(declaration, '`', Mon, ' Zeit`=', ZNVB, ', `', Mon, ' Wert`=', WNVB, ';');
            SELECT declaration INTO @declaration;
            PREPARE stmt FROM @declaration;
            EXECUTE stmt;
            DEALLOCATE PREPARE stmt;
    
            # Insert third (Gesamt) row
            SET declaration = CONCAT('INSERT INTO `temp_storage_5437485` (`ID`, `TicketNr`, `', Mon, ' Zeit`, `', Mon, ' Wert`) VALUES (');
            SET declaration = CONCAT(declaration, RowGes, ', ', ID, ', ', ZGes, ', ', WGes, ') ON DUPLICATE KEY UPDATE ');
            SET declaration = CONCAT(declaration, '`', Mon, ' Zeit`=', ZGes, ', `', Mon, ' Wert`=', WGes, ';');
            SELECT declaration INTO @declaration;
            PREPARE stmt FROM @declaration;
            EXECUTE stmt;
            DEALLOCATE PREPARE stmt;
    
            UPDATE temp_storage_5437485 SET Category = verbucht WHERE temp_storage_5437485.ID = RowVerb LIMIT 5;
            UPDATE temp_storage_5437485 SET Category = nichtverbucht WHERE temp_storage_5437485.ID = RowNVerb LIMIT 5;
            UPDATE temp_storage_5437485 SET Category = gesamt WHERE temp_storage_5437485.ID = RowGes LIMIT 5;
        END LOOP;
        CLOSE `Values`;
        # End of cycling for values input
    
        # Being calculating the total values
        SET declaration = 'UPDATE temp_storage_5437485 SET `Gesamt Zeit` = (';
        SET statezges = '';
        SET statewges = '';
    
        SET done = FALSE;
        OPEN Months;
        read_loop: LOOP
            FETCH Months INTO temptext;
            IF done THEN
                LEAVE read_loop;
            END IF;
    
            # If not the first entry, add more
            IF statezges <> '' THEN
                SET statezges = CONCAT(statezges, ' + ');
            END IF;
            IF statewges <> '' THEN
                SET statewges = CONCAT(statewges, ' + ');
            END IF;
    
            # Add column name
            SET statezges = CONCAT(statezges, 'temp_storage_5437485.`', temptext, ' Zeit`');
            SET statewges = CONCAT(statewges, 'temp_storage_5437485.`', temptext, ' Wert`');
        END LOOP;
        CLOSE Months;
    
        SET declaration = CONCAT(declaration, statezges, '), `Gesamt Wert` = (', statewges, ') LIMIT 100000');
        SELECT declaration INTO @declaration;
        PREPARE stmt FROM @declaration;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
        # End calculating the total values
    
        SELECT * FROM temp_storage_5437485;
        DROP TEMPORARY TABLE IF EXISTS temp_storage_5437485;
    ELSE
        SELECT 'is null';
    END IF;
    
    DROP TEMPORARY TABLE IF EXISTS temp_storage_5437485;
    END //
    
    DELIMITER ;
    

0 个答案:

没有答案