Thread: executing dynamic commands

executing dynamic commands

From
christian.michels@eifelgeist.com
Date:
Hi,

I user PostgreSQl 8.0.4 on Win2003 Server and write a function to copy rows from one table into another table with the
samecolumn definition.
 
My first approach was to use something like:

query_value :=  'INSERT INTO ' || tabledest || ' SELECT * FROM ' || tablesrc;
EXECUTE query_value; 

This only works if the column definition AND the order between source and destination is the same ! 
In my case I have always the same column definitions but they are not in the same order between source and destination
table.
What I tryed then is to loop through the column definition of the source and query the sourcetable for the value. For
thatI have to execut a query with dynamic tablename and dynamic columname to generate two stings one with the
columndefinitinand one with the columnvalues to exececute something like: INSERT INTO tabelfoo (columndefinitinstring)
VALUES(columnvaluesstring)
 
see snip of function:

fieldvalues RECORD;
output  RECORD;
insertvalues VARCHAR;
fieldname VARCHAR;


-- Get Attribute List from Table and write it to output
-- Read Values of Fieldname from source
query_value :=  'select * from ' || tablesrc ;

FOR fieldvalues IN EXECUTE query_value LOOP
 FOR output IN SELECT a.attnum,     a.attname AS field,     FROM     pg_class c,  pg_attribute a,  pg_type t   WHERE
c.relname = tablesrc  AND      a.attnum > 0  AND      a.attrelid = c.oid  AND     a.atttypid = t.oid   ORDER BY
a.attnumLOOP         -- Read Field Name from Out Table    fieldname := output.field;        -- Write Field Name into
Variable   IF insertcolumns IS NULL THEN      insertcolumns := fieldname;    ELSE      insertcolumns := insertcolumns
||',' || fieldname;    END IF;    
 
Until here everyting is fine ... but now I try to query  the value from RECORD fieldvalues with the columname fieldname
variablefrom the inner loop !
 
I tryed the following ...            
query_value :=  'select quote_ident(' || fieldvalues || ').quote_literal(' || fieldname ||')';

EXECUTE query_value;


and I get the following error message ...

ERROR:  could not find array type for data type record
CONTEXT:  SQL statement "SELECT  'select quote_ident(' ||  $1  || ').quote_literal(' ||  $2  ||')'"
PL/pgSQL function "prx_db__appendtable" line 87 at assignment

     END LOOP;            END LOOP;

I know the function is not runnable, but my question is  how can I dynamically combine "fieldvalues"."fieldname" to
readthe values column by colum out if a RECORD variable to generate the "columnvaluesstring" mentioned above ?!
 
Maybe this approach is to complicated and there is a quick and easy solution ?!

Any help is very much appreciated !!

Thanx a lot & Regards

Chris


Re: executing dynamic commands

From
"codeWarrior"
Date:
Talk about obfuscated.... Are you trying to retrieve the table structure / 
schema from the PG System Catalogs ?

If so -- you are better off using a VIEW instead of a manual procedure 
because it will automatically kepp up with the current schema definition...

Try this:

-- DROP VIEW sys_table_schemas;

CREATE OR REPLACE VIEW sys_table_schemas ASSELECT pc.oid AS tbl_oid, pc.relname::character varying AS table_name, 
pa.attname::character varying AS column_name, pt.typname AS data_type,       CASE           WHEN
substr(pt.typname::text,1, 3)::name = 'int'::name THEN 
 
'integer'::name           WHEN pt.typname = 'bool'::name THEN 'boolean'::name           ELSE pt.typname       END AS
udt_name,pa.attnum AS ordinal_position, 254 AS str_length,       CASE           WHEN pa.attnotnull THEN false
ELSEtrue       END AS nulls_allowed,       CASE           WHEN substr(pa.attname::text, 1, 3) = 'lu_'::text THEN true
       ELSE false       END AS lookup,       CASE           WHEN pd.description::character varying IS NOT NULL THEN 
 
pd.description::character varying           WHEN pa.attname IS NOT NULL THEN pa.attname::character varying
ELSENULL::character varying       END AS label  FROM ONLY pg_class pc  JOIN ONLY pg_attribute pa ON pc.oid =
pa.attrelidAND pc.relnamespace = 
 
