oracle - 顶点 : Download BLOB from temporary table

标签 oracle plsql oracle-apex

我正在尝试使用 Oracle APEX 4.1.1 构建一个简单的查看应用程序。要显示的信息位于不同数据库的表中,然后是包含 APEX 应用程序访问的架构的数据库。使用 View (RemoteTableView) 和数据库链接访问此远程表。 View 按预期工作,包括 Oracle 无法通过数据库链接选择 LOB 列项目。

根据 Oracle Application Express Advanced Tutorials 中的说明,在 APEX 应用程序中,我定义了一个程序 (DownloadFiles),每当需要从 View 下载 BLOB 时都会运行该程序。

当 APEX 应用程序构建在包含 BLOB 项目的现有表上时,这非常有效,没有问题。

但是,在 RemoteTableView 上,过程略有不同。将额外的代码行添加到 DownloadFiles 过程中,每当调用 View 中的项目进行下载时,将 RemoteTableView 中的实际 BLOB 插入到临时表 (TempTable) 中。然后在 TempTable 上调用 DownloadFile 以下载(现在本地存储的)BLOB。 (这样做是为了避免通过 DB-Link 直接选择 LOB 项)。没有提交。

不幸的是,APEX 应用程序在调用项目下载时失败,并显示“找不到此网页。未找到该网址的网页:.../f?p=101:7:1342995827199601::NO::P7_DOC_ID :3001"。

对这个问题的研究已被证明是徒劳的。插入过程按预期工作(在 PL/SQL Developer 中),并且可以轻松下载任何其他本地表中的任何其他 BLOB。

因此问题是,为什么 APEX 应用程序不能处理这种情况。使用临时表或插入语句时是否有我应该注意的限制?此外,下载 LOB 对象的最佳实践是什么。

详细说明插入行和下载 BLOB 的过程。 (我尝试过不同的方法)。这个 PL/SQL 块被称为'on load before header',:P2_BLOB_ID 用标识符列值填充到 BLOB 列。

DECLARE
  v_mime      VARCHAR2(48);
  v_length    NUMBER(38);
  v_file_name VARCHAR2(38);
  Lob_loc     BLOB;
BEGIN
  DELETE FROM [TemporaryTable];
  --
  INSERT INTO [TemporaryTable]( [attr1]
                              , [attr2]
                              , [blob]
                              , [mime] )
  SELECT [attr1]
  ,      [attr2]
  ,      [blob]
  ,      [mime]
  FROM   [RemoteTableView]
  WHERE  [attr1] = :P2_BLOB_ID
  AND    ROWNUM  = 1;
  --
  SELECT [mime]
  ,      [blob]
  ,      [attr1]
  ,      DBMS_LOB.GETLENGTH( [blob] )
  INTO   v_mime
  ,      lob_loc
  ,      v_file_name
  ,      v_length
  FROM   [TemporaryTable]
  WHERE  [attr1] = :P2_BLOB_ID;
  --
  owa_util.mime_header( nvl(v_mime,'application/octet'), FALSE );
  htp.p('Content-length: ' || v_length);
  htp.p('Content-Disposition:  attachment; filename="'||replace(replace(substr(v_file_name,instr(v_file_name,'/')+1),chr(10),null),chr(13),null)|| '"');
  owa_util.http_header_close;
  wpg_docload.download_file( Lob_loc );
END;

最佳答案

尝试添加 apex_application.stop_apex_enginewpg_docload称呼。这将避免 HTTP header 的进一步输出,可能会因为生成更多的顶点代码而破坏您的下载。

  owa_util.mime_header( nvl(v_mime,'application/octet'), FALSE );
  htp.p('Content-length: ' || v_length);
  htp.p('Content-Disposition:  attachment; filename="'||replace(replace(substr(v_file_name,instr(v_file_name,'/')+1),chr(10),null),chr(13),null)|| '"');
  owa_util.http_header_close;
  wpg_docload.download_file( Lob_loc );
  apex_application.stop_apex_engine;

此外,详细说明:

Are there limitations when working with temporary tables or insert statements that I should be aware of?



是的。但不一定在你的情况下。记住 apex 在数据库 session 方面的工作方式很重要。 Apex 是无状态的,可与连接池配合使用。 apex session 通常不会与 1 个数据库 session 匹配,并且您永远无法保证,例如,在渲染和处理之间使用相同的数据库 session 。在 Understanding Session State Management 的文档中也简要提到了这一点。 ,为了方便复制:

HTTP, the protocol over which HTML pages are most often delivered, is a stateless protocol. A web browser is only connected to the server for as long as it takes to download a complete page. In addition, each page request is treated by the server as an independent event, unrelated to any page requests that happened previously or that may occur in the future. To access form values entered on one page on a subsequent page, the values must be stored as session state. Oracle Application Express transparently maintains session state and provides developers with the ability to get and set session state values from any page in the application.

2.4.1 What Is a Session?

A session is a logical construct that establishes persistence (or stateful behavior) across page views. Each session is assigned a unique identifier. The Application Express engine uses this identifier (or session ID) to store and retrieve an application's working set of data (or session state) before and after each page view.

Because sessions are entirely independent of one another, any number of sessions can exist in the database at the same time. A user can also run multiple instances of an application simultaneously in different browsers.

Sessions are logically and physically distinct from Oracle database sessions used to service page requests. A user runs an application in a single Oracle Application Express session from log in to log out with a typical duration measured in minutes or hours. Each page requested during that session results in the Application Express engine creating or reusing an Oracle database session to access database resources. Often these database sessions last just a fraction of a second.



在全局临时表的情况下,这意味着在许多情况下使用它毫无意义,因为数据仅存在于当前数据库 session 中。这方面的一个例子是,人们将在 onload 某处的 GTT 中加载数据,并意味着在提交后流程或 ajax 调用中使用它。 table 很可能是空的。
然而,Apex 以 apex_collection 的形式提供了替代方案。 ,它将在给定的顶点 session 中临时保存数据。

关于oracle - 顶点 : Download BLOB from temporary table,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22940521/

相关文章:

Java JDBC 连接和 Oracle

oracle - 更改Oracle中列的数据类型

mysql - CLR 汇编 C# DBMS

java - SQLException.getErrorCode 和 SQLCODE

oracle - 调用 Oracle PL/SQL 过程时使用什么编码

oracle - 函数参数的自定义惰性求值/短路的语法

c# - 获取 ORA-01422 : exact fetch returns more than requested number of rows 的原因

security - Oracle Apex 中的授权和用户角色?

jquery - APEX ORDS Rest API 返回内容类型 :text/html

sql - 在oracle中用字符串连接多列