Strange "Column reference 'xxx' is ambiguous" for single-table query - postgresql

Inside a function there is a simple single table query:
create function myfunction(...)
LANGUAGE 'plpgsql'
...
return query select 1, variable1, xtcol1 from xtable where xtcolx=variablex;
...
when running it select myfunction(...) got
ERROR: column reference "xtcol1" is ambiguous
LINE 1: select 1, variable1, xtcol1 from xtable ...
^
DETAIL: It could refer to either a PL/pgSQL variable or a table column.
QUERY: ...
CONTEXT: PL/pgSQL function myfunction(integer,character varying) line 20 at RETURN QUERY
SQL state: 42702
Surely I can fix it by prefix every column in the query, but it makes no sense because I named all columns with a unique table abbreviation. For example xtable abbreviation is xt so there is no ambiguous columns across the board. It works out well in all other functions except this. Postgre v12

The correct way is to qualify the ambiguous name with either the table (alias) or the function name:
SELECT xtable.xtcol1 FROM xtable

so error message :
DETAIL: It could refer to either a PL/pgSQL variable or a table column.
shows you are passing a parameter with the same name as your column,
so how about you escape it :
select 1, variable1, "xtcol1" from xtable ...

Related

error raise when use within GROUP with string_agg in postgresql

My query in postgresql 10, raises an error when it uses within GROUP clause
ERROR: function string_agg(character varying, unknown, integer) does
not exist
I have tables at and atrelation. at has unique id and description while atrelation stores multiple transaction with code of related at and transaction line id. for example
product row with id 6 has a column name tag has value service5% and contco4.5%
product row with id 5 has tag value service5%
I need to show 2-rows i.e row 6 and 5.
row 5 show the column tag value 'service5% and contco4.5% '
row 6 show the column tag value 'service5%'
select atrelation.id,
string_agg(at.description, ' and ' ) within GROUP (ORDER BY atrelation.id ) as tag1
from at, atrelation
where atrelation.id = atrelation.atid
group by atrelation.id
order by atrelation.id desc;
above query raise following error,
ERROR: function string_agg(character varying, unknown, integer) does not exist
LINE 1: select atrelation.purchase_order_line_id as id, string_agg(a...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
********** Error **********
ERROR: function string_agg(character varying, unknown, integer) does not exist
SQL state: 42883
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Character: 49
You need to put the ORDER BY into the function call and remove the WITHIN GROUP part:
string_agg(at.description, ' and ' ORDER BY atrelation.id) as tag1

How to insert array of complex types into a table

I have a complex type defined as:
create type TP_IdAndVer AS
(
id uuid,
ver integer
);
And I'd like to insert an array of them into a temporary table (so I can join on a composite key).
This is what I have so far but it doesn't work:
DO $$
declare fred TP_IdAndVer[];
BEGIN
drop table if exists tmpTable;
fred := array[ ('034892e4-6137-440c-bb62-b609b60575aa'::uuid, 1), ('034892e4-6137-440c-bb62-b609b60575aa'::uuid, 2) ];
create temporary table temptbl_ids_and_vers(id uuid, ver integer)
on commit drop;
-- I want to insert each row of fred as a row into my temp table. But how??
insert into temptbl_ids_and_vers(id, ver) values (fred);
CREATE TEMPORARY TABLE tmpTable AS
select * from temptbl_ids_and_vers;
END $$;
select *
from tmpTable;
I get this error:
ERROR: INSERT has more target columns than expressions
LINE 1: insert into temptbl_ids_and_vers(id, ver) values (fred)
^
QUERY: insert into temptbl_ids_and_vers(id, ver) values (fred)
CONTEXT: PL/pgSQL function inline_code_block line 15 at SQL statement
********** Error **********
ERROR: INSERT has more target columns than expressions
SQL state: 42601
Context: PL/pgSQL function inline_code_block line 15 at SQL statement
If someone could point me to the right syntax to use it would be a big help. I guess I could loop through each element of the array inserting each row individually, but that feels a bit hacky.
Alternatively, is there a way of passing a table to a stored proc? This would get around what I'm trying to achieve at the moment since I could just a pass a table in without needing to worry about arrays.
Thanks,
Adam.
INSERT INTO temptbl_ids_and_vers(id, ver)
SELECT *
FROM UNNEST(fred) AS q(id, ver)
insert into temptbl_ids_and_vers(id, ver)
select id, ver
from unnest(fred) u

String Manipulation throws error while Inserting into PostgreSql Jsonb Column

I have the following code, to insert data into my table res(ID bigserial,
Results jsonb not null). I want to insert data so that 'Display' column always has the 'i' appended to it, so that every row has a different value for 'Display' Column.
DO $$
declare cnt bigint;
BEGIN
FOR i IN 1..2 LOOP
INSERT INTO res (Results)
VALUES ('{"cid":"CID1","Display":"User One'|| i || '","FName":"Userfff","LName":"One"}');
INSERT INTO res (Results)
VALUES ('{"cid":"CID1","Display":"User One'|| i || '","FName":"Userfff","LName":"One"}');
INSERT INTO res (Results)
VALUES ('{"cid":"CID1","Display":"User One'|| i || '","FName":"Userfff","LName":"One"}');
END LOOP;
END;
$$
LANGUAGE plpgsql;
However, when I run this code, I get the following error:
ERROR: column "results" is of type jsonb but expression is of type text
LINE 2: VALUES ('{"cid":"CID1","Display":"User One'|| i ...
^
HINT: You will need to rewrite or cast the expression.
How should I modify my query so that the query runs successfully?
No need for a loop or even PL/pgSQL.
You can generate any number of rows using generate_series()
To put a value into a string I prefer to use format() as that makes dealing with strings a lot easier:
insert into res(results)
select format('{"cid":"CID1","Display":"User One %s","FName":"Userfff","LName":"One"}', i::text)::jsonb
from generate_series(1,5) g(i);
The second parameter to the format() function will be put where the %s in the first parameter.
The above inserts 5 rows each with a different value for display. This is what you stated in your question. Your sample code however inserts a total of 6 rows where 3 rows have the same value for display.

Dynamically naming a table in postgresql function

So I have a table that for some design reasons cannot use a foreign key to map to other entities. So I am working on a function that is called to safely delete entries from the media table. As it stands at the moment I have written the function to have basic functionality using this resource as my guide on how to dynamically insert a table name into a query (http://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN). As it stands my query is written as follows
DECLARE
rows_returned numeric;
is_media boolean;
BEGIN
DELETE FROM solo_media WHERE entity_id = row_to_delete;
EXECUTE "DELETE FROM $1 WHERE id = $2;" INTO rows_returned USING table_name, row_to_delete;
END;
And when it is ran (with table_name and row_to_delete being parameters being passed in) I get the error
ERROR: column "DELETE FROM $1 WHERE id = $2;" does not exist
LINE 1: SELECT "DELETE FROM $1 WHERE id = $2;"
^
QUERY: SELECT "DELETE FROM $1 WHERE id = $2;"
CONTEXT: PL/pgSQL function "safe_del" line 7 at EXECUTE statement
when calling it with
SELECT safe_del(tableName, rowNumber);
As Milen A. Radev pointed out I was using the wrong characters to identify my string, I switched it over to dollar escaped strings, and resolved the issues.

Ambiguous plpgsql query error with insert with select

So I got this error, I put the alias at num_documento (codigo "a.num_documento") but Postgres says num_documento doesn't exist.
ERROR: la referencia a la columna �num_documento� es ambigua
Where: PL/pgSQL function "insertar_carga_giros"
line 145 at sentencia SQ???
--Query function insertar_carga_giros
insert into bdsinc."codigo"(num_documento,id_tip_dcto,id_deudor)
select distincta.num_documento,b.id_tip_dcto,b.id_deudor
from bdsinc."carga" a
left join bdsinc."tb_deudor" b
on a.num_documento=b.num_dcto
and a.id_tip_dcto=b.id_tip_dcto
where b.id_deudor is not null and validacion=1;
How can I do an insert with select join inside in PostgreSQL?
This INSERT statement looks ok. You probably defined a variable name num_documento in your function that conflicts with the column name. Maybe an IN parameter?
Try renaming that variable.
Assuming that you actually have:
select distinct a.num_documento,b.id_tip_dcto,b.id_deud;