2200::oid AND pc.reltype > 0::oid AND (pc.relkind = 'r'::"char" OR 
pc.relkind = 'v'::"char")  JOIN ONLY pg_type pt ON pa.atttypid = pt.oid  LEFT JOIN ONLY pg_description pd ON pc.oid =
pd.objoidAND pa.attnum = 
 
pd.objsubid WHERE pa.attnum > 0 ORDER BY pc.relname::character varying, pa.attnum;

ALTER TABLE sys_table_schemas OWNER TO "public";

SELECT * FROM sys_table_schemas;




<christian.michels@eifelgeist.com> wrote in message 
news:15802822.125111138807576371.JavaMail.servlet@kundenserver...
> Hi,
>
> I user PostgreSQl 8.0.4 on Win2003 Server and write a function to copy 
> rows from one table into another table with the same column definition.
> My first approach was to use something like:
>
> query_value :=  'INSERT INTO ' || tabledest || ' SELECT * FROM ' || 
> tablesrc;
> EXECUTE query_value;
>
> This only works if the column definition AND the order between source and 
> destination is the same !
> In my case I have always the same column definitions but they are not in 
> the same order between source and destination table.
> What I tryed then is to loop through the column definition of the source 
> and query the sourcetable for the value. For that I have to execut a query 
> with dynamic tablename and dynamic columname to generate two stings one 
> with the columndefinitin and one with the columnvalues to exececute 
> something like: INSERT INTO tabelfoo (columndefinitinstring) VALUES 
> (columnvaluesstring)
>
> see snip of function:
>
> fieldvalues RECORD;
> output  RECORD;
> insertvalues VARCHAR;
> fieldname VARCHAR;
>
>
> -- Get Attribute List from Table and write it to output
> -- Read Values of Fieldname from source
> query_value :=  'select * from ' || tablesrc ;
>
> FOR fieldvalues IN EXECUTE query_value LOOP
>
>  FOR output IN SELECT a.attnum,
>    a.attname AS field,
>    FROM
>      pg_class c,  pg_attribute a,  pg_type t
>    WHERE
>      c.relname = tablesrc  AND
>      a.attnum > 0  AND
>      a.attrelid = c.oid  AND
>      a.atttypid = t.oid
>    ORDER BY a.attnum LOOP
>
>     -- Read Field Name from Out Table
>     fieldname := output.field;
>
>     -- Write Field Name into Variable
>     IF insertcolumns IS NULL THEN
>       insertcolumns := fieldname;
>     ELSE
>       insertcolumns := insertcolumns || ',' || fieldname;
>     END IF;
>
> Until here everyting is fine ... but now I try to query  the value from 
> RECORD fieldvalues with the columname fieldname variable from the inner 
> loop !
> I tryed the following ...
>
> query_value :=  'select quote_ident(' || fieldvalues || ').quote_literal(' 
> || fieldname ||')';
>
> EXECUTE query_value;
>
>
> and I get the following error message ...
>
> ERROR:  could not find array type for data type record
> CONTEXT:  SQL statement "SELECT  'select quote_ident(' ||  $1  || 
> ').quote_literal(' ||  $2  ||')'"
> PL/pgSQL function "prx_db__appendtable" line 87 at assignment
>
>
>      END LOOP;
>
>    END LOOP;
>
> I know the function is not runnable, but my question is  how can I 
> dynamically combine "fieldvalues"."fieldname" to read the values column by 
> colum out if a RECORD variable to generate the "columnvaluesstring" 
> mentioned above ?!
> Maybe this approach is to complicated and there is a quick and easy 
> solution ?!
>
> Any help is very much appreciated !!
>
> Thanx a lot & Regards
>
> Chris
>
> ---------------------------(end of broadcast)---------------------------
> TIP 9: In versions below 8.0, the planner will ignore your desire to
>       choose an index scan if your joining column's datatypes do not
>       match
> 




Re: executing dynamic commands

