I have this code and I want to concatenate the variables but don't work.
This is my DDL code for the view:
CREATE OR REPLACE function acd.add_credito2()
RETURNS void
SET SCHEMA 'acd'
SET search_path = acd
AS $$
DECLARE
auxsigla text;
auxnome text;
_sql text := 'CREATE OR REPLACE VIEW acd.teste AS SELECT md.matriz_disciplina_id AS id, dcp.nome, mc.curso, mc.versao AS matriz';
_join text := ' FROM matriz_disciplina as md LEFT JOIN disciplina as dcp ON md.disciplina_id = dcp.disciplina_id LEFT JOIN matriz_curricular as mc ON md.matriz_curricular_id = mc.matriz_curricular_id';
BEGIN
select into auxsigla, auxnome from ( select sigla, nome from acd.categoria_credito where categoria_credito_id = 9) as foo;
_join := _join || ' LEFT JOIN (SELECT creditos, matriz_disciplina_id FROM acd.disciplina_credito WHERE categoria_credito_id = ' || x || ') AS ' || "auxsigla" ' ON ' || "auxsigla" || '.matriz_disciplina_id = md.matriz_disciplina_id';
_sql := _sql || ', ' || "auxsigla" || '.' || auxnome || ' AS ' || auxnome;
_sql := _sql || _join;
EXECUTE _sql;
END;
$$ LANGUAGE plpgsql
So, when I execute the function
database-1=# select acd.add_credito2();
This error appears:
ERROR: type "auxsigla" does not exist
LINE 1: ...WHERE categoria_credito_id = ' || x || ') AS ' || "auxsigla"...
^
QUERY: SELECT _join || ' LEFT JOIN (SELECT creditos, matriz_disciplina_id FROM acd.disciplina_credito WHERE categoria_credito_id = ' || x || ') AS ' || "auxsigla" ' ON ' || "auxsigla" || '.matriz_disciplina_id = md.matriz_disciplina_id'
CONTEXT: PL/pgSQL function add_credito2() line 13 at assignment
Can anyone help me? I don't know what to do now.
(I know, this study view don't have a purpose but this is the idea that I want to use in the real view)
The error comes from this construct:
"auxsigla" ' ON '
You forgot a concatenation operator || between these two tokens, and now the SQL parser interprets it as
data_type string_constant
which is a way to specify constants of a certain data type.
Working examples would be DATE '2018-09-20' or INTEGER '-20'.
Your function has numerous other problems, two of which I could spot:
select into auxsigla, auxnome from will always set the variables to NULL because you forgot to specify which columns you want to select.
you do not properly escape single quotes while composing your dynamic query string. What if auxsigla has the value with'quote?
Use format() or quote_literal() and quote_ident() for that.
Related
I modified the function to trim all values in multiple tables based on Trim Spaces inside whole Database as below:
create function trim_all_text()
RETURNS void AS $$
DECLARE QL VARCHAR;
BEGIN
QL ='';
-- stored procedure body
PERFORM QL = QL || 'UPDATE T SET T.'||IC.COLUMN_NAME ||
' = LTRIM(RTRIM(' || IC.COLUMN_NAME||'))
FROM '|| IT.TABLE_SCHEMA || '.[' || IT.TABLE_NAME ||
'] AS T ;' || CHR(13)
FROM INFORMATION_SCHEMA.TABLES IT
JOIN INFORMATION_SCHEMA.COLUMNS IC ON IT.TABLE_NAME = IC.TABLE_NAME
AND IT.TABLE_SCHEMA ='public' and IT.TABLE_SCHEMA = IC.TABLE_SCHEMA AND IT.TABLE_TYPE = 'BASE TABLE'
and IC.DATA_TYPE in( 'varchar','char','nvarchar','nchar', 'text');
END;
$$ LANGUAGE plpgsql;
When I run the function in pgadmin4, I receive the error below:
ERROR: operator does not exist: unknown + information_schema.sql_identifier
LINE 1: SELECT QL += 'UPDATE ' + IT.TABLE_SCHEMA + '.'
^
How can I combine strings in a query?
i have below tables and functions while executing the below function in postgresql ,it is showing ERROR: schema "tblmark" does not exist.Please help.
CREATE TABLE "LandXML_QCC_ParcelMarks"("DPID" TEXT,"From" TEXT,"Name" TEXT);
INSERT INTO "LandXML_QCC_ParcelMarks" VALUES ('1','ram','kumar');
CREATE TABLE "LandXML_QCC_ParcelInformation"("DPID" TEXT,"Pntref" TEXT)
INSERT INTO "LandXML_QCC_ParcelInformation" VALUES ('1','ram');
CREATE OR REPLACE FUNCTION GetParcelNonParcel(PlanID TEXT)
RETURNS TEXT AS $GetParcelNonParcel$
DECLARE
tblMark RECORD;
parCount INTEGER;
parNonCount INTEGER;
totalParNonCount TEXT;
tblCou INTEGER;
BEGIN
parCount=0;
parNonCount=0;
FOR tblMark IN (SELECT * FROM "LandXML_QCC_ParcelMarks" WHERE "DPID" = PlanID) LOOP
SELECT COUNT(*) INTO tblCou FROM "LandXML_QCC_ParcelInformation"
WHERE "DPID"=PlanID
AND (
"Pntref" LIKE '%' || tblMark.From || ',' || tblMark.Name '%'
OR
"Pntref" LIKE '%' || tblMark.Name || ',' || tblMark.From '%'
);
RAISE NOTICE 'Value: %', tblCou;
IF tblCou > 0 THEN
parCount = parCount + 1;
RAISE NOTICE 'Value: %', parCount;
ELSE
parNonCount = parNonCount + 1;
END IF;
END LOOP;
totalParNonCount = CAST(parCount AS TEXT) || ',' || CAST(parNonCount AS TEXT);
RAISE NOTICE 'Value: %', totalParNonCount;
RETURN totalParNonCount;
END;
$GetParcelNonParcel$ LANGUAGE plpgsql;
select GetParcelNonParcel('1');
While executing above function,it is showing ERROR: schema "tblmark" does not exist.
In your SELECT inside the FOR loop, you have the following condition:
... AND (
"Pntref" LIKE '%' || tblMark.From || ',' || tblMark.Name '%'
OR
"Pntref" LIKE '%' || tblMark.Name || ',' || tblMark.From '%'
)
You are missing the concatenation-operator || for the trailing '%' both times. Also, you are not properly referencing the columns of your record. Since you established them with " (double-quotes), you will always need to refer to them exactly the same way (This is a reason why you should not do this. So if it is not to late, change it to names without quotes.).
Using your momentary columnnames, this should help you:
... AND (
"Pntref" LIKE '%' || tblMark."From" || ',' || tblMark."Name" || '%'
OR
"Pntref" LIKE '%' || tblMark."Name" || ',' || tblMark."From" || '%'
)
I need to generate Insert script in postgres for all the tables in a database such that it can be run again without throwing any error.
The problem is, Only few tables have primary key while the rest have Unique index on different columns.
This is why I am not able to list out the columns on which unique index has been created.
The reason behind this is that the schema is automatically created through Magnolia.
Can anyone help me write the query which produces Insert statement including 'Where not Exists (Select 1 from table where column = value)' condition based on Primary Key/Unique columns?
You can use on conflict:
insert into t ( . . . )
values ( . . . )
on conflict do nothing;
This function returns Insert script for data and works well with tables on which primary constraint is not available.
I have modified the code that I found on another thread by adding the condition to it.
CREATE OR REPLACE FUNCTION public.generate_inserts(varSchema text, varTable text) RETURNS TABLE(resultado text) AS $$
DECLARE CODE TEXT;
BEGIN
CODE :=
(
SELECT
'SELECT ''INSERT INTO '
|| table_schema || '.'
|| table_name ||' ('
|| replace(replace(array_agg(column_name::text)::text,'{',''),'}','') || ') SELECT ''||'
|| replace(replace(replace(array_agg( 'quote_nullable(' || column_name::text || ')')::text,'{',''),'}',''),',',' || '','' || ')
|| ' || '' Where Not Exists (Select 1 From ' || table_name ||' Where 1 = 1 '
|| ''''
|| replace(replace(replace(replace(array_agg(' || '' and (' || column_name::text || ' = '' || quote_nullable(' || column_name::text || '),' || ' || '' or ' || column_name::text || ' is null)''')::text,'{',''),'}',''),'"',''),',','')
|| '|| '');'''
|| ' FROM ' || table_schema || '.' || table_name || ';'
FROM information_schema.columns c
WHERE table_schema = varSchema
AND table_name = varTable
GROUP BY table_schema, table_name);
RETURN QUERY
EXECUTE CODE;
END;
$$ LANGUAGE plpgsql;
When I run the following command from a function I defined, I get the error "EXECUTE of SELECT ... INTO is not implemented". Does this mean the specific command is not allowed (i.e. "SELECT ...INTO")? Or does it just mean I'm doing something wrong? The actual code causing the error is below. I apologize if the answer is already out here, however I looked and could not find this specific error. Thanks in advance... For whatever it's worth I'm running 8.4.7
vCommand = 'select ' || stmt.column_name || ' as id ' ||
', count(*) as nCount
INTO tmpResults
from ' || stmt.table_name || '
WHERE ' || stmt.column_name || ' IN (select distinct primary_id from anyTable
WHERE primary_id = ' || stmt.column_name || ')
group by ' || stmt.column_name || ';';
EXECUTE vCommand;
INTO is ambiguous in this use case and then is prohibited there.
You can use a CREATE TABLE AS SELECT instead.
CREATE OR REPLACE FUNCTION public.f1(tablename character varying)
RETURNS integer
LANGUAGE plpgsql
AS $function$
begin
execute 'create temp table xx on commit drop as select * from '
|| quote_ident(tablename);
return (select count(*) from xx);
end;
$function$
postgres=# select f1('omega');
f1
────
2
(1 row)
I have a production database, using Firebird 2.1, where I need to find out how much space is used by each table, including the blobs. The blob-part is the tricky one, because it is not covered using the standard statistical report.
I do not have easy access to the server's desktop, so installing UDFs etc. is not a good solution.
How can I do this easily?
You can count total size of all BLOB fields in a database with following statement:
EXECUTE BLOCK RETURNS (BLOB_SIZE BIGINT)
AS
DECLARE VARIABLE RN CHAR(31) CHARACTER SET UNICODE_FSS;
DECLARE VARIABLE FN CHAR(31) CHARACTER SET UNICODE_FSS;
DECLARE VARIABLE S BIGINT;
BEGIN
BLOB_SIZE = 0;
FOR
SELECT r.rdb$relation_name, r.rdb$field_name
FROM rdb$relation_fields r JOIN rdb$fields f
ON r.rdb$field_source = f.rdb$field_name
WHERE f.rdb$field_type = 261
INTO :RN, :FN
DO BEGIN
EXECUTE STATEMENT
'SELECT SUM(OCTET_LENGTH(' || :FN || ')) FROM ' || :RN ||
' WHERE NOT ' || :FN || ' IS NULL'
INTO :S;
BLOB_SIZE = :BLOB_SIZE + COALESCE(:S, 0);
END
SUSPEND;
END
I modified the code example of Andrej to show the size of each blob field, not only the sum of all blobs.
And used SET TERM so you can copy&paste this snippet directly to tools like FlameRobin.
SET TERM #;
EXECUTE BLOCK
RETURNS (BLOB_SIZE BIGINT, TABLENAME CHAR(31), FIELDNAME CHAR(31) )
AS
DECLARE VARIABLE RN CHAR(31) CHARACTER SET UNICODE_FSS;
DECLARE VARIABLE FN CHAR(31) CHARACTER SET UNICODE_FSS;
DECLARE VARIABLE S BIGINT;
BEGIN
BLOB_SIZE = 0;
FOR
SELECT r.rdb$relation_name, r.rdb$field_name
FROM rdb$relation_fields r JOIN rdb$fields f
ON r.rdb$field_source = f.rdb$field_name
WHERE f.rdb$field_type = 261
INTO :RN, :FN
DO BEGIN
EXECUTE STATEMENT
'SELECT SUM(OCTET_LENGTH(' || :FN || ')) AS BLOB_SIZE, ''' || :RN || ''', ''' || :FN || '''
FROM ' || :RN ||
' WHERE NOT ' || :FN || ' IS NULL'
INTO :BLOB_SIZE, :TABLENAME, :FIELDNAME;
SUSPEND;
END
END
#
SET TERM ;#
This example doesn't work with ORDER BY, maybe a more elegant solution without EXECUTE BLOCK exists.