Unable to INSERT between tables using ST_GeomFromText - postgresql

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;

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;

Insert a string into a bytea column

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);

Unable to insert data into postgres table from a remote database connection

I am trying to insert data into a postgres table from a remote database table. I have written the following query for this purpose but I am getting following error.
'[Code: 0, SQL State: 42601] ERROR: syntax error at or near "table"
Position: 13 [Script position: 141 - 146]'
create table clintrial_EP_map.lead_sponsors (row_id SERIAL, lead_sponsors character varying)
insert into table clintrial_ep_map (lead_sponsors)
( select
*
from
dblink('dbname=x user=x host=x password=x port = x',
'
SELECT
distinct bm_dimt_clinical_trial.lead_sponsor
FROM
dwh_prod.bm_dimt_clinical_trial
where dataset_version_id = xx and lead_sponsor_class = ''xx''
'
) as ls (
lead_sponsor character varying
)
)
;
Please see, the following query is giving me desired output.
select
*
from
dblink('dbname=x user=x host=x password=x port = x',
'
SELECT
distinct bm_dimt_clinical_trial.lead_sponsor
FROM
dwh_prod.bm_dimt_clinical_trial
where dataset_version_id = xx and lead_sponsor_class = ''xx''
'
) as ls (
lead_sponsor character varying
)
;
I am not able to find a syntax error near 'table' in my insert query. Any suggestions here will be really helpful.
Thanks
Your query has two issues.
First: Create table is not ending with ; i am hoping that is typo and Second: Your insert statement is referring to schema name instead of schema qualified table name. And also using keyword 'table' in insert statment which is not required. So your correct query will be
create table clintrial_EP_map.lead_sponsors (row_id SERIAL, lead_sponsors character varying);
and
insert into clintrial_EP_map.lead_sponsors (lead_sponsors)
( select * from
dblink('dbname=x user=x host=x password=x port = x',
'SELECT
distinct bm_dimt_clinical_trial.lead_sponsor
FROM
dwh_prod.bm_dimt_clinical_trial
where dataset_version_id = xx and lead_sponsor_class = ''xx''
'
) as ls (lead_sponsor character varying)
);

PostgresQL: Find array length of output from ARRAY_AGG()

How do I count the number of distinct elements in an array object, created by ARRAY_AGG() in PostgresQL? Here's a toy example for discussion purposes:
SELECT ARRAY_AGG (first_name || ' ' || last_name) actors
FROM film
I have tried ARRAY_LENGTH(), LENGTH(), etc., like so:
SELECT ARRAY_LENGTH(a.actors)
FROM (SELECT ARRAY_AGG (first_name || ' ' || last_name) actors
FROM film) a;
But I get an error:
function array_length(integer[]) does not exist
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Position: 208
So I tried (2):
SELECT ARRAY_LENGTH( CAST(COALESCE(a.actors, '0') AS integer) )
FROM (SELECT ARRAY_AGG (first_name || ' ' || last_name) actors
FROM film) a;
but I get the error:
malformed array literal: "0"
Detail: Array value must start with "{" or dimension information.
Position: 119
the function array_length(anyarray, int) require two elements, array and dimension for example:
Select array_length(array[1,2,3], 1);
Result:
3
If you are only dealing with a single dimension array, cardinality() is easier to use:
SELECT cardinality(ARRAY_LENGTH(a.actors))
FROM (
SELECT ARRAY_AGG (first_name || ' ' || last_name) actors
FROM film
) a;

Returning empty data from dynamic pivot is there is no data

Code below from how to preserve column names on dynamic pivot is used to create dynamic pivot table.
If source table contains no data, sql error occurs since create table column list end with comma (there are no pivot columns).
How to fix this so that empty table is returned ?
To reproduce, remove insert commands
insert into sales values ( '2016-1-1', 'Ø 12.3/3mm', 2);
insert into sales values ( '2016-1-1', '+-3,4%/3mm', 52);
insert into sales values ( '2016-1-3', '/3,2m-', 246);
from code.
testcase:
create temp table sales ( saledate date, productname char(20), quantity int );
insert into sales values ( '2016-1-1', 'Ø 12.3/3mm', 2);
insert into sales values ( '2016-1-1', '+-3,4%/3mm', 52);
insert into sales values ( '2016-1-3', '/3,2m-', 246);
do $do$
declare
voter_list text;
begin
create temp table myyk on commit drop as
select saledate as kuupaev,
format ('"%s"', replace (upper(productname), ' ', '')) as tootjakood,
sum(quantity)::int as kogus
from sales
group by 1,2
;
drop table if exists pivot;
voter_list := (
select string_agg(distinct tootjakood, ' ' order by tootjakood) from myyk
);
execute(format('
create table pivot (
kuupaev date,
%1$s
)', (replace(voter_list, ' ', ' integer, ') || ' integer')
));
execute (format($f$
insert into pivot
select
kuupaev,
%2$s
from crosstab($ct$
select
kuupaev,tootjakood,kogus
from myyk
order by 1
$ct$,$ct$
select distinct tootjakood
from myyk
order by 1
$ct$
) as (
kuupaev date,
%4$s
);$f$,
replace(voter_list, ' ', ' + '),
replace(voter_list, ' ', ', '),
'',
replace(voter_list, ' ', ' integer, ') || ' integer' -- 4.
));
end; $do$;
select * from pivot;
Postgres 9.1 is used.
Insert an exception handler at the bottom of the DO block body. You can silently ignore errors and create dummy pivot table:
...
exception
when others then
drop table if exists pivot;
create table pivot ("No data" text);
end; $do$;
or raise an exception with your own error message:
...
exception
when others then
drop table if exists pivot;
raise exception 'There is no data in the source dataset.'
end; $do$;
You can also use if-then-else statement:
...
drop table if exists pivot;
if (select count(*) from myyk) > 0 then
voter_list := (
select string_agg(distinct tootjakood, ' ' order by tootjakood) from myyk
);
...
...
else
create table pivot ("No data" text);
end if;
end; $do$;