I would like to do something like :
update cli_pe set nm_cli_espace_client = 9 || nm_cli_espace_client
where nm_cli_pe = 7006488
nm_cli_espace_client is numeric(0,8).
How to make it easy?
UPDATE cli_pe
SET nm_cli_espace_client = '9' || CAST(nm_cli_espace_client AS text)
WHERE nm_cli_pe = 7006488;
If you need a resulting number, then CAST back the result:
... SET nm_cli_espace_client =
CAST('9' || CAST(nm_cli_espace_client AS text) AS integer)
Your question is identical to this one: concat two int values in postgresql
Prefixing a digit onto a number can be done by textual concatenation, as @vyegorov has demonstrated, but it's also easily done as a mathematical operation.
Edit: Easily, but really not quickly in PostgreSQL. Even though this approach is much faster when programming in languages like C and Java for integer types, it seems to be quite a bit slower in SQL under PostgreSQL when working with an int, and immensely slower for NUMERIC. Probably function call overhead for ints, and the general slowness of numeric maths when working with numeric. In any case, you're better off concatenating as strings per @vyegorov's answer.
I'll preserve the rest of the answer for a laugh; it's a really good example of why you should test multiple approaches to a problem.
A mathematical approach is:
nm_cli_espace_client = 9*pow(10,1+floor(log(nm_cli_pe))) + nm_cli_espace_client;
There's probably a smarter way than that. What it does is basically produces the power of 10 with one more digit than the number being added to and multiplies the input by it.
regress=# SELECT (pow(10,1+floor(log( 7006488 ))) * 9) + 7006488;
?column?
---------------------------
97006488.0000000000000000
(1 row)
I'd love to have the smarter way to do this mathematically pointed out to me; I'm sure there is one.
Anyhow, it turns out you don't want to do this in PostgreSQL. With integer types it's a bit slower:
regress=# explain analyze select ('9'||x::text)::int from testtab;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------
Seq Scan on testtab (cost=0.00..26925.00 rows=1000000 width=4) (actual time=0.026..293.120 rows=1000000 loops=1)
Total runtime: 319.920 ms
(2 rows)
vs
regress=# explain analyze select 9*pow(10,1+floor(log(x)))+x from testtab;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------
Seq Scan on testtab (cost=0.00..34425.00 rows=1000000 width=4) (actual time=0.053..443.134 rows=1000000 loops=1)
Total runtime: 470.587 ms
(2 rows)
With NUMERIC types the text approach doesn't change much:
regress=# explain analyze select ('9'||x::text)::int from testtab;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------
Seq Scan on testtab (cost=0.00..17467.69 rows=579675 width=32) (actual time=0.039..368.980 rows=1000000 loops=1)
Total runtime: 396.376 ms
(2 rows)
but the maths based approach is horrifyingly slow even if I convert the NUMERIC to int after taking the logarithm. Clearly taking the logarithm of a NUMERIC is slow - not surprising, but I didn't expect it to be this slow:
regress=# explain analyze select 9*pow(10,1+floor(log(x)::int))+x from testtab;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------
Seq Scan on testtab (cost=0.00..18916.88 rows=579675 width=32) (actual time=0.253..86740.383 rows=1000000 loops=1)
Total runtime: 86778.511 ms
(2 rows)
The short version: Do it by text concatenation. In (PostgreSQL) SQL the maths-based approach is more than 200 times slower for NUMERIC, and about 50% slower on integers. It's a handy trick for languages where integer maths is cheap and string manipulation / memory allocation is expensive, though.