PostgreSQL : ERROR: function geta(integer, integer, unknown) does not exist - sql

I am creating a dynamic query generation function which helped me out in my work. The CREATE FUNCTION script parsed successfully but i am not able execute it. While executing the function, it shows an error.
I have tried a lot.
Please look below for code.
CREATE OR REPLACE FUNCTION "public"."GetA" (headcategoriesid int4,cdfid int4,
colName text)
RETURNS varchar AS
$BODY$
DECLARE
sql1 text := 'select string_agg(answer, '','') as HeadName from
' || $3 || 'where cdfid = ' || $2 || ' and headcategoriesid = '|| $1;
BEGIN
-- RETURN QUERY
Execute sql1;
-- 'select string_agg(answer, '','') as HeadName from ' || $3 ||
'where cdfid = ' || $2 || ' and headcategoriesid = '|| $1;
-- RETURN QUERY EXECUTE format(
-- 'select string_agg(answer, '','') as HeadName from %I WHERE
cdfid = %L and headcategoriesid = %L', colName, 7, 96
-- );
END
$BODY$
LANGUAGE plpgsql;
Am using Postgresql 9.2.4

Call function as below:
SELECT "GetA"(7,96,'educationdetails'::text);
when you call the function GetA without ""(quotes) than it will be considerd as geta (small letter). but in your code you are using "" so it is created as GetA.

Related

Problem with PL/SQL anonymous block in an exam

I am working with a code in SQLDeveloper for an exam and I'm having problems with the code. The error shown is
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 7
00000 - "PL/SQL: numeric or value error%s"
*Cause: An arithmetic, numeric, string, conversion, or constraint error
occurred. For example, this error occurs if an attempt is made to
assign the value NULL to a variable declared NOT NULL, or if an
attempt is made to assign an integer larger than 99 to a variable
declared NUMBER(2).
*Action: Change the data, how it is manipulated, or how it is declared so
that values do not violate constraints.
The code I'm using is this one:
VAR RUT_CLIENTE VARCHAR2(15);
EXEC :RUT_CLIENTE:= '12487147-9';
DECLARE
V_NOMBRE VARCHAR2(75);
V_RUN VARCHAR2(50);
V_RENTA VARCHAR2(12);
V_EST_CIVIL VARCHAR2(40);
BEGIN
SELECT
CLI.NOMBRE_CLI || ' ' || CLI.APPATERNO_CLI || ' ' || CLI.APMATERNO_CLI,
TO_CHAR(CLI.NUMRUT_CLI || '-' || CLI.DVRUT_CLI),
TO_CHAR(CLI.RENTA_CLI, '$999G999G999'),
EST.DESC_ESTCIVIL
INTO V_NOMBRE, V_RUN, V_RENTA, V_EST_CIVIL
FROM CLIENTE CLI JOIN ESTADO_CIVIL EST
ON CLI.ID_ESTCIVIL = EST.ID_ESTCIVIL
WHERE CLI.NUMRUT_CLI || '-' || CLI.DVRUT_CLI = :RUT_CLIENTE;
DBMS_OUTPUT.PUT_LINE('DATOS DEL CLIENTE');
DBMS_OUTPUT.PUT_LINE(' ');
DBMS_OUTPUT.PUT_LINE('----------------');
DBMS_OUTPUT.PUT_LINE(' ');
DBMS_OUTPUT.PUT_LINE('Nombre: ' || V_NOMBRE);
DBMS_OUTPUT.PUT_LINE('RUN: ' || V_RUN);
DBMS_OUTPUT.PUT_LINE('Estado Civil: ' || V_EST_CIVIL);
DBMS_OUTPUT.PUT_LINE('Renta: ' || V_RENTA);
END;
What am I doing wrong? Also, I have to make this block run three times, each time having to enter a different RUT_CLIENTE (the equivalent of the Social Security number in Chile) to show different results, so should I use a loop for that?
You can avoid such errors if you will use define your variables using the types from your cursor:
DECLARE
cursor cur(p_RUT_CLIENTE) is
SELECT
CLI.NOMBRE_CLI || ' ' || CLI.APPATERNO_CLI || ' ' || CLI.APMATERNO_CLI as col_nombre,
TO_CHAR(CLI.NUMRUT_CLI || '-' || CLI.DVRUT_CLI) as col_run,
TO_CHAR(CLI.RENTA_CLI, '$999G999G999') as col_renta,
EST.DESC_ESTCIVIL as col_est_civil
FROM CLIENTE CLI JOIN ESTADO_CIVIL EST
ON CLI.ID_ESTCIVIL = EST.ID_ESTCIVIL
WHERE CLI.NUMRUT_CLI || '-' || CLI.DVRUT_CLI = p_RUT_CLIENTE;
V_NOMBRE cur.col_nombre%type;
V_RUN cur.col_run%type;
V_RENTA cur.col_renta%type;
V_EST_CIVIL cur.est_civil%type;
BEGIN
open cur(:RUT_CLIENTE)
fetch cur into INTO V_NOMBRE, V_RUN, V_RENTA, V_EST_CIVIL;
close cur;
DBMS_OUTPUT.PUT_LINE('DATOS DEL CLIENTE');
DBMS_OUTPUT.PUT_LINE(' ');
DBMS_OUTPUT.PUT_LINE('----------------');
DBMS_OUTPUT.PUT_LINE(' ');
DBMS_OUTPUT.PUT_LINE('Nombre: ' || V_NOMBRE);
DBMS_OUTPUT.PUT_LINE('RUN: ' || V_RUN);
DBMS_OUTPUT.PUT_LINE('Estado Civil: ' || V_EST_CIVIL);
DBMS_OUTPUT.PUT_LINE('Renta: ' || V_RENTA);
END;