From
christian.michels@eifelgeist.com
Date:
Thanx for the quick response !
Sorry for asking a bit confusing question ... Using the View is a good idea but does not fully solve my problem. To
makeit a bit more clear: I want to copy all records from table1 to table2 assuming that the two tables have exactly the
samecolumn definition and column order. I could do that executing INSERT INTO tablefoo1 SELECT * FROM tablefoo2;
 
But how can I do the copying if the column order is different between tablefoo1 and tablefoo2 ?
My approach was to dynamically assemble a string1 with all fieldnames and a string2 with the corresponding field values
rowper row using a plpgsql function. The result would be a row per row copying using INSERT INTO tablefoo1 (string1)
VALUES(string2). My problem is that I not manage to read the fieldvalues row by row. 
 
Do you have any idea ?

Thanx a lot !

Regards

Chris


>
>Talk about obfuscated.... Are you trying to retrieve the table structure / 
>schema from the PG System Catalogs ?
>
>If so -- you are better off using a VIEW instead of a manual procedure 
>because it will automatically kepp up with the current schema definition...
>
>Try this:
>
>-- DROP VIEW sys_table_schemas;
>
>CREATE OR REPLACE VIEW sys_table_schemas AS
> SELECT pc.oid AS tbl_oid, pc.relname::character varying AS table_name, 
>pa.attname::character varying AS column_name, pt.typname AS data_type,
>        CASE
>            WHEN substr(pt.typname::text, 1, 3)::name = 'int'::name THEN 
>'integer'::name
>            WHEN pt.typname = 'bool'::name THEN 'boolean'::name
>            ELSE pt.typname
>        END AS udt_name, pa.attnum AS ordinal_position, 254 AS str_length,
>        CASE
>            WHEN pa.attnotnull THEN false
>            ELSE true
>        END AS nulls_allowed,
>        CASE
>            WHEN substr(pa.attname::text, 1, 3) = 'lu_'::text THEN true
>            ELSE false
>        END AS lookup,
>        CASE
>            WHEN pd.description::character varying IS NOT NULL THEN 
>pd.description::character varying
>            WHEN pa.attname IS NOT NULL THEN pa.attname::character varying
>            ELSE NULL::character varying
>        END AS label
>   FROM ONLY pg_class pc
>   JOIN ONLY pg_attribute pa ON pc.oid = pa.attrelid AND pc.relnamespace = 
>2200::oid AND pc.reltype > 0::oid AND (pc.relkind = 'r'::"char" OR 
>pc.relkind = 'v'::"char")
>   JOIN ONLY pg_type pt ON pa.atttypid = pt.oid
>   LEFT JOIN ONLY pg_description pd ON pc.oid = pd.objoid AND pa.attnum = 
>pd.objsubid
>  WHERE pa.attnum > 0
>  ORDER BY pc.relname::character varying, pa.attnum;
>
>ALTER TABLE sys_table_schemas OWNER TO "public";
>
>SELECT * FROM sys_table_schemas;
>
>
>
>
><christian.michels@eifelgeist.com> wrote in message 
>news:15802822.125111138807576371.JavaMail.servlet@kundenserver...
>> Hi,
>>
>> I user PostgreSQl 8.0.4 on Win2003 Server and write a function to copy 
>> rows from one table into another table with the same column definition.
>> My first approach was to use something like:
>>
>> query_value :=  'INSERT INTO ' || tabledest || ' SELECT * FROM ' || 
>> tablesrc;
>> EXECUTE query_value;
>>
>> This only works if the column definition AND the order between source and 
>> destination is the same !
>> In my case I have always the same column definitions but they are not in 
>> the same order between source and destination table.
>> What I tryed then is to loop through the column definition of the source 
>> and query the sourcetable for the value. For that I have to execut a query 
>> with dynamic tablename and dynamic columname to generate two stings one 
>> with the columndefinitin and one with the columnvalues to exececute 
>> something like: INSERT INTO tabelfoo (columndefinitinstring) VALUES 
>> (columnvaluesstring)
>>
>> see snip of function:
>>
>> fieldvalues RECORD;
>> output  RECORD;
>> insertvalues VARCHAR;
>> fieldname VARCHAR;
>>
>>
>> -- Get Attribute List from Table and write it to output
>> -- Read Values of Fieldname from source
>> query_value :=  'select * from ' || tablesrc ;
>>
>> FOR fieldvalues IN EXECUTE query_value LOOP
>>
>>  FOR output IN SELECT a.attnum,
>>    a.attname AS field,
>>    FROM
>>      pg_class c,  pg_attribute a,  pg_type t
>>    WHERE
>>      c.relname = tablesrc  AND
>>      a.attnum > 0  AND
>>      a.attrelid = c.oid  AND
>>      a.atttypid = t.oid
>>    ORDER BY a.attnum LOOP
>>
>>     -- Read Field Name from Out Table
>>     fieldname := output.field;
>>
>>     -- Write Field Name into Variable
>>     IF insertcolumns IS NULL THEN
>>       insertcolumns := fieldname;
>>     ELSE
>>       insertcolumns := insertcolumns || ',' || fieldname;
>>     END IF;
>>
>> Until here everyting is fine ... but now I try to query  the value from 
>> RECORD fieldvalues with the columname fieldname variable from the inner 
>> loop !
>> I tryed the following ...
>>
>> query_value :=  'select quote_ident(' || fieldvalues || ').quote_literal(' 
>> || fieldname ||')';
>>
>> EXECUTE query_value;
>>
>>
>> and I get the following error message ...
>>
>> ERROR:  could not find array type for data type record
>> CONTEXT:  SQL statement "SELECT  'select quote_ident(' ||  $1  || 
>> ').quote_literal(' ||  $2  ||')'"
>> PL/pgSQL function "prx_db__appendtable" line 87 at assignment
>>
>>
>>      END LOOP;
>>
>>    END LOOP;
>>
>> I know the function is not runnable, but my question is  how can I 
>> dynamically combine "fieldvalues"."fieldname" to read the values column by 
>> colum out if a RECORD variable to generate the "columnvaluesstring" 
>> mentioned above ?!
>> Maybe this approach is to complicated and there is a quick and easy 
>> solution ?!
>>
>> Any help is very much appreciated !!
>>
>> Thanx a lot & Regards
>>
>> Chris
>>
>> ---------------------------(end of broadcast)---------------------------
>> TIP 9: In versions below 8.0, the planner will ignore your desire to
>>       choose an index scan if your joining column's datatypes do not
>>       match
>> 
>
>
>
>---------------------------(end of broadcast)---------------------------
>TIP 4: Have you searched our list archives?
>
>               http://archives.postgresql.org


