【问题标题】:Insert into statement not working inside a function (PostgreSQL)插入语句在函数内部不起作用(PostgreSQL)
【发布时间】:2012-07-21 00:19:33
【问题描述】:

我有一个用 PostgreSQL 编写的函数,用于遍历一个大表并将大量值插入到另一个表中。输出很好,显然插入了很多行,但实际上没有值被插入到目标表(我的代码中的“资源”表)中。

我尝试将插入语句放入事务中,但无济于事。我是否缺少某种模糊的访问或权限设置?我在网上找到了几个像我一样这样做的例子,所以我在这个上拉了一点头发......

这是我的功能:

DECLARE
datatype_property record; 
property record;
new_resource_id bigint;
BEGIN  
    RAISE NOTICE 'Starting...';
    FOR datatype_property IN  
      SELECT * FROM datatype_properties
    LOOP  
        RAISE NOTICE 'Trying to insert';


        if not exists(select * from resources where uri = datatype_property.subject_resource) then
              SELECT INTO new_resource_id NEXTVAL('resources_id_seq');  
              INSERT INTO resources (id, uri) VALUES(  
                    new_resource_id,    
                    datatype_property.subject_resource
              );   
            RAISE NOTICE 'Inserted % with id %',datatype_property.subject_resource, new_resource_id;
        end if;
    END LOOP; 

 FOR property IN  
      SELECT * FROM properties 
 LOOP  

        if not exists(select * from resources where uri = property.source_uri) then
                SELECT INTO new_resource_id NEXTVAL('resources_id_seq');
              INSERT INTO resources (id, uri) VALUES(  
                        new_resource_id,
                        resource.source_uri
              ) ;   
                RAISE NOTICE 'Inserted % with id %',resource.source_uri, new_resource_id;
        end if;
        if not exists(select * from resources where uri = property.destination_uri) then
                SELECT INTO new_resource_id NEXTVAL('resources_id_seq');
              INSERT INTO resources (id, uri) VALUES(  
                        new_resource_id,
                        resource.source_uri
              ) ;   
        RAISE NOTICE 'Inserted % with id %',resource.source_uri, new_resource_id;
        end if;
 END LOOP;  
 RETURN;  

结束;

编辑:我已经使用以下链接中的说明激活了 plpgsql 语言:

http://wiki.postgresql.org/wiki/CREATE_OR_REPLACE_LANGUAGE

编辑2:

这段代码:

DECLARE
datatype_property record; 
property record;
new_resource_id bigint;
BEGIN  

    insert into resources (id, uri) values ('3', 'www.google.com');
END

也不行:O

【问题讨论】:

  • 您检查了服务器日志文件吗?也许您的内存不足,或者您达到了可配置的限制(表大小、记录数等)
  • 谢谢,我看看。
  • 好吧,我检查了 postgres.log 文件,内容只是我在 pgadmin III 查询浏览器中可以看到的输出。
  • 它看起来像未提交的事务。某些环境禁用自动提交 - 您必须明确提交。

标签: sql function postgresql stored-procedures insert


【解决方案1】:

您的问题听起来确实像是您没有提交交易(正如 Pavel 指出的那样),或者您用来检查行的工具是例如使用 REPEATABLE READ 作为其隔离级别或某种缓存。

但您的函数一开始并不是一个好的解决方案。在循环中逐行插入总是一个坏主意。这将比进行单次插入要慢得多(并且可扩展性较差)。

如果我没记错的话,这两个循环可以改写成如下语句:

insert into resource (id, uri)
select NEXTVAL('resources_id_seq'),
       dt.subject_resource
from datatype_properties dt
where not exists (select 1
                  from resources r
                  where r.uri = dt.subject_resource);


insert into resources (id, uri)
select nextval('resources_id_seq'),
       p.source_uri
from properties p
where not exists (select 1 
                  from resources r 
                  where r.uri = p.source_uri
                     or r.uri = p.destinatioin_uri);

【讨论】:

  • 是的。非常感谢你们所有的回复。当没有插入数据时,我尝试的第一件事是提交,但我唯一得到的是语法错误。与此同时,我发现你不能在 postgresql 函数中进行显式提交! stackoverflow.com/questions/5448984/… 至于单次插入,我现在使用一个小型 Java 程序进行插入,使用批处理语句和 executeBatch(),所以它遵循 a_horse_with_no_name 的推理。谢谢,已接受回复!
  • 这个故事的寓意是,您应该将存储过程留给真正完全支持它们的 DBMS,例如 Oracle 或 SQL Server(尽管我喜欢开源解决方案)...
  • @JoãoRochadaSilva:PostgreSQL 确实完全支持存储过程(或函数)。显然,在你的环境中有一些你没有说出来的东西。唯一的区别是,Postgres 需要 caller 来处理事务。顺便说一句:正如我所展示的那样,通过批处理进行多次插入仍然比单个插入要慢。
  • 没错,这就是我在正常情况下会做的事情。但是,我的批量插入非常大(大约 1.4 亿行),并且只运行一次。包含插入所需的所有文本的单个文件充其量是笨拙的。关于“完全支持”声明,我指的是在我喜欢的时候调用显式提交的能力(即使很难,它也可能是错误的,但在实际系统中,我们都知道,有时会忽视良好的实践,而倾向于支持 工作)。
猜你喜欢
  • 2011-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-05
  • 2012-05-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多