我有一个从php调用的postgres函数。函数的第一行在表中插入一些内容,将键返回到本地。
CREATE OR REPLACE FUNCTION uploadConfirm( bname text, ul text, pt text,
shp text, vzn integer,
gpsLoc double precision[], meta text ) RETURNS void AS $uC$
DECLARE
file Files%ROWTYPE;
shape text[];
locat_id integer;
crl_id integer;
uid integer DEFAULT(null);
iid integer;
make text;
model text;
BEGIN
insert into interact(webRequest) values(bname) RETURNING interact_id into iid;
shape := regexp_split_to_array( shp, E'x' ); -- get info for single file
--meta := encode( meta , 'base64' );
RAISE NOTICE 'uploadConfirm: % : % : % : % : % : % : %' , bname, ul, pt, shp , vzn, gpsLoc , meta ;
locat_id := getLocationId( gpsLoc[1],gpsLoc[2],gpsLoc[3] );
--RAISE 'meta: %d' , meta;
make := (regexp_matches( meta , $$Make's+='s+'([^']+)'$$ ))[1];
model := (regexp_matches( meta , $$Model's+='s+'([^']+)'$$ ))[1];
--RAISE '>> shape , loc_id, make, model: % : % : % : % ' , shape, loc_id, make, model ;
crl_id := getCurlId( '' , ul, pt, vzn );
select * into file from Files where Files.basename = bname;
IF NOT FOUND THEN
insert into Files
( basename , curl_id ) VALUES
( bname , crl_id ) returning * into file;
ELSE
update Files set ( curl_id ) =
( crl_id )
where basename = bname;
update interact set ( uid ) = ( file.uid ) where interact_id = iid;
END IF;
INSERT INTO Metadata VALUES ( meta , make , model , cast(shape[1] as integer), cast( shape[2] as integer) , file.file_id, locat_id );
EXCEPTION
WHEN not_null_violation THEN
perform reportError( 'File(bname='|| bname || ' no location data:' || SQLERRM, iid );
END;
$uC$ LANGUAGE plpgsql;
此函数有一个异常子句,它调用如下所示的错误报告函数。
CREATE OR REPLACE FUNCTION reportError( msgX text, iidX integer default(null) ) returns void as $re$
DECLARE
BEGIN
if iidX is null then
SELECT currval(pg_get_serial_sequence('interact', 'interact_id')) into iidX;
END IF;
insert into err (msg,iid) values ( msgX,iidX );
END;
$re$ LANGUAGE plpgsql;
它调用另一个函数reportError,该函数将有关异常的信息(包括文件名bname和关键字iid)放在表中。
当我查看时,尽管错误信息在表中,但它应该在表中。interact表中缺少带有相应键的条目。只有当bname为null时,插入interact才会失败;但是,bname(!=NULL)的值出现在错误消息中,因此我捕获的失败必须在代码的后面。
在我看来,插入交互不应该回滚,但显然是。
我不明白为什么这个条目不在interact表中。有人能解释为什么&帮我想办法把它送到那里。
谢谢。
postgres文档说这是应该发生的事情
When an error is caught by an EXCEPTION clause, the local variables
of the PL/pgSQL function remain as they were when the error occurred, but
all changes to persistent database state within the block are rolled back.
我应该对自己说RTM。
我可以在异常处理程序中重做插入操作。