在 PostgreSQL 函数中,是不是可以检查列值是不是与给定参数值匹配?
Posted
技术标签:
【中文标题】在 PostgreSQL 函数中,是不是可以检查列值是不是与给定参数值匹配?【英文标题】:In a PostgresSQL function, is it possible to check if a column value matches a given parameter value?在 PostgreSQL 函数中,是否可以检查列值是否与给定参数值匹配? 【发布时间】:2020-01-10 09:04:09 【问题描述】:在 SQL Server 存储过程的 WHERE 子句中,我可以这样做:
WHERE (*column_value* = @some_parameter OR @some_parameter IS NULL)
当我尝试在 PostgreSQL 函数中做同样的事情时,它会抛出一个错误。例如:
WHERE(FRQ.QuoteId = p_FilterQuote OR p_FilterQuote IS NULL)
产生错误:***列“p_FilterQuote”不存在。
输入参数 p_FilterQuote 在函数顶部声明和初始化,如下所示:
p_filterquote integer DEFAULT NULL::integer
必须有一种方法可以在 WHERE 子句中“使用”输入参数。
整个功能代码如下所示。
-- 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$;
【问题讨论】:
请edit您的问题并添加函数的完整定义。你想要做的当然是可能的:dbfiddle.uk/… 您在字符串中使用参数,因此它不再是该查询的参数,而是列名(用于“其他数据库”) - 您将需要动态 SQL。使用外部表(通过 FDW)将使这种方式更容易。或者也许不使用多个数据库,而是使用多个模式,那么你就不需要这个开始了。 好的,我会阅读有关 Foreign Tables 的内容。我已经有一个外部数据包装器和一个外部服务器。 如果您从 SQL Server 迁移,通常最好使用模式而不是数据库,那么您不需要类似的东西 我明白了。因此,将所有表都放在一个数据库中,但对以前在不同数据库中的表使用不同的模式。我想这也是相当可扩展的。 【参考方案1】:SQL 语句在远程数据库上执行,并且不执行任何类型的参数替换。
你必须自己做:
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;
【讨论】:
以上是关于在 PostgreSQL 函数中,是不是可以检查列值是不是与给定参数值匹配?的主要内容,如果未能解决你的问题,请参考以下文章
PostgreSQL 查询帮助:如何检查多个列的值是不是同时增加/减少
检查PostgreSQL jsonb列是不是包含某些字符串的快速方法