Ambiguous plpgsql query error with insert with select - postgresql

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;

Related

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

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 ...

Postgresql function table name parameter

I have n tables sharing a least one column name ("Date"), I want to create a function which can make a
select column1, column2, ..., columnx from myfunction('table_name','date_value')
First, tried with just table name parameter (excerpt from another post on this website) :
CREATE OR REPLACE FUNCTION test(_tbl regclass, OUT result integer) AS
$func$
BEGIN
EXECUTE format('SELECT (EXISTS (SELECT FROM %s))::int', _tbl)
INTO result;
END
$func$ LANGUAGE plpgsql;
and called with SELECT test('"vDxi"'); but the result is :
ERROR: syntax error at or near "FROM"
LINE 1: SELECT (EXISTS (SELECT FROM "vDxi"))::int
^
QUERY: SELECT (EXISTS (SELECT FROM "vDxi"))::int
CONTEXT: PL/pgSQL function test(regclass) line 3 at EXECUTE statement
SQL state: 42601
Since I'm a real newbie in PLSQL, I don't know where the error is (tried a SELECT * ... with no success).
And the calling query does not permit me to select column names, if I can make it working...

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

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.

How to get function parameter lists (so I can drop a function)

I want to get the SQL to drop a function in PostgreSQL. I write DROP FUNCTION and a get function name from pg_proc. That is not problem. However if I leave blank parameters it will not drop the function.
I checked the manual and there is written then I have to identify the function with its parameters to drop it, eg DROP FUNCTION some_func(text,integer) not just DROP FUNCTION some_func.
Where can I find the parameters? In the function's row on in the pg_proc table there is no parameters. So how can I get the SQL to drop the function?
Postgres has a dedicated function for that purpose. Introduced with Postgres 8.4. The manual:
pg_get_function_identity_arguments(func_oid) ... get argument list to identify a function (without default values) ...
pg_get_function_identity_arguments returns the argument list
necessary to identify a function, in the form it would need to appear
in within ALTER FUNCTION, for instance. This form omits default values.
Using that (and format(), introduced with Postgres 9.1), the following query generates DDL statements to drop functions matching your search terms:
SELECT format('DROP %s %I.%I(%s);'
, CASE WHEN p.proisagg THEN 'AGGREGATE' ELSE 'FUNCTION' END
, n.nspname
, p.proname
, pg_catalog.pg_get_function_identity_arguments(p.oid)
) AS stmt
FROM pg_catalog.pg_proc p
JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE p.proname = 'dblink' -- function name
-- AND n.nspname = 'public' -- schema name (optional)
-- AND pg_catalog.pg_function_is_visible(p.oid) -- function visible to user
ORDER BY 1;
The system catalog pg_proc changed in Postgres 11. proisagg was replaced by prokind, true stored procedures were added. You need to adapt. See:
How to drop all of my functions in PostgreSQL?
Returns:
stmt
---------------------------------------------------
DROP FUNCTION public.dblink(text);
DROP FUNCTION public.dblink(text, boolean);
DROP FUNCTION public.dblink(text, text);
DROP FUNCTION public.dblink(text, text, boolean);
Found four matches in the example because dblink uses overloaded functions.
Run DROP statements selectively!
Alternatively, you can use the convenient cast to the object identifier type regprocedure which returns a complete function signature including argument types:
-- SET LOCAL search_path = ''; -- optional, to get all names schema-qualified
SELECT format('DROP %s %s;'
, CASE WHEN proisagg THEN 'AGGREGATE' ELSE 'FUNCTION' END
, oid::regprocedure
) AS stmt
FROM pg_catalog.pg_proc
WHERE proname = 'dblink' -- function name
ORDER BY 1;
In Postgres 10, you can delete a function without knowing the list of parameters, as long as it is unique in its schema.
drop function if exists some_func;
See the docs.
Of course, if you have overloaded the function (or are trying to delete over multiple schemas), you will still need the above answers.
use pgadminIII and direct access to function list and right click it then select delete
If you are working on an old previous version of postgres, for which pg_get_function_identity_arguments(func_oid) doesn't exist, I create my own function get the parameters from the function, you only need to pass the oid for the function, you need to deploy the function below to your postgres db.
CREATE OR REPLACE FUNCTION public.getFunctionParameter(functionOid oid)
RETURNS text AS
$BODY$
declare
t_paras text;
paras oid[];
res text :='(';
begin
select proargtypes into t_paras from pg_proc where oid=functionOid;
if t_paras is null or t_paras='' then
return '()';
else
paras:=string_to_array(t_paras,' ');
for i in array_lower(paras,1) .. array_upper(paras,1)
loop
raise notice 'para is %',paras[i];
select format_type(paras[i]::oid,NULL) into t_paras;
res:=res||t_paras||',';
end loop;
res:=substring(res from 1 for char_length(res)-1);
res:=res||')';
return res;
end if;
end
$BODY$
LANGUAGE plpgsql ;
The function below will list the function name and parameters, change the schema name if you want to get function under some other schema, I am using public for example
SELECT n.nspname||'.'||p.proname||public.getFunctionParameter(p.oid)
FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE n.nspname='public'
You will the result like below
1 "public.getfunctionparameter(integer,text)"
2 "public.getfunctionparameter(oid)"