How can I output the result of PostgreSQL dates function as to_char to french language, for example the output of:
select to_char(current_date, 'Day') ;
should be (a french name for a day):
Mardi
instead of english of day (e.g. Monady)
You would need to set the display of date/time (LC_TIME) to french, and to query not the Day but rather the localizable day TMDay using the TM prefix.
show LC_TIME;
SET LC_TIME = 'French';
select to_char(current_date, 'TMDay') ;
to_char
---------
Mardi
(1 row)
The following works on Ubuntu 16.04 Server, with english language set-up
first we need to add system support for French templating with the command:
sudo locale-gen fr_FR.utf8
then restart postgresql service:
sudo systemctl restart postgresql
then log in to psql
SET LC_TIME = 'fr_FR.utf8';
select to_char(current_date, 'TMDay') ;
to_char
---------
Mardi
(1 row)
Related
As this might have something to do with AWS Lightsail, I've cross posted this question on AWS - Click Here
I'm trying to create a template database using
CREATE DATABASE __edgedbtpl__ OWNER='edgedb' IS_TEMPLATE = TRUE TEMPLATE='template0' ENCODING='UTF8' LC_COLLATE='C' LC_CTYPE='C.UTF-8';
But this fails and gives me the error
ERROR: invalid locale name: "C.UTF-8"
I checked if the PostgreSQL server supports the C.UTF-8 locale, using
SELECT collname FROM pg_collation WHERE lower(replace(collname, '-', '')) = 'c.utf8' LIMIT 1;
which gives me the response
collname
----------
C.utf8
(1 row)
Question
How are the collnames in pg_collation different from SHOW LC_CTYPE and SHOW LC_COLLATE?
SHOW LC_COLLATE and SHOW LC_TYPE responded with en_US.UTF-8 and not C.UTF-8. So how should I identify if a certain locale is supported?
Collation names are identifiers, not string literals in PostgreSQL. Use double quotes instead of single quotes. Also, case and spelling matter, so use "C.utf8".
One of our PostgreSQL 11.4 deployments in Congo uses the CAT timezone (Africa/Kigali +02) and one of our function chokes when trying to convert human-input timestamps to actual TIMESTAMPTZ data.
For example:
SELECT '2019-10-17 00:00:00 CAT'::TIMESTAMPTZ;
ERROR: invalid input syntax for type timestamp with time zone: "2019-10-17 00:00:00 CAT"
LINE 2: SELECT '2019-10-17 00:00:00 CAT'::TIMESTAMPTZ
^
SQL state: 22007
Character: 9
But when I try with CEST (Central European, also +02) it works.
SELECT '2019-10-17 00:00:00 CEST'::TIMESTAMPTZ;
"2019-10-17 00:00:00+02"
Incidentally, converting from epoch to CAT also works
select to_timestamp(1571263200);
"2019-10-17 00:00:00+02"
Version:
"PostgreSQL 11.4 (Ubuntu 11.4-1.pgdg18.04+1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0, 64-bit" on Ubuntu 18.04.2 LTS
For whatever reason, 'CAT' is not valid for input by default, presumably someone felt it was ambiguous or something. You could append the line
CAT 7200 # Central Africa Time
to the file "$SHAREDIR/timezonesets/Default" to make this work.
Or you could create a file "$SHAREDIR/timezonesets/Africa" with the contents:
#INCLUDE Default
#OVERRIDE
CAT 7200 # Central Africa Time
And then set the parameter timezone_abbreviations to 'Africa'.
I am not horologist, you might want to research why CAT is missing before blindly adding it. Also, if you go either of the above routes, you should document it clearly someplace. You will need to repeat the steps you took when you upgrade PostgreSQL, or restore or move your database.
Or, you could preprocess your user input to replace 'CAT' with 'Africa/Kigali'.
Incidentally, converting from epoch to CAT also works
select to_timestamp(1571263200);
"2019-10-17 00:00:00+02"
'CAT' does not appear in your example. So it is not clear what this is an example of.
What is the reason for this query give no results:
SELECT name FROM users WHERE LOWER(name) LIKE LOWER('%после%');
When this works fine:
SELECT name FROM users WHERE LOWER(name) LIKE LOWER('%После%');
Name is 'Последователь'. If i use name like 'Post', then search works fine.
Version: PostgreSQL 11.2 (Ubuntu 11.2-100) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0, 64-bit
Server and db encoding is UTF8. Client encoding is UNICODE.
The lower function works according to the database collation, so the result will vary depending on how your database is defined.
It will work well in this case:
test=# CREATE DATABASE rus TEMPLATE template0
ENCODING UTF8 LC_COLLATE "ru_RU.utf8" LC_CTYPE "ru_RU.utf8";
CREATE DATABASE
test=# \c rus
You are now connected to database "rus" as user "postgres".
rus=# SELECT LOWER('%после%') = LOWER('%После%');
?column?
----------
t
(1 row)
But it won't work with the C collation, because that does not know how to properly lower case cyrillic characters:
rus=# \c test
You are now connected to database "test" as user "postgres".
test=# DROP DATABASE rus;
DROP DATABASE
test=# CREATE DATABASE rus TEMPLATE template0
ENCODING UTF8 LC_COLLATE "C" LC_CTYPE "C";
CREATE DATABASE
test=# \c rus
You are now connected to database "rus" as user "postgres".
rus=# SELECT LOWER('%после%') = LOWER('%После%');
?column?
----------
f
(1 row)
So if you want your query to work well, make sure that you are using a collation that knows how to convert the characters to upper and lower case.
Functions LOWER and UPPER do not work correct if database has wrong locale.
Step-1. View locale of databases in Postgres:
\l
Step-2. View available locales in terminal:
locale -a
or by your language, for example ru:
locale -a | grep ru
Step-3. Use locale name from Step-2(for example ru_RU.utf8) in updating database YOUR_DATABASE_NAME in Postgres:
update pg_database set datcollate='ru_RU.utf8', datctype='ru_RU.utf8' where datname='YOUR_DATABASE_NAME';
or you can create new database with locale:
CREATE DATABASE NEW_DATABASE_NAME TEMPLATE template0 ENCODING UTF8 LC_COLLATE "ru_RU.UTF-8" LC_CTYPE "ru_RU.UTF-8";
PS My macOS has name ru_RU.UTF-8, Ubuntu has name ru_RU.utf8
Look Closer. LIKE statement is sometimes case sensitive. Depens on the program you use
The first statement is :
SELECT name FROM users WHERE LOWER(name) LIKE LOWER('%после%');
while the second is :
SELECT name FROM users WHERE LOWER(name) LIKE LOWER('%После%');
What you seek is
П оследователь
note that in the first statement you wrote with (п) while the second one is (П)
I have a table named contacts
id | name
----+------------------
44 | Aarón
I am trying to execute a query :
select id,name from contacts where name ilike 'Aaro%';
It return (0 rows)
I am trying to search 'o' and also expect to have result include all accent of 'o' like 'ó'.
As I have did some googling and stackoverlfowing I have found that using locale I need to install the collation.
So I have installed the collation in linux by
sudo locale-gen --no-archive de_DE.utf-8
after that I have tried to install collation in the postgresql database.
create collation de (LOCALE='de_DE.utf-8');
collation generated successfully. I have tried to list out this collation by using select * from pg_collation; and it is there.
after doing all this I tried again to get result of all relative accent 'o' by query:
select id,name from contacts where name ilike 'Aaro%';
but again i got (0 rows)
Ultimatly I want the record "Aarón" when I execute above query.
Thanks in Advance.
You can use unaccent module of postgres.
for that you need to install postgresql-contrib in your system. you can install it using below command in debian based linux.
sudo apt-get install postgresql-contrib
after that you can create unaccent in postgres.
postgres_db=# create EXTENSION unaccent;
CREATE EXTENSION
postgres_db=# select name from test where unaccent(name) ilike 'Aaro%';
name
-------
Aarón
(1 row)
Hope this helps!
The extension unaccent is a good solution. If you deal with a small set of characters without ligatures you can alternatively use a simple function like this one for Polish:
create or replace function unaccent_pl(text)
returns text language sql immutable as $$
select translate($1, 'ąćęłńóśźżĄĆĘŁŃÓŚŹŻ', 'acelnoszzACELNOSZZ')
$$;
select unaccent_pl('Zażółć gęślą jaźń');
unaccent_pl
-------------------
Zazolc gesla jazn
(1 row)
Could anybody give an insight on the locale and numeric types behaviour in PostgreSQL? We work with Italian locale. That is comma separation for decimal part. Setting in postgresql.conf
# These settings are initialized by initdb, but they can be changed.
lc_messages = 'it_IT.UTF-8' # locale for system error message
# strings
lc_monetary = 'it_IT.UTF-8' # locale for monetary formatting
lc_numeric = 'it_IT.UTF-8' # locale for number formatting
lc_time = 'it_IT.UTF-8' # locale for time formatting
.. does nothing! It behaves in a quite appropriate way with dates and so, BUT the numeric type remains DOT separated for decimal part.
root#server:~# uname -a
Linux server 2.6.32-36-generic-pae #79-Ubuntu SMP Tue Nov 8 23:25:26 UTC 2011 i686 GNU/Linux
root#server:~# dpkg -l | grep postgresql
ii postgresql-8.4 8.4.9-0ubuntu0.10.04 object-relational SQL database, version 8.4
ii postgresql-client 8.4.9-0ubuntu0.10.04 front-end programs for PostgreSQL (supported)
EDIT
Having problem with implementation of locale in different scopes: db, server script, os and client side. Decided to avoid any locale formatting and use en_EN locale. The locale formatting will be applied only at the moment of output and so.
I quote the manual:
lc_numeric (string)
Sets the locale to use for formatting numbers, for example with the to_char family of functions.
Concerns these type formatting functions. You should be able to reproduce the following demo:
SHOW lc_numeric;
de_AT.UTF-8
SELECT to_number('13,4','999D99')
13.4
SELECT to_char(13.4,'FM999D99')
13,4
SET lc_numeric = 'C';
SELECT to_number('13,4','999D99')
134
SELECT to_char(13.4,'FM999D99')
13.4
RESET lc_numeric;
Template patterns in the manual.
The format of numbers in SQL expressions does not change with locale settings. That would be madness.
On a different note: you are aware that you have to (at least) reload the server after changing postgresql.conf.
pg_ctl reload