Thread: column "id" is of type integer but expression is of type character

column "id" is of type integer but expression is of type character

From
"Andrus"
Date:
Commands:

create temp table test ( id int, baas char(10) );
create temp table lisa ( id int, baas char(10) );
alter table lisa drop column id;
INSERT INTO test SELECT * FROM lisa;
drop table lisa;

Cause error

ERROR:  column "id" is of type integer but expression is of type character
HINT:  You will need to rewrite or cast the expression.

********** Error **********

ERROR: column "id" is of type integer but expression is of type character
SQL state: 42804
Hint: You will need to rewrite or cast the expression.

How to fix ?

Andrus.

Re: column "id" is of type integer but expression is of type character

From
Raymond O'Donnell
Date:
On 08/01/2009 19:04, Andrus wrote:

> create temp table test ( id int, baas char(10) );
> create temp table lisa ( id int, baas char(10) );
> alter table lisa drop column id;
> INSERT INTO test SELECT * FROM lisa;
> drop table lisa;
>
> Cause error
>
> ERROR:  column "id" is of type integer but expression is of type character
> HINT:  You will need to rewrite or cast the expression.

Well, you've dropped the integer column from test, so now the INSERT
command is trying to stuff the char(10) value from test into the integer
column in lisa - which is what the error message is telling you.

I've no idea, in any case, whether you can expect SELECTing two columns
into a one-column table to work.

Ray.

------------------------------------------------------------------
Raymond O'Donnell, Director of Music, Galway Cathedral, Ireland
rod@iol.ie
Galway Cathedral Recitals: http://www.galwaycathedral.org/recitals
------------------------------------------------------------------

Re: column "id" is of type integer but expression is of type character

From
Alan Hodgson
Date:
On Thursday 08 January 2009, "Andrus" <kobruleht2@hot.ee> wrote:
> Commands:
>
> create temp table test ( id int, baas char(10) );
> create temp table lisa ( id int, baas char(10) );
> alter table lisa drop column id;
> INSERT INTO test SELECT * FROM lisa;


> How to fix ?

INSERT INTO test (baas)  SELECT baas FROM lisa;


--
Current Peeve: The mindset that the Internet is some sort of school for
novice sysadmins and that everyone -not- doing stupid dangerous things
should act like patient teachers with the ones who are. -- Bill Cole, NANAE

Re: column "id" is of type integer but expression is of type character

From
Richard Huxton
Date:
Andrus wrote:
> Commands:
>
> create temp table test ( id int, baas char(10) );
> create temp table lisa ( id int, baas char(10) );
> alter table lisa drop column id;
> INSERT INTO test SELECT * FROM lisa;
> drop table lisa;
>
> Cause error
>
> ERROR:  column "id" is of type integer but expression is of type character
> HINT:  You will need to rewrite or cast the expression.

> How to fix ?

