我正在做一个项目,其中包括计算产业集群成本结构中来自区域内运输成本的百分比。我将为每个行业集群提供一个表,其中包含详细的成本细目(naics、want、inregion_amt)、包含所有运输naics的查找表transpo_industries
和最终包含每个行业集群名称(c_name)、总成本(tot_cost)和区域内运输成本(inregion_transpo)的汇总表cluster_costs
。表中已经填充了所有行业名称,这些名称与相应的产业集群的表名相匹配。
由于我需要运行至少15个产业集群,并且可能希望用较小的数据子集重新运行这段代码,所以我正在尝试创建一个函数。下面的代码创建了没有错误的函数,但是当我试图调用它时,我会得到一个语法错误(“错误:语法错误在或接近”集群成本“SQL state: 42601")
有人能帮我指出我哪里错了吗?
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;
使用format()的版本给出了同样的错误:
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;
发布于 2016-03-24 04:41:56
你的问题从设计阶段开始。有了正确的DB设计,首先您就不需要动态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';
至于所问的问题:由于错误是由函数调用触发的,并且错误消息清楚地引用了函数的名称,所以问题在于调用,这在问题中是缺失的。
在您的函数定义中还有其他问题,正如注释中所指出的--这些问题都与您提供的错误消息无关。
发布于 2016-03-22 20:15:35
你被这样的事实咬了,你想在引号中使用单引号。您可以使用如文档所解释的那样,美元引号字符串常量。避免这种情况。
出现此问题是因为您希望在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执行。
https://stackoverflow.com/questions/36160601
复制相似问题