Postgres Type of Parameter does not match - sql

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;

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;

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.

Function with Table_name as input and returns a number in Oracle

I have a function that takes table_name as input and returns a number.
The function gets compiled properly but for some reason when I try test the function it throws error - missing keyword.
CREATE OR replace FUNCTION TEST_FUNCTION (name_table IN VARCHAR2) RETURN NUMBER
IS
rday NUMBER;
BEGIN
execute immediate
'select day_i into rday
FROM ' || name_table || '
WHERE day_i = 1 and rownum = 1';
return rday;
END TEST_FUNCTION;
This is how I am testing it Select TEST_FUNCTION ('FDR_REP') from dual;
The syntax for execute immediate is different for an into clause
try
CREATE OR replace FUNCTION TEST_FUNCTION (name_table IN VARCHAR2) RETURN NUMBER
IS
rday NUMBER;
BEGIN
execute immediate 'select day_i
FROM ' || name_table || '
WHERE day_i = 1 and rownum = 1' into rday;
return rday;
END TEST_FUNCTION;

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

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.

Finding specific data in Oracle Tables

I needed to find a value for a column in my oracle database but i don't know which
table or column it's stored in
How can I search for a specific or like %% data as I do in
select * from SYS.dba_source
is there a table like that
Column Name ID Data Type Null? Comments
OWNER 1 VARCHAR2 (30 Byte) Y
NAME 2 VARCHAR2 (30 Byte) Y Name of the object
TYPE 3 VARCHAR2 (12 Byte) Y
Type of the object:
"TYPE", "TYPE BODY", "PROCEDURE", "FUNCTION",
"PACKAGE", "PACKAGE BODY" or "JAVA SOURCE"
LINE 4 NUMBER Y Line number of this line of source
TEXT 5 VARCHAR2 (4000 Byte) Y Source text
LINK: pl/sq to find any data in a schema
Imagine, there are a few tables in your schema and you want to find a specific value in all columns within these tables. Ideally, there would be an sql function like
select * from * where any(column) = 'value';
Unfortunately, there is no such function.
However, a PL/SQL function can be written that does that. The following function iterates over all character columns in all tables of the current schema and tries to find val in them.
create or replace function find_in_schema(val varchar2)
return varchar2 is
v_old_table user_tab_columns.table_name%type;
v_where Varchar2(4000);
v_first_col boolean := true;
type rc is ref cursor;
c rc;
v_rowid varchar2(20);
begin
for r in (
select
t.*
from
user_tab_cols t, user_all_tables a
where t.table_name = a.table_name
and t.data_type like '%CHAR%'
order by t.table_name) loop
if v_old_table is null then
v_old_table := r.table_name;
end if;
if v_old_table <> r.table_name then
v_first_col := true;
-- dbms_output.put_line('searching ' || v_old_table);
open c for 'select rowid from "' || v_old_table || '" ' || v_where;
fetch c into v_rowid;
loop
exit when c%notfound;
dbms_output.put_line(' rowid: ' || v_rowid || ' in ' || v_old_table);
fetch c into v_rowid;
end loop;
v_old_table := r.table_name;
end if;
if v_first_col then
v_where := ' where ' || r.column_name || ' like ''%' || val || '%''';
v_first_col := false;
else
v_where := v_where || ' or ' || r.column_name || ' like ''%' || val || '%''';
end if;
end loop;
return 'Success';
end;