Don't use SELECT * - list the columns you want to insert. I can't think
why you would do that (you'll end up with nulls in the id column) but it
will work.

--
  Richard Huxton
  Archonet Ltd

Re: column "id" is of type integer but expression is of type character

From
Tom Lane
Date:
"Raymond O'Donnell" <rod@iol.ie> writes:
> I've no idea, in any case, whether you can expect SELECTing two columns
> into a one-column table to work.

It won't, but the other error happens to be detected first.

            regards, tom lane

Re: column "id" is of type integer but expression is of type character

From
"Andrus"
Date:
Thank you.

> Well, you've dropped the integer column from test, so now the INSERT
> command is trying to stuff the char(10) value from test into the integer
> column in lisa - which is what the error message is telling you.

INSERT INTO test SELECT * FROM lisa;

I need that test table primary key column (id) values are populated
automatically with new ids from serial sequence, but all other column values
are duplicatated.

In reality those tables contain large number of columns and  some column
names may be not known at script creation time.

So it is not possible not create column list instead of *

How to force PostgreSql to match columns by name, not by position so that
this command will work ?

Andrus.


Re: column "id" is of type integer but expression is of type character

From
"Andrus"
Date:
Richard,

> Don't use SELECT * - list the columns you want to insert. I can't think
> why you would do that (you'll end up with nulls in the id column) but it
> will work.

In real table id is defined as

id serial primary key

so I excpect that it will be populated with correct values.
List of columns are not exactly known at script creation time (in customer
sites customers may add additional columns to table),
so using column list is not possible.

Ony way seems to generates SELECT column list dynamically at run time, but
I'm looking for nicer solution to force PostgreSql to match columns by name.

Andrus.


Re: column "id" is of type integer but expression is of type character

From
Richard Huxton
Date:
Andrus wrote:
> Richard,
>
>> Don't use SELECT * - list the columns you want to insert. I can't think
>> why you would do that (you'll end up with nulls in the id column) but it
>> will work.
>
> In real table id is defined as
>
> id serial primary key
>
> so I excpect that it will be populated with correct values.
> List of columns are not exactly known at script creation time (in
> customer sites customers may add additional columns to table),
> so using column list is not possible.
>
> Ony way seems to generates SELECT column list dynamically at run time,
> but I'm looking for nicer solution to force PostgreSql to match columns
> by name.

There isn't one. That's not how SQL works. You need to know what columns
your tables have.

If you want to update the primary key just do something like:

INSERT INTO t1 SELECT * FROM t2;
UPDATE t1 SET id = DEFAULT;

Although if you don't know what your columns are called I can't see how
you can figure out that you have a single-column pkey with
auto-incrementing default.

--
  Richard Huxton
  Archonet Ltd

Re: column "id" is of type integer but expression is of type character

From
Raymond O'Donnell
Date:
On 08/01/2009 20:10, Andrus wrote:
> Thank you.
>
>> Well, you've dropped the integer column from test, so now the INSERT
>> command is trying to stuff the char(10) value from test into the integer
>> column in lisa - which is what the error message is telling you.
>
> INSERT INTO test SELECT * FROM lisa;

Oops - my mistake - I read it the wrong way around.

> In reality those tables contain large number of columns and  some column
> names may be not known at script creation time.
>
> So it is not possible not create column list instead of *
>
> How to force PostgreSql to match columns by name, not by position so that
> this command will work ?

I don't think you can - here's what the docs[1] for INSERT say:

<quote from docs>
The target column names can be listed in any order. If no list of column
names is given at all, the default is all the columns of the table in
their declared order; or the first N column names, if there are only N
columns supplied by the VALUES clause or query. The values supplied by
the VALUES clause or query are associated with the explicit or implicit
column list left-to-right.
</quote from docs>

So it seems that the association between columns is based on order, not
on name.

Ray.

[1] http://www.postgresql.org/docs/8.3/static/sql-insert.html


------------------------------------------------------------------
Raymond O'Donnell, Director of Music, Galway Cathedral, Ireland
rod@iol.ie
Galway Cathedral Recitals: http://www.galwaycathedral.org/recitals
------------------------------------------------------------------

Re: column "id" is of type integer but expression is of type character

From
"Andrus"
Date:
> There isn't one. That's not how SQL works. You need to know what columns
> your tables have.
>
> If you want to update the primary key just do something like:
>
> INSERT INTO t1 SELECT * FROM t2;
> UPDATE t1 SET id = DEFAULT;
>
> Although if you don't know what your columns are called I can't see how
> you can figure out that you have a single-column pkey with
> auto-incrementing default.

I know most column names.
Customer can add few columns to tables which are not known to me at design
time.

The command

 INSERT INTO t1 SELECT * FROM t2;

causes primary key violation since t2 is subset of t1 and thus has primary
key values which are already present in t1.
So update is not possible.
Only way I see is to generate script dynamically at runtime containing all
columns excluding id column:

INSERT INTO t1 ( c1, c2, ..., cn )
SELECT c1,c2,  ...., cn
FROM t2;

or

INSERT INTO t1 ( id, c1, c2, ..., cn )
SELECT DEFAULT, c1,c2,  ...., cn
FROM t2;

in this case id column is populated automatically from sequence.
This is very ugly solution since requires dynamic script creation from pg
metadata instead of writing simple query.

Andrus.


Re: column "id" is of type integer but expression is of type character

From
"Andrus"
Date:
Ray,

> I don't think you can - here's what the docs[1] for INSERT say:
>
> <quote from docs>
> The target column names can be listed in any order. If no list of column
> names is given at all, the default is all the columns of the table in
> their declared order; or the first N column names, if there are only N
> columns supplied by the VALUES clause or query. The values supplied by
> the VALUES clause or query are associated with the explicit or implicit
> column list left-to-right.
> </quote from docs>
>
> So it seems that the association between columns is based on order, not
> on name.

Solution seems to force id column to be last column in table.
In this case drop column id drops last columns and insert should work.

Any idea how to force id to be last column in table ?
Is it possible to create updatable view where id is last column ?

Andrus.


Re: column "id" is of type integer but expression is of type character

From
Richard Huxton
Date:
Andrus wrote:
>> There isn't one. That's not how SQL works. You need to know what columns
>> your tables have.
>>
>> If you want to update the primary key just do something like:
>>
>> INSERT INTO t1 SELECT * FROM t2;
>> UPDATE t1 SET id = DEFAULT;
>>
>> Although if you don't know what your columns are called I can't see how
>> you can figure out that you have a single-column pkey with
>> auto-incrementing default.
>
> I know most column names.
> Customer can add few columns to tables which are not known to me at
> design time.

I'm confused now.

You've defined a table with columns (id, c1, c2, c3) and the customer
adds columns (c4, c5) - so far so good. You now want to send out some
updates to the customer - ok.

But - you're supplying the customer with values for (c4,c5) even though
you don't know what the columns are for, their types or their names? How?

If you're only supplying values for your columns then you could just
name them.

> The command
>
> INSERT INTO t1 SELECT * FROM t2;
>
> causes primary key violation since t2 is subset of t1 and thus has
> primary key values which are already present in t1.
> So update is not possible.

Ah, t1 isn't the final table, it's an empty temporary table that you are
importing into. That lets you do whatever tidying to need to before
inserting to the "live" table.

--
  Richard Huxton
  Archonet Ltd