My question is some kind of extension to Erwin Brandstetter's excellent answer in this thread on the correct use of WITH.
My old query looks like this:
WITH x AS (
    INSERT INTO d (dm_id)
    SELECT dm_id
    FROM dm, import i
    WHERE  dm.dm_name = i.dm_name
    RETURNING d_id
), y AS (
    INSERT INTO z (d_id)
    SELECT d_id
    FROM x
    RETURNING z_id
)
INSERT INTO port (z_id)
SELECT z_id
FROM y;
This works like a charm. But now, another table (r) has been added (same structure as table d) and with it the possibility that either d_id or r_id has to be added to table z. This, depending on whether dm_name or rm_name is empty in table import. So my theoretical approach would be something like this:
SELECT dm_name, rm_name
    ,CASE WHEN dm_name != '' THEN 
        WITH x AS (
            INSERT INTO d (dm_id)
            SELECT dm_id
            FROM dm, import i
            WHERE  dm.dm_name = i.dm_name
            RETURNING d_id
        ), y AS (
            INSERT INTO z (d_id)
            SELECT d_id
            FROM x
            RETURNING z_id
        )
        INSERT INTO port (z_id)
        SELECT z_id
        FROM y
    END
    ,CASE WHEN rm_name != '' THEN 
        WITH x AS (
            INSERT INTO r (rm_id)
            SELECT rm_id
            FROM rm, import i
            WHERE  rm.rm_name = i.rm_name
            RETURNING r_id
        ), y AS (
            INSERT INTO z (r_id)
            SELECT r_id
            FROM x
            RETURNING z_id
        )
        INSERT INTO port (z_id)
        SELECT z_id
        FROM y
    END
FROM import;
But PostgreSQL tells me:
syntax error at or near "INSERT INTO port (z_id)"
although that part of the query should be correct as it works already.
I hope you can help me solve this. :)
For a better understanding - here's the table structure:
CREATE TABLE import (
    dm_name character varying,
    rm_name character varying
    -- many other columns which are not relevant
);
CREATE TABLE dm (
    dm_id integer NOT NULL, -- serial
    dm_name character varying
    -- plus more columns
);
CREATE TABLE d (
    d_id integer NOT NULL, -- serial
    dm_id integer -- references dm.dm_id
    -- plus more columns
);
CREATE TABLE rm (
    rm_id integer NOT NULL, -- serial
    rm_name character varying
    -- plus more columns
);
CREATE TABLE r (
    r_id integer NOT NULL, -- serial
    rm_id integer -- references rm.rm_id
    -- plus more columns
);
CREATE TABLE z (
    z_id integer NOT NULL, -- serial
    r_id integer, -- references r.r_id
    d_id integer -- references d.d_id
    -- plus more columns
);
CREATE TABLE port (
    p_id integer NOT NULL, -- serial
    z_id integer, -- references z.z_id
    -- plus more columns
);
The import table doesn't know the ids as they are generated during the atomization process. The dm and rm tables are for device models which were already extracted from the import table. The d and r tables are for the actual devices. As a port only can only have either a r-device or a d-device or none, the z-table was introduced to have only one field in the port-table representing all possibilities. The d/r and dm/rm tables can't be combined as they have different special columns depending on the device types.
 
     
    