In a PostgresSQL function, is it possible to check if a column value matches a given parameter value? - postgresql

In the WHERE clause of a SQL Server stored procedure, I can do this:
WHERE (*column_value* = #some_parameter OR #some_parameter IS NULL)
When I try to do the same thing in a PostgreSQL function, it throws an error. For example:
WHERE(FRQ.QuoteId = p_FilterQuote OR p_FilterQuote IS NULL)
produces the error: ***column "p_FilterQuote" does not exist.
The input parameter p_FilterQuote is declared and initialized at the top of the function like this:
p_filterquote integer DEFAULT NULL::integer
There must be a way to 'use' input parameters in a WHERE clause.
The entire function code is shown below.
-- FUNCTION: public.postgres_termpositionrawdata_ver3(character varying, date, character, character varying, character varying, character varying, character varying, character varying, integer, integer, character varying, character varying, character varying, character varying, character varying)
-- DROP FUNCTION public.postgres_termpositionrawdata_ver3(character varying, date, character, character varying, character varying, character varying, character varying, character varying, integer, integer, character varying, character varying, character varying, character varying, character varying);
CREATE OR REPLACE FUNCTION public.postgres_termpositionrawdata_ver3(
p_provider character varying,
p_date date,
p_correlationid character DEFAULT NULL::bpchar,
p_type character varying DEFAULT NULL::character varying,
p_productexclusionset character varying DEFAULT 'LevelTermPosition'::character varying,
p_ctmoptions character varying DEFAULT 'WOM'::character varying,
p_test character varying DEFAULT 'No'::character varying,
p_testaccountlogon character varying DEFAULT NULL::character varying,
p_averagetopx integer DEFAULT 5,
p_filterquote integer DEFAULT NULL::integer,
p_includeduplicatequotes character varying DEFAULT 'Yes'::character varying,
p_ignoreglobalpermissions character varying DEFAULT 'Yes'::character varying,
p_ignoredefaultproductexclusions character varying DEFAULT 'No'::character varying,
p_ignorelowstartresponseindicator character varying DEFAULT 'No'::character varying,
p_ignorevariableresponseindicator character varying DEFAULT 'No'::character varying)
RETURNS void
LANGUAGE 'plpgsql'
COST 100
VOLATILE
AS $BODY$
--DECLARE CONSTANTS
DECLARE
--DECLARE VARIABLES
v_Status varchar(10) = 'Success';BEGIN
-- assume success
-- SET CorrelationID
IF p_CorrelationId IS NULL THEN p_CorrelationId := public.swf_newid();
END IF;
DROP TABLE IF EXISTS FilteredRequests;
DROP TABLE IF EXISTS FilteredResponses;
DROP TABLE IF EXISTS Ranks;
CREATE TEMP TABLE FilteredRequests AS
SELECT * FROM public.dblink('srv_exchangemart', '
SELECT
FRQ.QuoteID
,DEO.Name AS OrganisationName
,DEO.Postcode AS OrganisationPostcode
,DEO.FRN AS OrganisationFRN
,DDQ.Date AS RequestDate
,DLB.LifeBasis
,DDC.Date AS CommencementDate
,DQF.QuotationFor
,LCR.LifeCriticalIllnessRiskRelationship
,TDP.TotalPermanentDisabilityCover
,CB.CommissionBasis
,DCT.CommissionType
,DG1.Gender AS Life1Gender
FROM FactRequest FRQ
INNER JOIN dimExchangeOrganisation DEO ON FRQ.ExchangeOrganisationID = DEO.ExchangeOrganisationId
INNER JOIN dimExchangeUser DEU ON FRQ.ExchangeUserId = DEU.ExchangeUserId
INNER JOIN dimLifeBasis DLB ON FRQ.LifeBasisId = DLB.LifeBasisID
INNER JOIN dimTotalPermanentDisabilityCover TDP ON FRQ.TotalPermanentDisabilityCoverId = TDP.TotalPermanentDisabilityCoverID
INNER JOIN dimDate DDQ ON FRQ.QuotationDateID = DDQ.DateID
INNER JOIN dimDate DDC ON FRQ.CommencementDateID = DDC.DateID
INNER JOIN dimExchangePanel DEP ON FRQ.ExchangePanelId = DEP.ExchangePanelId
INNER JOIN dimCommissionBasis CB ON FRQ.CommissionBasisId = CB.CommissionBasisId
INNER JOIN dimCommissionType DCT ON FRQ.CommissionTypeId = DCT.CommissionTypeId
INNER JOIN factClient FC ON FRQ.QuoteID = FC.QuoteID
INNER JOIN dimLifeCriticalIllnessRiskRelationship LCR ON FRQ.LifeCriticalIllnessRiskRelationshipId = LCR.LifeCriticalIllnessRiskRelationshipId
INNER JOIN dimQuotationFor DQF ON FRQ.QuotationForId = DQF.QuotationForId
INNER JOIN dimKeyPerson DKP ON FRQ.KeyPersonId = DKP.KeyPersonId
INNER JOIN dimBenefitBasis DBB ON FRQ.BenefitBasisId = DBB.BenefitBasisId
INNER JOIN dimIntegrator DI ON FRQ.ExchangeIntegratorId = DI.ExchangeIntegratorId
INNER JOIN dimGender DG1 ON FC.Life1GenderID = DG1.GenderID
INNER JOIN dimGender DG2 ON FC.Life2GenderID = DG2.GenderID
INNER JOIN dimSmoker DS1 ON FC.Life1SmokerID = DS1.SmokerID
INNER JOIN dimSmoker DS2 ON FC.Life2SmokerID = DS2.SmokerID
INNER JOIN dimOccupation DO1 ON FC.Life1OccupationId = DO1.OccupationID
INNER JOIN dimOccupation DO2 ON FC.Life2OccupationId = DO2.OccupationID
WHERE DDQ.Date = p_date
AND FRQ.ProductTypeId IN (53) -- TERM ONLY
AND DKP.KeyPerson = ''No'' -- Not Business
AND DBB.BenefitBasis = ''Benefit Led'' -- ONLY RETURNS BENEFIT LED QUOTES
AND (DEU.LogonId = p_TestAccountLogon OR (p_TestAccountLogon IS NULL
AND DI.DefaultExclusion = ''No''
AND DEO.DefaultExclusion = ''No''))
AND ( (p_IncludeDuplicateQuotes = ''No'' AND FRQ.IsDuplicateQuote = 0)
OR (p_IncludeDuplicateQuotes = ''Yes''))
AND (FRQ.QuoteId = p_FilterQuote OR p_FilterQuote IS NULL)
AND ( (p_CTMOptions = ''CTM Only''AND DEU.LogonId = ''CTM000'')
OR (p_CTMOptions = ''Exclude CTM'' AND DEU.LogonId != ''CTM000'')
OR (p_CTMOptions = ''WOM'')
)
')
AS DATA
(QuoteID integer, OrganisationName character varying, OrganisationPostcode character varying, OrganisationFRN character varying, RequestDate date,
LifeBasis character varying, CommencementDate date, QuotationCoverFor character varying,
LifeCIRiskRelationship character varying, TPDOption character varying, CommissionBasis character varying,
CommissionType character varying, Life1Gender character varying);
-- SELECT * FROM FilteredRequests;
END;
$BODY$;

The SQL statement is executed as it is on the remote database, and no parameter substitutions of any kind are performed.
You have to do that yourself:
DECLARE
sql text;
BEGIN
sql := format(
'SELECT ... WHERE(FRQ.QuoteId = %L::integer OR %L::integer IS NULL)',
p_FilterQuote,
p_FilterQuote
);
SELECT * FROM dblink('conn', sql) AS ...;
END;

Related

invalid input syntax for integer: "0A000" CONTEXT: PL/pgSQL function trigger update

I have an update and insert function triggers, bvtrigger_fct_tr_people_upd and bvtrigger_fct_tr_people_ins
When I updated the information on the main table I encountered the error
ERROR: invalid input syntax for integer: "0A000"
CONTEXT: PL/pgSQL function bvtrigger_fct_tr_people_upd() line 75 at assignment
SQL state: 22P02
here are my tables:
CREATE TABLE pkihtts.bv_tb_people
(
peopleid integer NOT NULL DEFAULT nextval('pkihtts.bvsq_peopleid'),
tokenid integer,
auid character varying(25) COLLATE pg_catalog."default" NOT NULL,
upn character varying(256) COLLATE pg_catalog."default" NOT NULL,
firstname character varying(64) COLLATE pg_catalog."default",
middlename character varying(64) COLLATE pg_catalog."default",
lastname character varying(64) COLLATE pg_catalog."default" NOT NULL,
genqual character varying(4) COLLATE pg_catalog."default",
serialnumber character varying(25) COLLATE pg_catalog."default",
agency character varying(50) COLLATE pg_catalog."default",
subagency character varying(64) COLLATE pg_catalog."default",
affiliation character varying(10) COLLATE pg_catalog."default",
subscribertype character varying(64) COLLATE pg_catalog."default",
countryofcitizenship character varying(2) COLLATE pg_catalog."default",
emailaddress character varying(256) COLLATE pg_catalog."default" NOT NULL,
dateregistered timestamp without time zone NOT NULL,
comments character varying(255) COLLATE pg_catalog."default",
isdeleted character varying(1) COLLATE pg_catalog."default" NOT NULL DEFAULT 'n'::character varying,
modifiedby double precision NOT NULL,
modifieddate timestamp(0) without time zone,
profileid integer,
last_logon_date timestamp without time zone,
status character varying(25) COLLATE pg_catalog."default",
role character varying(15) COLLATE pg_catalog."default",
componentid integer,
CONSTRAINT bv_pk_peopleid PRIMARY KEY (peopleid)
USING INDEX TABLESPACE pkihtts_data,
CONSTRAINT tokenid_uniq UNIQUE (tokenid)
INCLUDE(tokenid)
USING INDEX TABLESPACE pkihtts_data,
CONSTRAINT fk_tokenid FOREIGN KEY (tokenid)
REFERENCES pkihtts.tb_token (tokenid) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
NOT VALID
)
TABLESPACE pkihtts_data;
ALTER TABLE pkihtts.bv_tb_people
OWNER to pkihtts;
bv_tb_people_his:
CREATE TABLE pkihtts.bv_tb_people_his
(
javaid integer NOT NULL DEFAULT nextval('pkihtts.bvsq_peoplehis_javaid'),
peopleid integer NOT NULL,
tokenid integer,
auid character varying(25) COLLATE pg_catalog."default" NOT NULL,
upn character varying(256) COLLATE pg_catalog."default" NOT NULL,
firstname character varying(64) COLLATE pg_catalog."default",
middlename character varying(64) COLLATE pg_catalog."default",
lastname character varying(64) COLLATE pg_catalog."default" NOT NULL,
genqual character varying(4) COLLATE pg_catalog."default",
agency character varying(50) COLLATE pg_catalog."default",
subagency character varying(64) COLLATE pg_catalog."default",
affiliation character varying(10) COLLATE pg_catalog."default",
subscribertype character varying(64) COLLATE pg_catalog."default",
countryofcitizenship character varying(2) COLLATE pg_catalog."default",
emailaddress character varying(256) COLLATE pg_catalog."default" NOT NULL,
dateregistered timestamp(0) without time zone NOT NULL,
comments character varying(255) COLLATE pg_catalog."default",
isdeleted character varying(1) COLLATE pg_catalog."default" NOT NULL DEFAULT 'n'::character varying,
modifiedby integer NOT NULL,
modifieddate timestamp(0) without time zone,
profileid integer,
status character varying(25) COLLATE pg_catalog."default",
component character varying(100) COLLATE pg_catalog."default",
role character varying(15) COLLATE pg_catalog."default",
componentid integer,
CONSTRAINT bv_pk_peoplehis_javaid PRIMARY KEY (javaid)
USING INDEX TABLESPACE pkihtts_data
)
TABLESPACE pkihtts_data;
ALTER TABLE pkihtts.tb_people_his
OWNER to "pkihtts";
tb_token:
CREATE TABLE pkihtts.bv_tb_token
(
tokenid integer NOT NULL DEFAULT nextval('pkihtts.bvsq_tokenid'::regclass),
internalshipmentid integer,
tokenassignmentid integer,
tokenserialno character varying(25) COLLATE pg_catalog."default" NOT NULL,
alphakey character varying(10) COLLATE pg_catalog."default",
statusdate timestamp without time zone NOT NULL,
comments character varying(255) COLLATE pg_catalog."default",
isdeleted character varying(1) COLLATE pg_catalog."default" NOT NULL DEFAULT 'n'::character varying,
modifiedby integer NOT NULL,
modifieddate timestamp without time zone,
identity_verified character varying(1) COLLATE pg_catalog."default",
new_token_required character varying(1) COLLATE pg_catalog."default",
isreassigned smallint NOT NULL DEFAULT 0,
identityverified smallint NOT NULL DEFAULT 0,
newtokenrequired smallint NOT NULL DEFAULT 0,
status character varying(25) COLLATE pg_catalog."default",
prevstatus character varying(25) COLLATE pg_catalog."default",
reason character varying(25) COLLATE pg_catalog."default",
CONSTRAINT bv_pk_tokenid PRIMARY KEY (tokenid)
USING INDEX TABLESPACE pkihtts_data
)
TABLESPACE pkihtts_data;
ALTER TABLE pkihtts.bv_tb_token
OWNER to pkihtts;
sequences:
peopleid sequence:
CREATE SEQUENCE pkihtts.bvsq_peopleid
INCREMENT 1
START 50
MINVALUE 1
MAXVALUE 9223372036854775807
CACHE 1;
ALTER SEQUENCE pkihtts.bvsq_peopleid
OWNER TO "pkihtts";
javaid sequence:
CREATE SEQUENCE pkihtts.bvsq_peoplehis_javaid
INCREMENT 1
START 50
MINVALUE 1
MAXVALUE 9223372036854775807
CACHE 1;
ALTER SEQUENCE pkihtts.bvsq_peoplehis_javaid
OWNER TO "pkihtts";
here are my functions/triggers:
function tb_people_upd:
CREATE FUNCTION pkihtts.bvtrigger_fct_tr_people_upd()
RETURNS trigger
LANGUAGE 'plpgsql'
COST 100
VOLATILE NOT LEAKPROOF
AS $BODY$
DECLARE
v_ErrorCode int;
v_ErrorMsg varchar(512);
v_Module varchar(31) = 'BVTR_PEOPLE_UPD';
v_Os_User varchar(30);
v_Host varchar(40);
BEGIN
---
-- Copy the record from tb_people_his to tb_peop;e
---
INSERT INTO pkihtts.bv_tb_people_his (
peopleid,
role,
status,
tokenid,
auid,
upn,
firstname,
middlename,
lastname,
genqual,
agency,
subagency,
affiliation,
subscribertype,
countryofcitizenship,
emailaddress,
dateregistered,
comments,
isdeleted,
modifiedby,
modifieddate,
profileid,
componentid
)
VALUES (
old.peopleid,
old.role,
old.status,
old.tokenid,
old.auid,
old.upn,
old.firstname,
old.middlename,
old.lastname,
old.genqual,
old.agency,
old.subagency,
old.affiliation,
old.subscribertype,
old.countryofcitizenship,
old.emailaddress,
old.dateregistered,
old.comments,
old.isdeleted,
old.modifiedby,
old.modifieddate.
old.profileid,
old.componentid
)
;
RETURN NEW;
---
-- Exception error handler
---
exception
when others then
v_ErrorCode := SQLSTATE;
v_ErrorMsg := SQLERRM;
v_Os_User := CURRENT_USER;
v_Host := inet_server_addr();
INSERT INTO pkihtts.bv_tb_errorlog( tstamp, os_user, host, module, errorcode, errormsg )
VALUES ( current_timestamp, v_Os_User, v_Host, v_Module, v_ErrorCode, v_ErrorMsg );
RETURN NEW;
END;
$BODY$;
CREATE TRIGGER bvtr_people_upd
BEFORE UPDATE
ON pkihtts.bv_tb_people
FOR EACH ROW
EXECUTE PROCEDURE pkihtts.bvtrigger_fct_tr_people_upd();
tb_people_ins:
CREATE FUNCTION pkihtts.bvtrigger_fct_tr_people_ins()
RETURNS trigger
LANGUAGE 'plpgsql'
COST 100
VOLATILE NOT LEAKPROOF
AS $BODY$
DECLARE
v_peopleid int = 0;
v_ErrorCode int;
v_ErrorMsg varchar(512);
v_Module varchar(31) = 'TR_PEOPLE_INS';
v_Os_User varchar(30);
v_Host varchar(40);
BEGIN
if TG_OP = 'INSERT' then
IF new.peopleid IS null THEN
SELECT nextval('pkihtts."bvsq_peopleid"') INTO v_peopleid;
new.peopleid := v_peopleid;
END IF;
IF new.modifieddate is null then
new.modifieddate := CURRENT_TIMESTAMP;
END IF;
RETURN NEW;
END IF;
---
-- Exception error handler
---
exception
when others then
v_ErrorCode := SQLSTATE;
v_ErrorMsg := SQLERRM;
v_Os_User := CURRENT_USER;
v_Host := inet_server_addr();
INSERT INTO pkihtts.bv_tb_errorlog( tstamp, os_user, host, module, errorcode, errormsg )
VALUES ( current_timestamp, v_Os_User, v_Host, v_Module, v_ErrorCode, v_ErrorMsg );
RETURN NEW;
END;
$BODY$;
CREATE TRIGGER bvtr_people_ins
BEFORE INSERT
ON pkihtts.bv_tb_people
FOR EACH ROW
EXECUTE PROCEDURE pkihtts.bvtrigger_fct_tr_people_ins();
trigger tb_people_his_ins:
CREATE FUNCTION pkihtts.bvtrigger_fct_tr_peoplehis_ins()
RETURNS trigger
LANGUAGE 'plpgsql'
COST 100
VOLATILE NOT LEAKPROOF
AS $BODY$
DECLARE
v_javaid int = 0;
v_ErrorCode int;
v_ErrorMsg varchar(512);
v_Module varchar(31) = 'BVTR_PEOPLEHIS_INS';
v_Os_User varchar(30);
v_Host varchar(40);
BEGIN
if TG_OP = 'INSERT' then
IF new.javaid IS null THEN
SELECT nextval('pkihtts."bvsq_peoplehis_javaid"') INTO v_javaid;
new.javaid := v_javaid;
END IF;
RETURN NEW;
END IF;
---
-- Exception error handler
---
exception
when others then
v_ErrorCode := SQLSTAT;
v_ErrorMsg := SQLERRM;
v_Os_User := CURRENT_USER;
v_Host := inet_server_addr();
INSERT INTO pkihtts.bv_tb_errorlog( tstamp, os_user, host, module, errorcode, errormsg )
VALUES ( current_timestamp, v_Os_User, v_Host, v_Module, v_ErrorCode, v_ErrorMsg );
RETURN NEW;
END;
$BODY$;
CREATE TRIGGER bvtr_peoplehis_ins
BEFORE INSERT
ON pkihtts.bv_tb_people_his
FOR EACH ROW
EXECUTE PROCEDURE pkihtts.bvtrigger_fct_tr_peoplehis_ins();
the max for javaid and peopleid sequences are both 50 and I altered the current value at 51.
select max(peopleid) from pkihtts.bv_tb_people; 50
select max(javaid) from pkihtts.bv_tb_people_his; 50
when I update tb_people record, I keep getting the 22P02 error in AWS only
UPDATE pkihtts.bv_tb_people
SET lastname='TEST'
WHERE tokenid='49';
ERROR: invalid input syntax for integer: "0A000"
CONTEXT: PL/pgSQL function bvtrigger_fct_tr_people_upd() line 75 at assignment
SQL state: 22P02
but it updated fine in REL staging server and it didn't insert into the history table (tb_people_his) when I update tb_people record.
why the error popping in AWS not in Redhat? How can I resolve the problem?
because AWS has non-numeric error codes and you are trying to save a non numeric value("0A000") into an int variable v_ErrorCode

Concatenating two integer columns works in isolation, but not in a function

Related to my question yesterday which was answered by #a_horse_with_no_name.
The following query works..
SELECT
CAST(FC.Life1monthofbirth AS VARCHAR(2)) || '/' || CAST(FC.Life1yearofbirth AS VARCHAR(4))
FROM
public.factclient FC;
...but when I have essentially the same code in a function...
,CAST(FC.Life1monthofbirth AS VARCHAR(2)) || '/' || CAST(FC.Life1yearofbirth AS VARCHAR(4)) AS Life1DOB
I get this error:
ERROR: operator is not unique: unknown / unknown
LINE 25: ,CAST(FC.Life1monthofbirth AS VARCHAR(2)) || '/' || CAST...
^
HINT: Could not choose a best candidate operator. You might need to add explicit type casts.
I don't understand why the first scenario works, but the second one doesn't. I'm using Postgres version 12 and writing my queries using pgAdmin 4.13
I have added the complete function code below. Apologies if it is not very readable.
CREATE OR REPLACE FUNCTION public.postgres_termpositionrawdata_ver2(
p_provider character varying,
p_date date,
p_correlationid character DEFAULT NULL::bpchar,
p_type character varying DEFAULT NULL::character varying,
p_productexclusionset character varying DEFAULT 'LevelTermPosition'::character varying,
p_ctmoptions character varying DEFAULT 'WOM'::character varying,
p_test character varying DEFAULT 'No'::character varying,
p_testaccountlogon character varying DEFAULT NULL::character varying,
p_averagetopx integer DEFAULT 5,
p_filterquote integer DEFAULT NULL::integer,
p_includeduplicatequotes character varying DEFAULT 'Yes'::character varying,
p_ignoreglobalpermissions character varying DEFAULT 'Yes'::character varying,
p_ignoredefaultproductexclusions character varying DEFAULT 'No'::character varying,
p_ignorelowstartresponseindicator character varying DEFAULT 'No'::character varying,
p_ignorevariableresponseindicator character varying DEFAULT 'No'::character varying)
RETURNS void
LANGUAGE 'plpgsql'
COST 100
VOLATILE
AS $BODY$
--DECLARE CONSTANTS
DECLARE
--DECLARE VARIABLES
v_Status varchar(10) = 'Success';BEGIN
-- assume success
-- SET CorrelationID
IF p_CorrelationId IS NULL THEN p_CorrelationId := public.swf_newid();
END IF;
DROP TABLE IF EXISTS FilteredRequests;
DROP TABLE IF EXISTS FilteredResponses;
DROP TABLE IF EXISTS Ranks;
CREATE TEMP TABLE FilteredRequests AS
SELECT * FROM public.dblink('srv_exchangemart',
'SELECT
FRQ.QuoteID
,DEO.Name AS OrganisationName
,DEO.Postcode AS OrganisationPostcode
,DEO.FRN AS OrganisationFRN
,DDQ.Date AS RequestDate
,DLB.LifeBasis
,DDC.Date AS CommencementDate
,CASE
WHEN FRQ.Term <> 0
THEN CAST (FRQ.Term AS Varchar(5)) || "Years"
WHEN FRQ.TermToAge <> 0
THEN "To Age " || CAST(FRQ.TermToAge AS Varchar(5))
ELSE "Unknown"
END AS PolicyTerm
,DQF.QuotationFor
,LCR.LifeCriticalIllnessRiskRelationship
,TDP.TotalPermanentDisabilityCover
,CB.CommissionBasis
,DCT.CommissionType
,DG1.Gender AS Life1Gender
,CONCAT_WS('|', FC.Life1MonthOfBirth, FC.Life1YearOfBirth) AS Life1DOB
,FC.Life1Age AS Life1Age
,FC.Life1QuarterlyAge
,DS1.Smoker AS Life1Smoker
,DO1.Occupation AS Life1Occupation
,DG2.Gender AS Life2Gender
,CONCAT_WS('|', FC.Life2MonthOfBirth, FC.Life2YearOfBirth) AS Life2DOB
,FC.Life2Age AS Life2Age
,FC.Life2QuarterlyAge
,DS2.Smoker AS Life2Smoker
,DO2.Occupation AS Life2Occupation
,DEP.PanelId
FROM ExchangeMart.dbo.FactRequest FRQ
INNER JOIN ExchangeMart.dbo.dimExchangeOrganisation DEO ON FRQ.ExchangeOrganisationID = DEO.ExchangeOrganisationId
INNER JOIN ExchangeMart.dbo.dimExchangeUser DEU ON FRQ.ExchangeUserId = DEU.ExchangeUserId
INNER JOIN ExchangeMart.dbo.dimLifeBasis DLB ON FRQ.LifeBasisId = DLB.LifeBasisID
INNER JOIN ExchangeMart.dbo.dimTotalPermanentDisabilityCover TDP ON FRQ.TotalPermanentDisabilityCoverId = TDP.TotalPermanentDisabilityCoverID
INNER JOIN ExchangeMart.dbo.dimDate DDQ ON FRQ.QuotationDateID = DDQ.DateID
INNER JOIN ExchangeMart.dbo.dimDate DDC ON FRQ.CommencementDateID = DDC.DateID
INNER JOIN ExchangeMart.dbo.dimExchangePanel DEP ON FRQ.ExchangePanelId = DEP.ExchangePanelId
INNER JOIN ExchangeMart.dbo.dimCommissionBasis CB ON FRQ.CommissionBasisId = CB.CommissionBasisId
INNER JOIN ExchangeMart.dbo.dimCommissionType DCT ON FRQ.CommissionTypeId = DCT.CommissionTypeId
INNER JOIN ExchangeMart.dbo.factClient FC ON FRQ.QuoteID = FC.QuoteID
INNER JOIN ExchangeMart.dbo.dimLifeCriticalIllnessRiskRelationship LCR ON FRQ.LifeCriticalIllnessRiskRelationshipId = LCR.LifeCriticalIllnessRiskRelationshipId
INNER JOIN ExchangeMart.dbo.dimQuotationFor DQF ON FRQ.QuotationForId = DQF.QuotationForId
INNER JOIN ExchangeMart.dbo.dimKeyPerson DKP ON FRQ.KeyPersonId = DKP.KeyPersonId
INNER JOIN ExchangeMart.dbo.dimBenefitBasis DBB ON FRQ.BenefitBasisId = DBB.BenefitBasisId
INNER JOIN ExchangeMart.dbo.dimIntegrator DI ON FRQ.ExchangeIntegratorId = DI.ExchangeIntegratorId
INNER JOIN ExchangeMart.dbo.dimGender DG1 ON FC.Life1GenderID = DG1.GenderID
INNER JOIN ExchangeMart.dbo.dimGender DG2 ON FC.Life2GenderID = DG2.GenderID
INNER JOIN ExchangeMart.dbo.dimSmoker DS1 ON FC.Life1SmokerID = DS1.SmokerID
INNER JOIN ExchangeMart.dbo.dimSmoker DS2 ON FC.Life2SmokerID = DS2.SmokerID
INNER JOIN ExchangeMart.dbo.dimOccupation DO1 ON FC.Life1OccupationId = DO1.OccupationID
INNER JOIN ExchangeMart.dbo.dimOccupation DO2 ON FC.Life2OccupationId = DO2.OccupationID
WHERE DDQ.Date = p_Date
AND FRQ.ProductTypeId IN (53) -- TERM ONLY
AND KeyPerson = "No" -- Not Business
AND DBB.BenefitBasis = "Benefit Led" -- ONLY RETURNS BENEFIT LED QUOTES
AND (DEU.LogonId = p_TestAccountLogon OR (p_TestAccountLogon IS NULL
AND DI.DefaultExclusion = "No"
AND DEO.DefaultExclusion = "No"))
AND ( (p_IncludeDuplicateQuotes = "No" AND FRQ.IsDuplicateQuote = 0)
OR (p_IncludeDuplicateQuotes = "Yes"))
AND (FRQ.QuoteId = p_FilterQuote OR p_FilterQuote IS NULL)
AND ( (p_CTMOptions = "CTM Only" AND DEU.LogonId = "CTM000")
OR (p_CTMOptions = "Exclude CTM" AND DEU.LogonId != "CTM000")
OR (p_CTMOptions = "WOM")
)
')
AS DATA(QuoteID INTEGER, OrganisationName character varying, OrganisationPostcode character varying, OrganisationFRN character varying
, RequestDate date, LifeBasis character varying, CommencementDate date, PolicyTerm character varying, QuotationFor character varying
, LifeCriticalIllnessRiskRelationship character varying, TotalPermanentDisabilityCover character varying, COmmissionBasis character varying
, CommisionType character varying, Life1Gender character varying, Life1DOB character varying, Life1Age INTEGER, Life1QuarterlyAge numeric(12,2)
, Life1Smoker character varying, Life1Occupation character varying, Life2Gender character varying, Life2Age INTEGER
, Life2QuarterlyAge numeric(12,2), Life2Smoker character varying, Life2Occupation character varying);
SELECT * FROM FilteredRequests;
END;
$BODY$;
The error message says you are dividing two items, while your intent is to concatenate them.
It implies that you are running this query using EXECUTE, so the query text is build then run, and the result of the concatenation you wrote is executed, leading to the unexpected division.
You would have to transform the query so that the result of the concatenation - which will be executed - is the desired concatenation. Something like:
EXECUTE 'select fieldA' || '||''/''||' || 'fieldB from myTable';

Order by not working on PostgreSQL function

I am new to PostgreSQl and I have created one function which is mentioned below. What I want that when I am running SELECT query in query tool then it working fine and giving result what I want but when I am executing below function then order by not working. Stageno is a "character varying". How can I fix that ?
-- FUNCTION: public.getauditquestion(integer)
-- DROP FUNCTION public.getauditquestion(integer);
CREATE OR REPLACE FUNCTION public.getauditquestion(
auditid integer)
RETURNS TABLE(audit_ques_id bigint, audit_id integer, activityname character varying, question_id integer, question character varying, answer_type integer, answer_lov integer, answertypename character varying, ok_notok integer, oknotokname character varying, answer_min character varying, answer_max character varying, uom integer, uomname character varying, correct_ans integer, created_by integer, created_date timestamp without time zone, stage character varying, stageno character varying, description character varying, severity character varying, who character varying, how character varying, "when" character varying, "where" character varying)
LANGUAGE 'plpgsql'
COST 100.0
VOLATILE
ROWS 1000.0
AS $function$
BEGIN
Return Query
select am.audit_ques_id, am.audit_id ,ddl3.dd_value AS activityName , am.question_id ,
ddl2.question AS question, am.answer_type, am.answer_lov, ddl4.dd_value AS answerTypeName, am.ok_notok ,
ddl5.dd_value AS okNotOkName, am.answer_min, am.answer_max, am.uom, ddl13.dd_value AS uomname, am.correct_ans,
am.created_by, am.created_date,ddl6.dd_value AS stage, ddl14.dd_value AS stage_no, ddl7.description, ddl8.dd_value AS severity,
ddl9.dd_value AS who , ddl10.dd_value AS how , ddl11.dd_value AS "when" , ddl12.dd_value AS "where"
from audit_ques_detail am left join audit_master ddl1 on ddl1.audit_id=am.audit_id
left join dd_type_details ddl3 on ddl3.dd_id=ddl1.activity_id
left join question_master ddl2 on ddl2.question_id=am.question_id
left join dd_type_details ddl4 on ddl4.dd_id = am.answer_type
left join dd_type_details ddl5 on ddl5.dd_id = am.ok_notok
left join dd_type_details ddl6 on ddl6.dd_id = ddl2.stage
left join question_master ddl7 on ddl7.question_id = am.question_id
left join dd_type_details ddl8 on ddl8.dd_id = ddl2.severity
left join dd_type_details ddl9 on ddl9.dd_id = ddl2.who
left join dd_type_details ddl10 on ddl10.dd_id = ddl2.how
left join dd_type_details ddl11 on ddl11.dd_id = ddl2.when
left join dd_type_details ddl12 on ddl12.dd_id = ddl2.where
left join dd_type_details ddl13 on ddl13.dd_id = am.uom
left join dd_type_details ddl14 on ddl14.dd_id = am.stage_no
where am.audit_id = auditid and am.isActive = 1 ORDER BY cast(ddl14.dd_value AS Integer);
END;
$function$;
ALTER FUNCTION public.getauditquestion(integer)
OWNER TO postgres;

POSTGRESQL PG/PGSQL- Function with params

I'm having some issues making a function in Postgresql, I have this function:
CREATE OR REPLACE FUNCTION public.isp_ticket(_cr integer, _grupo character varying(255), _numero integer, _descripcion text, _resumen character varying(255), _fechaaper timestamp with time zone, _fechacierr timestamp with time zone, _tipo smallint, _apellidousuarioafectado character varying(255), _apellidosolicitante character varying(255), _tenant character varying(255), _metodoreportado character varying(100), _prioridad smallint, _sla character varying(255), _categoria character varying(255), _estado character varying(255), _herramienta_id integer, _asignado character varying(255), _nombresolicitante character varying(255), _nombreusuarioafectado character varying(255))
RETURNS void AS $$
BEGIN
CASE
WHEN _asignado = '' AND _close_date = '' AND _sla = ''
THEN INSERT INTO public.website_ticket(cr, grupo, numero, descripcion, resumen, fechaaper, tipo, apellidousuarioafectado, apellidosolicitante, tenant, metodoreportado, prioridad, categoria, estado, herramienta_id, nombresolicitante, nombreusuarioafectado) VALUES (_cr, _grupo, _numero, _descripcion, _resumen, _fechaaper, _tipo, _apellidousuarioafectado, _apellidosolicitante, _tenant, _metodoreportado, _prioridad, _categoria, estado, _herramienta_id, _nombresolicitante, _nombreusuarioafectado);
WHEN _asignado = '' AND _close_date = ''
THEN INSERT INTO public.website_ticket(cr, grupo, numero, descripcion, resumen, fechaaper, tipo, apellidousuarioafectado, apellidosolicitante, tenant, metodoreportado, prioridad, sla, categoria, estado, herramienta_id, nombresolicitante, nombreusuarioafectado) VALUES (_cr, _grupo, _numero, _descripcion, _resumen, _fechaaper, _tipo, _apellidousuarioafectado, _apellidosolicitante, _tenant, _metodoreportado, _prioridad, _sla, _categoria, _estado, _herramienta_id, _nombresolicitante, _nombreusuarioafectado);
WHEN new_close_date = ''
THEN INSERT INTO public.website_ticket(cr, grupo, numero, descripcion, resumen, fechaaper, tipo, apellidousuarioafectado, apellidosolicitante, tenant, metodoreportado, prioridad, sla, categoria, estado, herramienta_id, asignado,nombresolicitante, nombreusuarioafectado)
VALUES (_cr, _grupo, _numero, _descripcion, _resumen, _fechaaper, _tipo, _apellidousuarioafectado, _apellidosolicitante, _tenant, _metodoreportado, _prioridad, _sla, _categoria, _estado, _herramienta_id, _asignado, _nombresolicitante, _nombreusuarioafectado);
ELSE
UPDATE public.website_ticket SET fechacierr = _fechacierr WHERE numero = _numero;
END CASE;
END;
$$ LANGUAGE plpgsql;
and when I try to use the function doing this:
SELECT public.isp_ticket(924266,
'EUS_Zona V Region',
512294,
'Nombre: Gisselle Espinoza Contreras\nCorreo: gespinoza#bancoripley.cl
\nAnexo: 6221\nUbicación: Valparaiso\nPais: Chile\nMotivo: Usuario indica
que su computador se apagó repentinamente. Se pudo entrar a windows después
de un buen rato, pero no puede ingresar a las aplicaciones que se conecten a
red.\n\nDirección: Plaza Victoria 1646 - Piso 1 - Banco',
'Valparaiso // Computador con problemas de conexión.',
'2018-01-23 15:17:51',
'',
1,
'Espinoza Contreras',
'Espinoza Contreras',
'Ripley',
'Telephone',
3,
'',
'Ripley.Hardware.Desktop.Falla',
'Open',
1,
'',
'Gissel Rose Marie',
'Gissel Rose Marie')
I tried to CAST every value, and it didn't work either, always appear the same error:
ERROR: no existe la función public.isp_ticket(integer, character varying, integer, text, character varying, timestamp with time zone, unknown, integer, character varying, character varying, character varying, character varying, integer, unknown, character varying, character varying, integer, unknown, character varying, character varying)
LINE 1: SELECT public.isp_ticket(
^
SQL state: 42883
Character: 8
I need help how can I fix it?
Forwards thanks everyone!!!
Parameter #7, _fechacierr should be timestamp with time zone. You can not pass '', change it to null (and cast it to timestamp with time zone) if you need empty value.
And it's worth to read how PostgreSQL finds specific function to call, especially:
If any input arguments are unknown, check the type categories accepted
at those argument positions by the remaining candidates. At each
position, select the string category if any candidate accepts that
category. (This bias towards string is appropriate since an
unknown-type literal looks like a string.) Otherwise, if all the
remaining candidates accept the same type category, select that
category; otherwise fail because the correct choice cannot be deduced
without more clues. Now discard candidates that do not accept the
selected type category. Furthermore, if any candidate accepts a
preferred type in that category, discard candidates that accept
non-preferred types for that argument. Keep all candidates if none
survive these tests. If only one candidate remains, use it; else
continue to the next step.

How to approach data warehouse (PostgreSQL) documentation?

We do have a small data warehouse in PostgreSQL database and I have to document all the tables.
I thought I can add a comment to every column and table and use pipe "|" separator to add more attributes. Then I can use information schema and array function to get documentation and use any reporting software to create desired output.
select
ordinal_position,
column_name,
data_type,
character_maximum_length,
numeric_precision,
numeric_scale,
is_nullable,
column_default,
(string_to_array(descr.description,'|'))[1] as cs_name,
(string_to_array(descr.description,'|'))[2] as cs_description,
(string_to_array(descr.description,'|'))[3] as en_name,
(string_to_array(descr.description,'|'))[4] as en_description,
(string_to_array(descr.description,'|'))[5] as other
from
information_schema.columns columns
join pg_catalog.pg_class klass on (columns.table_name = klass.relname and klass.relkind = 'r')
left join pg_catalog.pg_description descr on (descr.objoid = klass.oid and descr.objsubid = columns.ordinal_position)
where
columns.table_schema = 'data_warehouse'
order by
columns.ordinal_position;
It is a good idea or is there better approach?
Unless you must include descriptions of the system tables, I wouldn't try to shoehorn your descriptions into pg_catalog.pg_description. Make your own table. That way you get to keep the columns as columns, and not have to use clunky string functions.
Alternatively, consider adding specially formatted comments to your master schema file, along the lines of javadoc. Then write a tool to extract those comments and create a document. That way the comments stay close to the thing they're commenting, and you don't have to mess with the database at all to produce the report. For example:
--* Used for authentication.
create table users
(
--* standard Rails-friendly primary key. Also an example of
--* a long comment placed before the item, rather than on the
--* the same line.
id serial primary key,
name text not null, --* Real name (hopefully)
login text not null, --* Name used for authentication
...
);
Your documentation tool reads the file, looks for the --* comments, figures out what comments go with what things, and produces some kind of report, e.g.:
table users: Used for authentication
id: standard Rails-friendly primary key. Also an example of a
long comment placed before the item, rather than on the same
line.
name: Real name
login: Name used for authentication
You might note that with appropriate comments, the master schema file itself is a pretty good report in its own right, and that perhaps nothing else is needed.
If anyone interested, here is what I've used for initial load for my small documentation project. Documentation is in two tables, one for describing tables and one for describing columns and constraints. I appreciate any feedback.
/* -- Initial Load - Tables */
drop table dw_description_table cascade;
create table dw_description_table (
table_description_key serial primary key,
physical_full_name character varying,
physical_schema_name character varying,
physical_table_name character varying,
Table_Type character varying, -- Fact Dimension ETL Transformation
Logical_Name_CS character varying,
Description_CS character varying,
Logical_Name_EN character varying,
Description_EN character varying,
ToDo character varying,
Table_Load_Type character varying, --Manually TruncateLoad AddNewRows
Known_Exclusions character varying,
Table_Clover_Script character varying
);
insert into dw_description_table (physical_full_name, physical_schema_name, physical_table_name) (
select
table_schema || '.' || table_name as physical_full_name,
table_schema,
table_name
from
information_schema.tables
where
table_name like 'dw%' or table_name like 'etl%'
)
/* -- Initial Load - Columns */
CREATE TABLE dw_description_column (
column_description_key serial,
table_description_key bigint,
physical_full_name text,
physical_schema_name character varying,
physical_table_name character varying,
physical_column_name character varying,
ordinal_position character varying,
column_default character varying,
is_nullable character varying,
data_type character varying,
logical_name_cs character varying,
description_cs character varying,
logical_name_en character varying,
description_en character varying,
derived_rule character varying,
todo character varying,
pk_name character varying,
fk_name character varying,
foreign_table_name character varying,
foreign_column_name character varying,
is_primary_key boolean,
is_foreign_key boolean,
CONSTRAINT dw_description_column_pkey PRIMARY KEY (column_description_key ),
CONSTRAINT fk_dw_description_table_key FOREIGN KEY (table_description_key)
REFERENCES dw_description_table (table_description_key) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
);
insert into dw_description_column (
table_description_key ,
physical_full_name ,
physical_schema_name ,
physical_table_name ,
physical_column_name ,
ordinal_position ,
column_default ,
is_nullable ,
data_type ,
logical_name_cs ,
description_cs ,
logical_name_en ,
description_en ,
derived_rule ,
todo ,
pk_name ,
fk_name ,
foreign_table_name ,
foreign_column_name ,
is_primary_key ,
is_foreign_key )
(
with
dw_constraints as (
SELECT
tc.constraint_name,
tc.constraint_schema || '.' || tc.table_name || '.' || kcu.column_name as physical_full_name,
tc.constraint_schema,
tc.table_name,
kcu.column_name,
ccu.table_name AS foreign_table_name,
ccu.column_name AS foreign_column_name,
TC.constraint_type
FROM
information_schema.table_constraints AS tc
JOIN information_schema.key_column_usage AS kcu ON (tc.constraint_name = kcu.constraint_name and tc.table_name = kcu.table_name)
JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name
WHERE
constraint_type in ('PRIMARY KEY','FOREIGN KEY')
AND tc.constraint_schema = 'bizdata'
and (tc.table_name like 'dw%' or tc.table_name like 'etl%')
group by
tc.constraint_name,
tc.constraint_schema,
tc.table_name,
kcu.column_name,
ccu.table_name ,
ccu.column_name,
TC.constraint_type
)
select
dwdt.table_description_key,
col.table_schema || '.' || col.table_name || '.' || col.column_name as physical_full_name,
col.table_schema as physical_schema_name,
col.table_name as physical_table_name,
col.column_name as physical_column_name,
col.ordinal_position,
col.column_default,
col.is_nullable,
col.data_type,
null as Logical_Name_CS ,
null as Description_CS ,
null as Logical_Name_EN,
null as Description_EN ,
null as Derived_Rule ,
null as ToDo,
dwc1.constraint_name pk_name,
dwc2.constraint_name as fk_name,
dwc2.foreign_table_name,
dwc2.foreign_column_name,
case when dwc1.constraint_name is not null then true else false end as is_primary_key,
case when dwc2.constraint_name is not null then true else false end as foreign_key
from
information_schema.columns col
join dw_description_table dwdt on (col.table_schema || '.' || col.table_name = dwdt.physical_full_name )
left join dw_constraints dwc1 on ((col.table_schema || '.' || col.table_name || '.' || col.column_name) = dwc1.physical_full_name and dwc1.constraint_type = 'PRIMARY KEY')
left join dw_constraints dwc2 on ((col.table_schema || '.' || col.table_name || '.' || col.column_name) = dwc2.physical_full_name and dwc2.constraint_type = 'FOREIGN KEY')
where
col.table_name like 'dw%' or col.table_name like 'etl%'
)