Can someone help me understand why I get a parenthesis around the schemaname nspname? And/or, a way to remove it, so the loop will work?
DO $$
DECLARE
views_ CURSOR FOR
SELECT nspname
FROM pg_catalog.pg_namespace
WHERE nspname LIKE '%scemanames%';
BEGIN
FOR nspname IN views_ LOOP
EXECUTE 'INSERT INTO forkert_ejendom_roert SELECT * FROM ' || nspname || '.viewname';
-- Do something with nbRow
END LOOP;
END$$;
The output i get is:
ERROR: syntax error at or near ")"
LINE 1: ...m_roert SELECT * FROM ('schemanames).bbr_punk...
^
QUERY: INSERT INTO forkert_ejendom_roert SELECT * FROM (name of the schema).viewname
CONTEXT: PL/pgSQL function inline_code_block line 9 at EXECUTE
********** Error **********
ERROR: syntax error at or near ")" SQL state: 42601
Context: PL/pgSQL function inline_code_block line 9 at EXECUTE
The loop variable is a record (actually containing a single column), try:
FOR rec IN views_ LOOP
EXECUTE 'INSERT INTO forkert_ejendom_roert SELECT * FROM ' || rec.nspname || '.viewname';
Related
I am a newbie wrt functions and I am struggling with using the name of a table in the function body. I get an error "SQL Error [42703]: ERROR: column "tname" does not exist" when I call the function using
select "JsonToView"('data_import.import_360xero_report');
My code is below
create or replace
function data_import."JsonToView"(tname text) returns numeric
language plpgsql
as $function$
begin
do
$$
declare
l_keys text;
begin
drop view if exists v_json_view cascade;
select
string_agg(distinct format('import_data ->> %L as %I', jkey, jkey), ', ')
into
l_keys
from
import_360xero_report,
json_object_keys(import_data) as t(jkey);
execute 'create view v_json_view as select ' || l_keys || ' from ' || tname;
end;
$$;
return 0;
end $function$ ;
I have modified the code and the second create view query works with the table name but the first one does not.
Below if my modified code
create or replace
function data_import."JsonToView"(tname text) returns numeric
language plpgsql
as $function$
declare
l_keys text;
begin
drop view if exists v_json_view cascade;
execute $a$select
string_agg(distinct format('import_data ->> %L as %I', jkey, jkey), ', ')
into
l_keys
from $a$ ||
tname || $b$,
json_object_keys(import_data) as t(jkey)$b$;
execute 'create view v_json_view as select ' || l_keys || ' from ' || tname;
return 0;
end $function$ ;
The error I am getting is
SQL Error [0A000]: ERROR: EXECUTE of SELECT ... INTO is not implemented
Hint: You might want to use EXECUTE ... INTO or EXECUTE CREATE TABLE ... AS instead.
Where: PL/pgSQL function "JsonToView"(text) line 10 at EXECUTE
The problem is the superfluous nested DO statement.
The variable tname exists only in the scope of the function, not in the nested DO statement. DO is an SQL statement, not a PL/pgSQL statement, and there are no variables in SQL. Also, DO does not allow parameters.
Get rid of the DO and you will be fine.
Is it possible to iterate over a table's records and make a left join with them in a stored procedure?
Something like this:
FOR r IN SELECT tablename FROM tablewithtablenames ORDER BY tablename ASC
LOOP
INSERT INTO temp_Results
SELECT
temp_ids.Key as Key,
loggedvalue.pk_timestamp,
FROM
(temp_idS AS temp_ids
LEFT JOIN
quote_ident(r.tablename) AS loggedvalue
ON temp_ids.Key = loggedvalue.pk_fk_id);
END LOOP;
Unfortunately i get the following error message when i want to execute the stored procedure. (Function creation was successful.)
Error message:
ERROR: column loggedvalue.pk_fk_id does not exist LINE 29:
ON temp_ids.Key = "loggedvalue...
I have the feeling that i convert the record in a wrong way maybe because when i manually replaced the quote_ident(r.tablename) to the name of the table that i know the r contains it was fine, also i traced out the r.tablename in the loop and it was correct also.
As a_horse_with_no_name pointed out i should have use dynamic sql because in plpgsql you can not use a variable as a table name so i eliminated the loop and i used a union all:
CREATE OR REPLACE FUNCTION getaffectedtables(
OUT tableNames TEXT)
as $$
BEGIN
SELECT TRIM(TRAILING ' UNION ALL ' FROM string_agg('','SELECT * FROM "' || "tablename" || '" UNION ALL '))
INTO tableNames
FROM exampleTable;
END;$$
LANGUAGE plpgsql;
Then i used dynamic execute:
DECLARE
affectednames TEXT;
BEGIN
affectednames := getaffectedtables();
EXECUTE '
SELECT
temp_ids.Key as Key,
loggedvalue.pk_timestamp,
FROM
(temp_idS AS temp_ids
LEFT JOIN
('|| affectednames ||') AS loggedvalue
ON temp_ids.Key = loggedvalue.pk_fk_id);';
in my postgres 9.3 database, I have the following combination of function and a trigger to implement soft delete functionality:
ALTER TABLE "LIBN02"."trigger_test_1"
ADD COLUMN delete_ind integer
CREATE OR REPLACE FUNCTION trigger_test_1_soft_delete()
RETURNS trigger AS $$
DECLARE
command text := ' SET delete_ind = 1 WHERE uuid_col = $1';
BEGIN
EXECUTE 'UPDATE ' || "LIBN02"."trigger_test_1" || command USING OLD.uuid_col;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER test_1_soft_delete_trigger
BEFORE DELETE ON "LIBN02"."trigger_test_1"
FOR EACH ROW EXECUTE PROCEDURE trigger_test_1_soft_delete();
After all of the above is done, I run the following delete statement:
DELETE FROM "LIBN02"."trigger_test_1"
I get the following error:
ERROR: missing FROM-clause entry for table "LIBN02"
LINE 1: SELECT 'UPDATE ' || "LIBN02"."trigger_test_1" || command
^
QUERY: SELECT 'UPDATE ' || "LIBN02"."trigger_test_1" || command
CONTEXT: PL/pgSQL function trigger_test_1_soft_delete() line 5 at EXECUTE
********** Error **********
ERROR: missing FROM-clause entry for table "LIBN02"
SQL state: 42P01
Context: PL/pgSQL function trigger_test_1_soft_delete() line 5 at EXECUTE
What should I change in order for this to work?
The error you are receiving is because "LIBN02"."trigger_test_1" is not a string (these are quoted with single quotes), but an identifier. You should use
EXECUTE 'UPDATE "' || TG_TABLE_SCHEMA || '"."' || TG_TABLE_NAME || '" ' || command
USING OLD.uuid_col;
You could also add AND NOT deleted to the WHERE clause to avoid unnecessary churn.
I have a huge OSM dataset with a lot of null-only columns which i want to get rid of.
DO
$do$
DECLARE
_column TEXT;
BEGIN
FOR _column IN
SELECT attname
FROM pg_stats where tablename = 'rail_l'
and most_common_vals is null
and most_common_freqs is null
and histogram_bounds is null
and correlation is null
and null_frac = 1
LOOP
RAISE NOTICE '%', _column;
EXECUTE
'ALTER TABLE rail_l DROP COLUMN ' || _column;
END LOOP;
END
$do$
Column names containing a colon cause the following error:
ERROR: syntax error at or near ":"
LINE 1: ALTER TABLE rail_l DROP COLUMN generator:source
QUERY: ALTER TABLE rail_l DROP COLUMN generator:source
CONTEXT: PL/pgSQL function inline_code_block line 16 at EXECUTE statement
SQL state: 42601
Perhaps a beginner's question since I used postgresql only for simple queries so far but i'd thankfully take any advice.
Use format() with the specifier %I:
...
LOOP
RAISE NOTICE '%', _column;
EXECUTE format('ALTER TABLE rail_l DROP COLUMN %I', _column);
END LOOP;
...
I am creating function which return the select query result from it. The details as shown below in the example:
Example:
Create or replace function fun_test(cola text,colb text,rel text)
returns table(columna text,columnb text)as
$Body$
Declare
table_name varchar :='Table_';
Begin
table_name := table_name || rel;
return query select distinct || quote_ident(cola) ||,||quote_ident(colb)|| from || quote_ident(table_name) ;
end;
$Body$
language plpgsql;
Error:
ERROR: syntax error at or near "||"
LINE 10: ...| quote_ident(cola) ||,||quote_ident(colb)|| from || quote_i...
^
You're trying to construct a query dynamically, but you're not using EXECUTE. That won't work. You can't just put arbitrary expressions in place of identifiers, like:
return query select distinct || quote_ident(cola) ||,||quote_ident(colb)|| from || quote_ident(table_name) ;
which is why you're getting the error at:
from ||
^
as that's syntactically invalid nonsense.
Instead I think you want:
RETURN QUERY EXECUTE 'select distinct ' || quote_ident(cola) ||', '||quote_ident(colb)||' from '|| quote_ident(table_name);
which is better written as:
RETURN QUERY EXECUTE format('select distinct %I, %I from %I', cola, colb, table_name);