Postgres Type of Parameter does not match

I am having an odd problem with Postgres (10.5). I have a function, generate_unique_name which takes in three text values. It works fine; however, calling this function seems to be an issue. When I call the function using:
SELECT generate_unique_name('basic', 'seeds', 'project=' || 2)
It works without issue. I can make the same call several times. Now, when I try the same call, but change the second parameter as below:
SELECT generate_unique_name('basic', 'queue', 'project=' || 2)
Then it seems to fail with the error:
ERROR: type of parameter 9 (text) does not match that when preparing
the plan (character varying) CONTEXT: PL/pgSQL function
generate_unique_name(text,text,text) line 12 at assignment SQL state:
42804
I have tried changing the query to:
SELECT generate_unique_name('basic'::text, 'queue'::text, ('project=' || 2)::text)
But this also fails. If I then kill the connection to postgres DB, and create a new one, and instead start with the second query, it now works, but the first stops functioning.
It seems like postgres decides to stop treating the parameters as text part way through, for no apparent reason. Am I missing something?
EDIT: Code for generate_unique_name
CREATE OR REPLACE FUNCTION public.generate_unique_name(
proposed_name text,
table_name text,
condition text)
RETURNS text
LANGUAGE 'plpgsql'
COST 100
VOLATILE
AS $BODY$
DECLARE
unique_name text;
name_counter integer;
r record;
names_to_check text[];
BEGIN
unique_name = proposed_name;
name_counter = 0;
FOR r IN EXECUTE 'SELECT name FROM ' || table_name || ' WHERE ' || condition LOOP
names_to_check = array_append(names_to_check, r.name::text);
END LOOP;
WHILE unique_name = ANY(names_to_check) LOOP
name_counter = name_counter + 1;
unique_name = proposed_name || ' (' || name_counter || ')';
END LOOP;
RETURN unique_name;
END;
$BODY$;
My guess is there's a value in the name column of the queue table that causes an issue with
names_to_check = array_append(names_to_check, r.name::text)
As Joe mentioned, the issue was with the array_append, which I could not figure out a way to fix. Instead, the generate_unique_names functions was changed to just query the DB continuously.
CREATE OR REPLACE FUNCTION generate_unique_name (proposed_name text, table_name text, condition text) RETURNS text AS
$BODY$
DECLARE
unique_name text;
name_counter integer;
not_unique boolean;
BEGIN
unique_name = proposed_name;
name_counter = 0;
EXECUTE 'SELECT COUNT(*)!=0 FROM ' || table_name || ' WHERE ' || condition || ' AND name = ''' || unique_name || '''' INTO not_unique;
WHILE not_unique LOOP
name_counter = name_counter + 1;
unique_name = proposed_name || ' (' || name_counter || ')';
EXECUTE 'SELECT COUNT(*)!=0 FROM ' || table_name || ' WHERE ' || condition || ' AND name = ''' || unique_name || '''' INTO not_unique;
END LOOP;
RETURN unique_name;
END;
$BODY$ LANGUAGE plpgsql;

how to += in Postgres 9.3

i am having a trouble to reassign a value, my teacher told me to use something like
var = var + (rest of the query)
but it aint working at all, here it is my code:
create or replace function recorrertablas()
returns void as
$BODY$
declare cursorx cursor for select id, nombre as nombres from tablas;
declare cursory refcursor;
declare rec record;
declare rec2 record;
declare consulta varchar;
--declare consulta2 varchar;
begin
open cursorx;
loop
fetch cursorx into rec;
exit when not found;
consulta= 'create table ' || rec.nombres;
--consulta2= '';
open cursory for select * from atributos where idtabla = rec.id;
loop
fetch cursory into rec2;
exit when not found;
consulta = consulta + '(' || rec2.id || ', ' || rec2.idtabla || ', ' || rec2.nombre || ', ' ||rec2.tipodedatos ;
if rec2.claveprimaria = 1 then
consulta= consulta +', constraint pk_ ' || rec.nombres || '( ' || rec.id || '));';
else
consulta = consulta +');';
end if;
end loop;
close cursory;
end loop;
execute consulta;
close cursorx;
end;
$BODY$
language plpgsql volatile;
If you need to concatenate things use || operator or concat() function like below.
You've been using this operator, but for some reason you mixed it with +.
SELECT 'string' || 'part2';
or
SELECT concat('string', 'part2');
For your specific case:
consulta = consulta || '(' || rec2.id || ', ' || rec2.idtabla || ', ' || rec2.nombre || ', ' ||rec2.tipodedatos ;
if rec2.claveprimaria = 1 then
consulta= consulta || ', constraint pk_ ' || rec.nombres || '( ' || rec.id || '));';
else
consulta = consulta || ');';
When using || operator if any value evaluates to NULL the whole output will be NULL, but when using concat() function it will omit NULL values and still concatenate other arguments.

Prepared statements in PostgreSQL

Trying to figure out how to make prepared statements work in plpgsql in order to sanitize my code.
PREPARE statements(text, text, text, text, text, text, text, text, text, text, text, text) AS
'SELECT
*
FROM
articles
WHERE
' || $1 || ' AND
' || $2 || ' AND
primary_category LIKE ''' || $3 || ''' AND
' || $4 || ' AND
' || $5 || ' AND
' || $6 || ' AND
' || $7 || ' AND
' || $8 || ' AND
' || $9 || ' AND
' || $10 || ' AND
' || $11 || ' AND
is_template = ' || ยง12 || ' AND
status <> ''DELETED''
ORDER BY ' || $13 || ' LIMIT 500';
RETURN QUERY EXECUTE statements(search_term, publication_date_query, category_filter, tags_query, districts_query, capability_query, push_notification_query, distance_query, revision_by, publication_priority_query, status_query, only_templates, order_by);
The above code returns
ERROR: syntax error at or near "'SELECT
*
FROM
articles
WHERE
'"
LINE 67: 'SELECT
I declade my variables like so:
DECLARE
tags_query text := 'true';
BEGIN
IF char_length(search_term) > 0 THEN
order_by := 'ts_rank_cd(textsearchable_index_col, to_tsquery(''' || search_term || ':*''))+GREATEST(0,(-1*EXTRACT(epoch FROM age(last_edited)/86400))+60)/60 DESC';
search_term := 'to_tsquery(''' || search_term || ':*'') ## textsearchable_index_col';
ELSE
search_term := 'true';
END IF;
...
I am new at this, please don't freak out immediately, if it is something silly, i did not notice.
Edit: PostgreSQL Version 9.6
Edit: I am aware of the documentation.
I see more issues.
PLpgSQL doesn't support explicitly prepared commands - so SQL EXECUTE command is different than PLpgSQL EXECUTE command. Parameter of PLpgSQL EXECUTE command is SQL string - not name of prepared command. There are not clean way, how to execute SQL explicitly prepared command from PLpgSQL. So, combination PREPARE cmd(); EXECUTE cmd() in PLpgSQL has not any sense.
Parameter of prepared statement should by clean value - it cannot be used inside apostrophes. ` ' $n ' is another nonsense. Just $n is safe. ' $n ' means string " $n " what is probably different, than you are expecting.

Error while inserting data into a table using package body

I am getting following error:
'ORA-06550: line 1, column 48:PLS-00103: Encountered the symbol "," when expecting one of the following: := . ( # % ;'
while trying to run below code:
create or replace PACKAGE BODY "PACKAGE_NAME" As
Procedure MAIN Is
BEGIN
LOAD_DATA;
END MAIN;
Procedure LOAD_DATA Is
V_LC_NARRATIVE VARCHAR2(50) :=
'CDB_LETTER_OF_CREDIT_NARRATIVE.LOAD_DATA';
V_LC_STMT_ENTRY_NO VARCHAR2(50) := 'CDB_LC_STMT_ENTRY_NO.LOAD_DATA';
V_LC_HSCODE VARCHAR2(50) := 'CDB_LETTER_OF_CREDIT_HSCODE.LOAD_DATA';
BEGIN
insert into table_name
(
column1,
column2,...
)
SELECT
column1,
column2,...
FROM Table_2 WHERE ID IS NOT NULL;
COMMIT;
EXECUTE IMMEDIATE ' BEGIN ' || V_LC_NARRATIVE || ', END,';
EXECUTE IMMEDIATE ' BEGIN ' || V_LC_STMT_ENTRY_NO || ', END,';
EXECUTE IMMEDIATE ' BEGIN ' || V_LC_HSCODE || ', END,';
Exception
WHEN OTHERS THEN
ERROR_LOGGER ('PACKAGE_NAME', 'TABLE_NAME','', SQLCODE, substr(SQLERRM, 1, 500));
END LOAD_DATA;
END PACKAGE_NAME;
Change these lines:
execute immediate ' BEGIN ' || v_lc_narrative || ', END,';
to
execute immediate ' BEGIN ' || v_lc_narrative || '; END;';