Insert a string into a bytea column - postgresql

I want to insert text data into a Postgres bytea column using the concat function or the || operator. I am getting an error
column "name" is of type bytea but expression is of type text
create table test(
name bytea
);
insert into test(name) values(concat('abac-' , 'test123'));
insert into test(name) values('aa' || 'bb');
I am executing the insert inside a stored procedure. If want to add the argument like
(concat('abac-' , row.name , 'test123'));
How do I do it?

Perform a type cast after concatenating the values:
INSERT INTO test (name)
VALUES (CAST('abac-' || row.name || 'test123' AS bytea));
Note: The difference between || and concat is how they behave with NULLs.

You need to cast both strings to bytea, for example:
insert into test(name) values('aa'::bytea || 'bb'::bytea);

Related

create postgresql generated column from multiple jsonb columns

How to combine multiple jsonb columns into a generated column
For single column the following statement works
alter table r
add column txt TEXT GENERATED ALWAYS as (
doc->'contact'->>'name'
) stored;
I tried the following statement without success,
SQL Error [42883]: ERROR: operator does not exist: text -> unknown
alter table r
add column txt TEXT GENERATED ALWAYS as (
doc->'contact'->>'name' || ' ' || doc->'contact'->>'phone'
) stored;
Answer:
alter table r
add column txt TEXT GENERATED ALWAYS as (
(doc->'contact'->>'name') || ' ' || (doc->'contact'->>'phone')
) stored;

Check if value is not null and not empty in a select query

I have created a function in Postgresql and specified the returned type as TABLE (id uuid, data boolean).
This is the code that I have tried:
BEGIN
RETURN QUERY SELECT table.id, (table.data <> '') as data FROM table;
END
But it will return NULL for "data" when data is NULL in the table. I was expecting it to return FALSE.
Data column is storing a JSON and I am trying to check if the stored value is not null and not empty
How can I make this code work?
Use is distinct from to use a null-safe comparison:
SELECT table.id, table.data is distinct from '' as data
FROM table;
Another option is to treat an empty string like null:
SELECT table.id, nullif(table.data, '') is not null as data
FROM table;

Declare a column of type 'not-null-string' array in PostgreSQL

Using PostgreSQL 9.6 I can create a column with type 'not-null-array of string' with:
CREATE TABLE example (
foo TEXT[] NOT NULL
);
but this allows the elements to be null, i.e I can do:
INSERT INTO example VALUES('{NULL}')
Is there a way to instead create a column with type 'not-null-array of not-null-string'? I'd like something like this:
CREATE TABLE example (
foo (NOT NULL TEXT)[] NOT NULL
);
but it's not syntactically valid. Is there a valid way to express this?
Simpler since pg 9.5, with the addition of array_position()
CREATE TABLE example (
foo TEXT[] NOT NULL check (array_position(foo, null) is null)
);
You might also want to check for an empty array:
CREATE TABLE example (
foo TEXT[] NOT NULL check (foo <> '{}' and array_position(foo, null) is null)
);
Use the function:
create or replace function are_elements_not_null(arr anyarray)
returns boolean language sql immutable
as $$
select bool_and(elem is not null)
from unnest(arr) as elem
$$;
in a check constraint:
create table example(
foo text[] check(are_elements_not_null(foo))
);
insert into example values
(array[null]);
ERROR: new row for relation "example" violates check constraint "example_foo_check"
DETAIL: Failing row contains ({NULL}).
Note that the column still may be null or may contain an empty array. If you want to exclude these cases expand the definition in the way:
create table example(
foo text[] check(are_elements_not_null(foo) and foo <> '{}') not null
);

Unable to INSERT between tables using ST_GeomFromText

I'm trying to insert point geometry values and other data from one table to another table.
-- create tables
create table bh_tmp (bh_id integer, bh_name varchar
, easting decimal, northing decimal, ground_mod decimal);
create table bh (name varchar);
SELECT AddGeometryColumn('bh', 'bh_geom', 27700, 'POINT',3);
-- popualte bh_tmp
insert into bh_tmp values
(1,'C5',542945.0,180846.0,3.947),
(3,'B24',542850.0,180850.0,4.020),
(4,'B26',543020.0,180850.0,4.020);
-- populate bh from bh_tmp
insert into bh(name, bh_geom) SELECT
bh_name,
CONCAT($$ST_GeomFromText('POINT($$, Easting, ' ', Northing, ' '
, Ground_mOD, $$)', 27700)$$);
FROM bh_tmp;
Gives this error:
ERROR: parse error - invalid geometry
SQL state: XX000
Hint: "ST" <-- parse error at position 2 within geometry
I can't see anything wrong with the ST_GeomFromText string that I've specified. But I can populate table bh if I insert rows 'manually', e.g.:
INSERT INTO bh (name, bh_geom)
VALUES ('C5' ST_GeomFromText('POINT(542945.0 180846.0 3.947)', 27700));
What am I doing wrong?
First of all, there is a misplaced semicolon after CONCAT(...);
And you can't concatenate the function name itself into the string:
INSERT INTO bh(name, bh_geom)
SELECT bh_name
, ST_GeomFromText('POINT(' || concat_ws(' ', easting, northing, ground_mod) || ')'
, 27700)
FROM bh_tmp;
Or, since you have values already (not text), you could use ST_MakePoint() and ST_SetSRID():
ST_SetSRID(ST_MakePoint(easting, northing, ground_mod), 27700)
Should be faster.
Npgsql parameterized query output incompatible with PostGIS
You're getting that error because the output of the CONCAT function is text, and your bh_geom column is geometry, so you're trying to insert text into geometry. This will work:
INSERT INTO bh(name, bh_geom) SELECT
bh_name,
ST_GeomFromText('POINT('
|| easting|| ' '
|| Northing
|| ' '
|| Ground_mOD
|| ')', 27700)
FROM bh_tmp;

postgresql use column name value when quoted with single quotes

I'm trying to update hstore key value with another table reference column. Syntax as simple as
SET misc = misc || ('domain' => temp.domain)
But I get error because everything in parenthesis should be quoted:
SET misc = misc || ('domain=>temp.domain')::hstore
But this actually inserts temp.domain as a string and not its value. How can I pass temp.domain value instead?
You can concatenate text with a subquery, and cast the result to type hstore.
create temp table temp (
temp_id integer primary key,
domain text
);
insert into temp values (1, 'wibble');
select ('domain => ' || (select domain from temp where temp_id = 1) )::hstore as key_value
from temp
key_value
hstore
--
"domain"=>"wibble"
Updates would work in a similar way.