234

I have two string columns a and b in a table foo.

select a, b from foo returns values a and b. However, concatenation of a and b does not work. I tried :

select a || b from foo

and

select  a||', '||b from foo

Update from comments: both columns are type character(2).

6
  • ... or another text type? Commented Nov 13, 2013 at 0:31
  • 1
    @acfrancis Since OP says concatenate I doubt that he's dealing with numeric types, though PostgreSQL would take care of some of them as well. See here:postgresql.org/docs/9.1/static/functions-string.html Commented Nov 13, 2013 at 0:34
  • 1
    Yes, these columns are character(2). "+" does not work - " No operator matches the given name and argument type(s). You might need to add explicit type casts." Commented Nov 13, 2013 at 0:35
  • 1
    What version of PostgreSQL? Here are docs for 9.1: postgresql.org/docs/9.1/static/functions-string.html. See my example: sqlfiddle.com/#!15/d41d8/182 Commented Nov 13, 2013 at 0:38
  • You probably have a syntax error in your query not related to concatenation. Commented Nov 13, 2013 at 0:40

9 Answers 9

371

With string types (including character(2)), the displayed concatenation just works because, quoting the manual:

[...] the string concatenation operator (||) accepts non-string input, so long as at least one input is of a string type, as shown in Table 9.8. For other cases, insert an explicit coercion to text [...]

Bold emphasis mine. The 2nd example select a||', '||b from foo works for any data types because the untyped string literal ', ' defaults to type text making the whole expression valid.

For non-string data types, you can "fix" the 1st statement by casting at least one argument to text. Any type can be cast to text.

SELECT a::text || b AS ab FROM foo;

Judging from your own answer, "does not work" was supposed to mean "returns null". The result of anything concatenated to null is null. If null values can be involved and the result shall not be null, use concat_ws() to concatenate any number of values:

SELECT concat_ws(', ', a, b) AS ab FROM foo;

Separators are only added between non-null values, i.e. only where necessary.

Or concat() if you don't need separators:

SELECT concat(a, b) AS ab FROM foo;

No need for type casts since both functions take "any" input and work with text representations. However, that's also why the function volatility of both concat() and concat_ws() is only STABLE, not IMMUTABLE. If you need an immutable function (like for an index, a generated column, or for partitioning), see:

More details (and why COALESCE is a poor substitute) in this related answer:

Asides

+ (as mentioned in comments) is not a valid operator for string concatenation in Postgres (or standard SQL). It's a private idea of Microsoft to add this to their products.

There is hardly any good reason to use character(n) (synonym: char(n)). Use text or varchar. Details:

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you. The 1st version does not work with null and the 2nd gave me the error for concat_ws: No function matches the given name and argument types. You might need to add explicit type casts.
You did see Postgres 9.1 or later, right? You should have provided your version of Postgres to begin with, in the question. Please update your question with all the requested information, before you come back for anything else.
Thank you, the solution I found works for any Postgres version
SELECT concat(a, b) FROM foo; works for me in Postgres 9.3 when a and b are VARCHARs.
52

The problem was in nulls in the values; then the concatenation does not work with nulls. The solution is as follows:

SELECT coalesce(a, '') || coalesce(b, '') FROM foo;

Comments

33

it is better to use CONCAT function in PostgreSQL for concatenation

eg : select CONCAT(first_name,last_name) from person where pid = 136

if you are using column_a || ' ' || column_b for concatenation for 2 column , if any of the value in column_a or column_b is null query will return null value. which may not be preferred in all cases.. so instead of this

||

use

CONCAT

it will return relevant value if either of them have value

2 Comments

Worked for me. Happily found I could add a space between too: CONCAT(first_name, ' ', last_name)
this should be the right answer because concat accepts null
15

As i was also stuck in this, think i should share the solution that worked best for me. I also think that this is much simpler.

If you use Capitalized table name.

SELECT CONCAT("firstName", ' ', "lastName") FROM "User"

If you use lowercase table name

SELECT CONCAT(firstName, ' ', lastName) FROM user

That's it!. As PGSQL counts Double Quote for column declaration and Single Quote for string, this works like a charm.

1 Comment

If there can be NULL values, this expression produces a leading or trailing space. Typically not what you want. Use concat_ws() instead.
13

CONCAT functions sometimes not work with older postgreSQL version

see what I used to solve problem without using CONCAT

 u.first_name || ' ' || u.last_name as user,

Or also you can use

 "first_name" || ' ' || "last_name" as user,

in second case I used double quotes for first_name and last_name

Hope this will be useful, thanks

1 Comment

if my first name or last name is null then concat value also showing null
0

PHP's Laravel framework, I am using search first_name, last_name Fields consider like Full Name Search

Using || symbol Or concat_ws(), concat() methods

$names = str_replace(" ", "", $searchKey);                               
$customers = Customer::where('organization_id',$this->user->organization_id)
             ->where(function ($q) use ($searchKey, $names) {
                 $q->orWhere('phone_number', 'ilike', "%{$searchKey}%"); 
                 $q->orWhere('email', 'ilike', "%{$searchKey}%");
                 $q->orWhereRaw('(first_name || last_name) LIKE ? ', '%' . $names. '%');
    })->orderBy('created_at','desc')->paginate(20);

This worked charm!!!

Comments

0

Try this

select concat_ws(' ', FirstName, LastName) AS Name from person;

1 Comment

concat_ws(' ', FirstName, LastName) would be much cleaner.
-2

For example if there is employee table which consists of columns as:

employee_number,f_name,l_name,email_id,phone_number 

if we want to concatenate f_name + l_name as name.

SELECT employee_number,f_name ::TEXT ||','|| l_name::TEXT  AS "NAME",email_id,phone_number,designation FROM EMPLOYEE;

1 Comment

What does this answer add over existing answers?
-2

You can also use a pipe for this operation.

Select EmployeeID ,FirstName ||' ' || LastName as Full_Name from Employees
order by EmployeeID

1 Comment

This does not answer the question. Nor does it add anything useful.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.