Re: Problem with upper() in select statement - Mailing list pgsql-general

From Tom Lane
Subject Re: Problem with upper() in select statement
Date
Msg-id 1450.960829237@sss.pgh.pa.us
Whole thread Raw
In response to Problem with upper() in select statement  (John Cochran <jdc@fiawol.org>)
List pgsql-general
John Cochran <jdc@fiawol.org> writes:
>> John Cochran <jdc@fiawol.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

pgsql-general by date:

Previous
From: Tom Lane
Date:
Subject: Re: Problem with upper() in select statement
Next
From: "I'm Your Handiman -Online-"
Date:
Subject: (no subject)