Re: executing dynamic commands

From
Stephan Szabo
Date:
On Wed, 1 Feb 2006 christian.michels@eifelgeist.com wrote:

> Hi,
>
> I user PostgreSQl 8.0.4 on Win2003 Server and write a function to copy rows from one table into another table with
thesame column definition.
 
> My first approach was to use something like:
>
> query_value :=  'INSERT INTO ' || tabledest || ' SELECT * FROM ' || tablesrc;
> EXECUTE query_value;
>
> This only works if the column definition AND the order between source and destination is the same !
> In my case I have always the same column definitions but they are not in> the same order between source and
destinationtable.
 

> What I tryed then is to loop through the column definition of the source
> and query the sourcetable for the value. For that I have to execut a
> query with dynamic tablename and dynamic columname to generate two
> stings one with the columndefinitin and one with the columnvalues to
> exececute something like: INSERT INTO tabelfoo (columndefinitinstring)
> VALUES (columnvaluesstring)

You might have better luck with a INSERT ... SELECT where you've reordered
the columns in the select list

INSERT INTO tabledest SELECT <reordered columns to match dest order> FROM
tablesrc


Re: executing dynamic commands

From
christian.michels@eifelgeist.com
Date:
Thanx a lot guys -  it works !

Cheers

Chris


On Wed, 1 Feb 2006 christian ( dot ) michels ( at ) eifelgeist ( dot ) com wrote:

> Hi,
>
> I user PostgreSQl 8.0.4 on Win2003 Server and write a function to copy rows from one table into another table with
thesame column definition.
 

> My first approach was to use something like:
>
> query_value :=  'INSERT INTO ' || tabledest || ' SELECT * FROM ' || tablesrc;
> EXECUTE query_value;
>
> This only works if the column definition AND the order between source and destination is the same !
> In my case I have always the same column definitions but they are not in> the same order between source and
destinationtable.
 

