我正在开展一个项目,该项目涉及计算来自区域内运输成本的产业集群成本结构的百分比。我将为每个行业集群提供一个表格,其中包含详细的成本明细(naics,amount,inregion_amt),包含所有运输naics的查找表cluster_costs
以及我最终想要的汇总表create or replace function clustercosts(tblname text) RETURNS void
AS $$
BEGIN
EXECUTE 'update cluster_costs set tot_cost= (select sum(amount) from '||tblname||'), inregion_transpo = (select sum(inregion_amt) from '||tblname||', transpo_industries where '||tblname||'.naics=transpo_industries.naics) where c_name='||tblname||;
END;
$$ Language plpgsql;
包含每个行业集群的名称(c_name),总成本(tot_cost)和区域内运输成本(inregion_transpo)。该表已填充了所有行业名称,这些名称与相应行业集群的表名相匹配。
由于我需要运行至少15个行业集群,并且可能希望使用较小的数据子集重新运行此代码,我正在尝试创建一个函数。下面的代码创建函数没有错误,但是当我尝试调用它时,我得到一个语法错误(“错误:语法错误在或接近”clustercosts“SQL状态:42601”)
任何人都可以帮助指出我出错的地方吗?
CREATE OR REPLACE FUNCTION udate_clustercosts(tblname text)
RETURNS void AS
$BODY$
BEGIN
EXECUTE format(
'update cluster_costs'
'set tot_cost= (select sum(amount)from %I),'
'inregion_transpo = (select sum(inregion_amt) from %I, transpo_industries where %I.naics=transpo_industries.naics)'
'where c_name=%I',tblname);
END;
$BODY$
LANGUAGE plpgsql;
使用format()的版本给出了同样的错误:
urlConnection.setRequestProperty("Accept","*/*");
答案 0 :(得分:1)
您的问题始于设计阶段。通过适当的数据库设计,您无需为此开始使用动态SQL。
每个行业集群都有一张表......
别。这应该是一个单个表(如cluster_details
),其中FK列(如cluster_id
)引用列出行业集群的表的PK(如industry_cluster
) 。
使用UPDATE
实现计算聚合也是个问题。使用VIEW
(或函数)来获取当前总和。您的基本查询类似于:
SELECT ic.*
, sum(cd.amount) AS sum_amount
, (SELECT sum(inregion_amt)
FROM transpo_industries
WHERE naics = cd.naics) AS sum_inregion_amt
FROM industry_cluster ic
LEFT JOIN cluster_details cd USING (cluster_id)
WHERE ic.name = 'Cluster 1';
至于提出的问题:由于错误是由函数 调用 触发的,并且错误消息明确引用了函数名称,问题在于调用,在问题中缺失。
您的函数定义中还存在其他问题,正如评论中指出的那样 - 这些问题都与您提供的错误消息无关。
答案 1 :(得分:0)
你一直被这个事实所困扰,你想在引用的字符串中使用单引号。您可以使用dollar-quoted string constants as explained in the documentation来避免这种情况。
出现问题的原因是您希望在SQL语句中使用单引号,因为您希望将tblname
的值作为字符串常量传递。
在这里,我使用$a$
在函数体内引用,引用$$
:
create or replace function clustercosts(tblname text) RETURNS void
AS $$
BEGIN
EXECUTE $a$ update cluster_costs set tot_cost= (select sum(amount) from $a$ || tblname || $a$), inregion_transpo = (select sum(inregion_amt) from $a$ || tblname || $a$, transpo_industries where $a$ || tblname || $a$.naics=transpo_industries.naics) where cluster_costs.c_name='$a$ || tblname || $a$'$a$;
END;
$$ language plpgsql;
在美元符号之间插入几乎任何标识符是有效的,并且是函数中嵌套引号的常用模式,与您的情况完全相同。
示例强>
我创建你描述的表:
create table tblname (naics int, amount int, inregion_amt int);
create table transpo_industries (naics int);
create table cluster_costs (c_name text, tot_cost int, inregion_transpo int);
testdb=> SELECT clustercosts('tblname');
clustercosts
--------------
(1 row)
没有错误,SQL已执行。