0

I am trying to write a mysql stored procedure with the following functions :

  1. Inputs are report parameters including report type, database to run against and some date and filter parameters
  2. The procedure looks up the report in table (report) and reads the report parameters.
  3. some reports are simple queries while others are UNIONS of 2 reports (isunion=1)
  4. after reading the report parameters from the report table, the procedure passes these to the build_report function which puts it together and returns the sql query.
  5. in the case of single query, the procedure works perfectly (i.e only 1 report part) but where there are 2 parts, the procedure fails. It seems unable to get a value from the build_report function even though the part1 of a multi part query is the almost identical as the case for report with a single query (is_union=0) except for getting the report_id for the part from the reports table.

What am I missing ? any insight would be hugely appreciated.

The below procedure works perfectly when isunion=0 but fails when isunion=1 (even if I rem out part 2 altogether)

    CREATE PROCEDURE `runreport_u`(
    in all_active INT(1),
    in reportid INT(10), 
    in db_id INT(10), 
    in start_date date, 
    in end_date date, 
    in inc_grpby INT(1), 
    OUT qry_part varchar(20000), #only outputing these to help debug
    OUT qry_part1 varchar(20000),
    OUT qry_part2 varchar(50000),
    OUT qry varchar(40000),
    OUT union_rep_id1 int(10),
    OUT union_rep_id2 int(10),
    OUT isunion int(10))
    BEGIN
    # purpose - this procedures looks up the specifications of a report query in table report. If the report is a single query the procedure works perfectly (case isunion=0) . When the qry is made up of 2 queries to be unionized, the build_report function which builds the parts seems to return nothing. 

    DECLARE part int DEFAULT NULL;

    # is this report a union
    SELECT is_union INTO isunion FROM report WHERE report_id=@reportid;

    IF isunion=0 THEN
    #report is not a union
            SET part=1;
            SET union_rep_id1=reportid;
          SET qry_part = build_report(all_active,union_rep_id1,db_id,start_date,end_date,inc_grpby); 
    #log the components into gen table (more for debugging than anything else)
            INSERT INTO gen (report_number,run_date,part_number,part_report_number,qry_part,part_order,param_all_active,param_report_id,param_db_id,param_start_date,param_end_date,param_incgrp)   VALUES (reportid, now(),part,COALESCE(union_rep_id1,999),qry_part,part,all_active,reportid,db_id,start_date,end_date,inc_grpby);        

    SET qry=qry_part;

    ELSE 
    #report has 2 or more parts
    #*** first part
        SET part=1;
    #set the first report part - works (returns same union_rep_id as above)     
        SELECT union_report_id1 INTO union_rep_id1 FROM report WHERE report_id=reportid;
    #get the query - in principle identical to the above but works above and returns nothing here 
            SET qry_part1 = build_report(all_active,union_rep_id1,db_id,start_date,end_date,inc_grpby); 

            INSERT INTO gen (report_number,run_date,part_number,part_report_number,qry_part,part_order,param_all_active,param_report_id,param_db_id,param_start_date,param_end_date,param_incgrp)   VALUES (reportid, now(),part,COALESCE(union_rep_id1,999),qry_part1,part,all_active,reportid,db_id,start_date,end_date,inc_grpby);       

    #*** second part
        SET part=2;
        SELECT union_report_id2 INTO union_rep_id2 FROM report WHERE report_id=reportid;
          SET qry_part2 = build_report(all_active,union_rep_id2,db_id,start_date,end_date,inc_grpby); 
            INSERT INTO gen (report_number,run_date,part_number,part_report_number,qry_part,part_order,param_all_active,param_report_id,param_db_id,param_start_date,param_end_date,param_incgrp)   VALUES (reportid, now(),part,COALESCE(union_rep_id2,999),qry_part,part,all_active,reportid,db_id,start_date,end_date,inc_grpby);        

    #*******
    #join the parts together in UNION
    SET qry=CONCAT(qry_part,' UNION ',qry_part2);

    END IF;

#had to add the line below otherwise Prepare stmt failed to recognize qry as variable

    SET @final_qry=qry;

    PREPARE stmt FROM @final_qry;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;

    #fails if isunion=1

    END
dengApro
  • 3,848
  • 2
  • 27
  • 41
pb6969
  • 1
  • 1
  • Print out the @final_qry before you execute it and check if it makes sense (and maybe run it outside of the procedure). It might simply be `null` if one of your parts is `null`. It's also unclear what you mean by "procedure fails". Do you get an error (if yes: add that error and the value for `@final_qry`)? Or does it something you do not want it to do? Then describe what is does, what it should do, and also the `@final_qry` (although it will then probably also require sample data). – Solarflare Sep 16 '17 at 17:02
  • adding as a comment, as this isn't entirely an answer... the "@" prefix is for session scoped user defined variables, not variables within your proc. So "@reportid" in your query is not the parameter "reportid". Naming conflicts can occur between columns, stored proc parameters/variables and user defined @vars. See this answer also in SO https://stackoverflow.com/a/1011052/5512900 – MNB Sep 16 '17 at 22:30

0 Answers0