我想以说我对SQL还是很陌生的方式来开头,但是现在我的工作需要我参与其中。
我有一个包含地形点数据(x,y,z)的数据集。我正在尝试基于此数据构建KNN模型。对于每个点“ P”,我在数据集中最近的P(最近的意思是地理上最近的)中搜索100个点。然后,我将这些点的值取平均值(该平均值称为残差),并将此值添加到“残差”列中的表中。
作为概念验证,我试图简单地遍历表,并将每行中“ resid”列的值设置为1.0。
我的查询是这样的:
CREATE OR REPLACE FUNCTION LoopThroughTable() RETURNS VOID AS '
DECLARE row table%rowtype;
BEGIN
FOR row in SELECT * FROM table LOOP
SET row.resid = 1.0;
END LOOP;
END
' LANGUAGE 'plpgsql';
SELECT LoopThroughTable() as output;
这段代码将执行并成功返回,但是当我检查表时,没有进行任何更改。我怎么了
循环进行逐行更新几乎总是一个坏主意,并且将非常缓慢且无法扩展。您应该真正找到避免这种情况的方法。
说完之后:
您所做的所有功能就是更改内存中列值的值-您只是在修改变量的内容。如果要更新数据,则需要update
声明:
您需要UPDATE
在循环内部使用:
CREATE OR REPLACE FUNCTION LoopThroughTable()
RETURNS VOID
AS
$$
DECLARE
t_row the_table%rowtype;
BEGIN
FOR t_row in SELECT * FROM the_table LOOP
update the_table
set resid = 1.0
where pk_column = t_row.pk_column; --<<< !!! important !!!
END LOOP;
END;
$$
LANGUAGE plpgsql;
请注意,您必须where
在update
语句的主键上添加一个条件,否则将为循环的每次迭代更新所有行。
甲稍微更有效的解决方案是使用一个光标,然后用做更新where current of
CREATE OR REPLACE FUNCTION LoopThroughTable()
RETURNS VOID
AS $$
DECLARE
t_curs cursor for
select * from the_table;
t_row the_table%rowtype;
BEGIN
FOR t_row in t_curs LOOP
update the_table
set resid = 1.0
where current of t_curs;
END LOOP;
END;
$$
LANGUAGE plpgsql;
因此,如果在循环结束后执行UPDATE查询,是否会将更改提交到表中?
否。对该函数的调用在调用事务的上下文中运行。因此,如果在SQL客户端中禁用了自动提交,则需要commit
在运行后执行SELECT LoopThroughTable()
。
请注意,语言名称是一个标识符,请勿在其周围使用单引号。您还应该避免使用诸如row
变量名之类的关键字。
使用美元引号(如我所做的)也使编写函数主体更加容易
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句