> What I tryed then is to loop through the column definition of the source
> and query the sourcetable for the value. For that I have to execut a
> query with dynamic tablename and dynamic columname to generate two
> stings one with the columndefinitin and one with the columnvalues to
> exececute something like: INSERT INTO tabelfoo (columndefinitinstring)
> VALUES (columnvaluesstring)

You might have better luck with a INSERT ... SELECT where you've reordered
the columns in the select list

INSERT INTO tabledest SELECT <reordered columns to match dest order> FROM
tablesrc


Re: executing dynamic commands

From
"codeWarrior"
Date:
In your function why not create a temporary table then use that for your 
processing ?

CREATE TEMPRORARY TABLE tabledest AS (SELECT * FROM tblsrc WHERE condition);


<christian.michels@eifelgeist.com> wrote in message 
news:15802822.125111138807576371.JavaMail.servlet@kundenserver...
> Hi,
>
> I user PostgreSQl 8.0.4 on Win2003 Server and write a function to copy 
> rows from one table into another table with the same column definition.
> My first approach was to use something like:
>
> query_value :=  'INSERT INTO ' || tabledest || ' SELECT * FROM ' || 
> tablesrc;
> EXECUTE query_value;
>
> This only works if the column definition AND the order between source and 
> destination is the same !
> In my case I have always the same column definitions but they are not in 
> the same order between source and destination table.
> What I tryed then is to loop through the column definition of the source 
> and query the sourcetable for the value. For that I have to execut a query 
> with dynamic tablename and dynamic columname to generate two stings one 
> with the columndefinitin and one with the columnvalues to exececute 
> something like: INSERT INTO tabelfoo (columndefinitinstring) VALUES 
> (columnvaluesstring)
>
> see snip of function:
>
> fieldvalues RECORD;
> output  RECORD;
> insertvalues VARCHAR;
> fieldname VARCHAR;
>
>
> -- Get Attribute List from Table and write it to output
> -- Read Values of Fieldname from source
> query_value :=  'select * from ' || tablesrc ;
>
> FOR fieldvalues IN EXECUTE query_value LOOP
>
>  FOR output IN SELECT a.attnum,
>    a.attname AS field,
>    FROM
>      pg_class c,  pg_attribute a,  pg_type t
>    WHERE
>      c.relname = tablesrc  AND
>      a.attnum > 0  AND
>      a.attrelid = c.oid  AND
>      a.atttypid = t.oid
>    ORDER BY a.attnum LOOP
>
>     -- Read Field Name from Out Table
>     fieldname := output.field;
>
>     -- Write Field Name into Variable
>     IF insertcolumns IS NULL THEN
>       insertcolumns := fieldname;
>     ELSE
>       insertcolumns := insertcolumns || ',' || fieldname;
>     END IF;
>
> Until here everyting is fine ... but now I try to query  the value from 
> RECORD fieldvalues with the columname fieldname variable from the inner 
> loop !
> I tryed the following ...
>
> query_value :=  'select quote_ident(' || fieldvalues || ').quote_literal(' 
> || fieldname ||')';
>
> EXECUTE query_value;
>
>
> and I get the following error message ...
>
> ERROR:  could not find array type for data type record
> CONTEXT:  SQL statement "SELECT  'select quote_ident(' ||  $1  || 
> ').quote_literal(' ||  $2  ||')'"
> PL/pgSQL function "prx_db__appendtable" line 87 at assignment
>
>
>      END LOOP;
>
>    END LOOP;
>
> I know the function is not runnable, but my question is  how can I 
> dynamically combine "fieldvalues"."fieldname" to read the values column by 
> colum out if a RECORD variable to generate the "columnvaluesstring" 
> mentioned above ?!
> Maybe this approach is to complicated and there is a quick and easy 
> solution ?!
>
> Any help is very much appreciated !!
>
> Thanx a lot & Regards
>
> Chris
>
> ---------------------------(end of broadcast)---------------------------
> TIP 9: In versions below 8.0, the planner will ignore your desire to
>       choose an index scan if your joining column's datatypes do not
>       match
>