我尝试使用httpRequest在insert上发送xmltype表内容,为此我必须将其转换为varchar以在POST中传递它。
这是我的插页:
Insert into CC.MOVIE (SYS_NC_ROWINFO$) values ('<movie>
<id>217530</id>
<title>Midnight Limited</title>
<originalTitle>Midnight Limited</originalTitle>
<release_date>1940-03-20</release_date>
<status>3</status>
<vote_average>0</vote_average>
<vote_count>0</vote_count>
<runtime>0</runtime>
<certification/>
<budget>61</budget>
<tagline>DEATH RIDES THE RAILS! </tagline>
<genres>
<genre>
<idGenre>12</idGenre>
</genre>
<genre>
<idGenre>28</idGenre>
</genre>
<genre>
<idGenre>80</idGenre>
</genre>
</genres>
<actors>
<actor>
<idActor>32218</idActor>
<characterName>Prof. Van Dillon</characterName>
</actor>
<actor>
<idActor>87545</idActor>
<characterName>Joan Marshall</characterName>
</actor>
<actor>
<idActor>90336</idActor>
<characterName>Val Lennon</characterName>
</actor>
<actor>
<idActor>120708</idActor>
<characterName>Capt. Harrigan</characterName>
</actor>
</actors>
<directors>
<director>
<idDirector>120796</idDirector>
</director>
</directors>
</movie>
');
和我的触发器:
create or replace TRIGGER movie_insert
AFTER INSERT ON MOVIE
FOR EACH ROW
DECLARE
doc XMLType;
req utl_http.req;
res utl_http.resp;
url varchar2(4000) := 'http://10.0.2.2:8088/VerifActeur/VerifActeur';
--name varchar2(4000);
buffer varchar2(5000);
BEGIN
SELECT
EXTRACTVALUE(:new.object_value, '/movie/text()')
INTO buffer
FROM DUAL;
--Select CAST(:new.object_value AS VARCHAR2(5000)) into buffer from dual;
-- buffer := :new.object_value.getStringVal();
--doc := :new.sys_nc_rowinfo$;
--buffer:= :new.object_value.extract('/movie/text()').getStringVal();
dbms_output.put_line(buffer);
req := utl_http.begin_request(url, 'POST');
--utl_http.set_header(req, 'user-agent', 'mozilla/4.0');
utl_http.set_header(req, 'content-type', 'text/xml');
utl_http.set_header(req, 'Content-Length', length(buffer));
utl_http.write_text(req, buffer);
res := utl_http.get_response(req);
-- process the response from the HTTP call
begin
loop
utl_http.read_line(res, buffer);
dbms_output.put_line(buffer);
end loop;
utl_http.end_response(res);
exception
when utl_http.end_of_body
then
utl_http.end_response(res);
end;
utl_http.end_request(req);
END;
但是提取值输出什么都没有显示,并且在这种情况下请求不是凹痕(可能是因为长度没有返回)。其他方法正在返回异常。
答案 0 :(得分:1)
您的movie
节点不包含任何文本,它只包含子节点;所以extractvalue
返回null是正确的。顺便提一下,该功能已从11g弃用。您的插入和触发器当前正在查看不同的列,这可能没有帮助,但这可能是问题的错误,而不是您的实际代码。
您可以使用XMLSerialize将XMLType值转换为字符串,varchar或(如果该值对于该数据类型而言太大)CLOB,如:
SELECT XMLSerialize(DOCUMENT :new.object_value AS VARCHAR2(4000) NO INDENT)
INTO buffer
FROM dual;
您还没有说过您正在使用的Oracle版本。在12c之前,SQL上下文意味着你被限制为4000个字符,但你的缓冲区被声明为5000.使用no indent
可能会删除足够的空格,这不是问题,但你可能不得不使用CLOB而不是
使用虚拟表,并插入相同的XMLType列,触发器正在查询(为什么使用数据字典表中的列名?希望您实际上没有在数据字典中添加触发器?)并注释掉现在的HTTP位,产生:
Table MOVIE created.
Trigger MOVIE_INSERT compiled
<movie><id>217530</id><title>Midnight Limited</title><originalTitle>Midnight Limited</originalTitle><release_date>1940-03-20</release_date><status>3</status><vote_average>0</vote_average><vote_count>0</vote_count><runtime>0</runtime><certification/><budget>61</budget><tagline>DEATH RIDES THE RAILS! </tagline><genres><genre><idGenre>12</idGenre></genre><genre><idGenre>28</idGenre></genre><genre><idGenre>80</idGenre></genre></genres><actors><actor><idActor>32218</idActor><characterName>Prof. Van Dillon</characterName></actor><actor><idActor>87545</idActor><characterName>Joan Marshall</characterName></actor><actor><idActor>90336</idActor><characterName>Val Lennon</characterName></actor><actor><idActor>120708</idActor><characterName>Capt. Harrigan</characterName></actor></actors><directors><director><idDirector>120796</idDirector></director></directors></movie>
1 row inserted.
在触发器中执行此操作看起来很尴尬,即使dbms_output
仅用于调试。例如,如果http调用失败会发生什么 - 是否仍然存储新行,或者是异常过滤到调用者并按需要/期望回滚?对于插入的人来说,发生什么事情并不清楚。将插入和http调用放入存储过程可能更加健壮,因此逻辑在一起并且易于查看,而不是通过触发器依赖副作用。然后阻止对表的直接访问(无论如何为插入)并且只允许调用包装程序。只是一个想法...