Re: Problem with upper() in select statement

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: John Cochran <jdc(at)fiawol(dot)org>
Cc: pgsql-general(at)postgreSQL(dot)org
Subject: Re: Problem with upper() in select statement
Date: 2000-06-12 17:00:37
Message-ID: 1450.960829237@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

John Cochran <jdc(at)fiawol(dot)org> writes:
>> John Cochran <jdc(at)fiawol(dot)org> writes:
>>>> Why isn't the upper() function working in the first query?
>>
>> Odd. You aren't by some chance working in a non-ASCII locale where
>> "upper('Boulevard')" yields something besides 'BOULEVARD', are you?

> Nope, using the standard locale. Here is a short session to
> prove that upper() is working like it should.

Oh, never mind. I was busy looking for complicated answers, but
actually the answer is simple: char(n) and text are not the same
thing because they have different ideas about the significance of
trailing blanks.

create table abbreviation(word char(15) not null);

insert into abbreviation values('BOULEVARD');

select * from abbreviation where word = 'BOULEVARD';
word
-----------------
BOULEVARD
(1 row)

The above works because the unknown-type literal 'BOULEVARD' is promoted
to char(n) type, and then char(n) vs. char(n) does what you want because
it regards trailing spaces as insignificant: 'BOULEVARD ' is equal
to 'BOULEVARD' under char(n) rules.

But 'BOULEVARD ' != 'BOULEVARD' under varchar(n) or text rules.
Thus this doesn't match:

select * from abbreviation where word = 'BOULEVARD'::text;
word
------
(0 rows)

because the type ordering is that char(n) promotes to text not vice
versa, so you get a text equality comparison here. Same result with

select * from abbreviation where word::text = 'BOULEVARD';
word
------
(0 rows)

and more to the point, upper() is a function that yields type text,
so:

select * from abbreviation where word = upper('Boulevard');
word
------
(0 rows)

You could make it work by coercing upper()'s result back to char(n),
so that char(n) equality is used:

select * from abbreviation where word = upper('Boulevard')::char;
word
-----------------
BOULEVARD
(1 row)

but on the whole my advice is that you are using the wrong datatype for
this table. Variable-length strings should be represented by varchar(n)
or text. Fixed-width char(n) is appropriate for fixed-length strings
like state abbreviations.

> BTW, why doesn't PostgreSQL have a SYSDUMMY table or something like it
> (the way Oracle or IBM's DB2 have).

Don't need it, since we don't require a FROM clause.

regression=# select upper('Boulevard');
upper
-----------
BOULEVARD
(1 row)

regards, tom lane

Browse pgsql-general by date

  From Date Subject
Next Message I'm Your Handiman -Online- 2000-06-12 17:04:27 Re: (no subject)
Previous Message I'm Your Handiman -Online- 2000-06-12 16:59:44 (no subject)