Search code examples
informixprocedure

Informix procedure — how to return an empty table?


I need to create an Informix procedure to return a table with rows if I found some value and an empty table if no value found.

I know how to return a table with rows, but I don't know how to return the empty table; can anyone help?

CREATE row type AType (
  id VARCHAR(255),
  name VARCHAR(255)
);


CREATE PROCEDURE getmeasurement (p_date DATETIME YEAR TO SECOND)
RETURNING MULTISET(AType NOT NULL);

    DEFINE AType_TABLE MULTISET (AType NOT NULL);
    DEFINE v_id VARCHAR(255);
    DEFINE v_name VARCHAR(255);
    ....
    IF( FoundValue ) THEN
        -- INSERT INTO TABLE
        INSERT INTO TABLE (AType_TABLE) VALUES (ROW(v_id,v_name)::AType);     
    ELSE
        // how to initial a AType_TABLE instance with empty records.
    END IF
    ....
    RETURN AType_TABLE;

END PROCEDURE;

Solution

  • Despite what it says in the SQL Syntax Manual, SPL (Stored Procedure Language) procedures can return collection types (COLLECT, SET, MULTISET or LIST). I've reported a documentation bug against that — which misled me earlier this week.

    I'm not able to get this procedure to compile under Informix 11.70.FC6 on Mac OS X 10.7.5, but the error it comes up with is:

    SQL -9905: [Internal] No extended type information for domain.
    

    I've run into various issues trying various variants of the above code. You can't have a WHERE clause on a DELETE from a multiset, it seems (different error message). You can also run into problems if you rollback the creation of the type and then try again.

    However, I was able to test it with a pre-release of 11.70.FC8 on Linux (RHEL 5, x86/64) and got the desired output:

    CREATE ROW TYPE IF NOT EXISTS AType
    (
        id   VARCHAR(255),
        name VARCHAR(255)
    );
    
    CREATE PROCEDURE getmeasurement (p_date DATETIME YEAR TO SECOND)
            RETURNING MULTISET(AType NOT NULL);
    
        DEFINE AType_TABLE MULTISET(AType NOT NULL);
        DEFINE v_id VARCHAR(255);
        DEFINE v_name VARCHAR(255);
    
        LET v_id = "Polynomial - " || p_date;
        LET v_name = "Euclid's Geometry of the Plane";
        INSERT INTO TABLE (AType_TABLE) VALUES(ROW(v_id, v_name)::AType);
        IF 1 = 1 THEN
            -- how TO initial a AType_TABLE instance WITH empty records.
            DELETE FROM TABLE(AType_TABLE);
        END IF
    
        RETURN AType_TABLE;
    
    END PROCEDURE;
    
    EXECUTE PROCEDURE getmeasurement(CURRENT);
    
    ROLLBACK;
    

    The output was:

    MULTISET{}
    

    which is an empty multiset. If you don't insert something into the multiset first, the delete fails. This is a trifle odd.

    Summary

    You may be OK with Informix 11.70.xC7; it may work on some other versions too. But there are likely to be a lot of versions of Informix where it does not work.