通过 SAS 从 ORACLE DB 导入 blob
Import blob through SAS from ORACLE DB
祝大家一天愉快。
我在上周的工作中遇到了一个大问题。
这是一笔交易:
我需要通过 SAS 从 ORACLE 数据库下载 exel 文件 (blob)。
我正在使用:
第一步我需要从 oracle 获取数据。我用的构造(blob文件将近100kb):
proc sql;
connect to oracle;
create table SASTBL as
select * from connection to oracle (
select dbms_lob.substr(myblobfield,1,32767) as blob_1,
dbms_lob.substr(myblobfield,32768,32767) as blob_2,
dbms_lob.substr(myblobfield,65535,32767) as blob_3,
dbms_lob.substr(myblobfield,97302,32767) as blob_4
from my_tbl;
);
quit;
结果是:
blob_1 = 70020202020202...02
blob_2 = 02020202020...02
blob_3 = 02020202...02
我不明白为什么该字段由“02”(整个文件)组成
并且sas中任意变量的长度都是1024(而不是37767)$HEX2024格式。
如果我要:
dbms_lob.substr(my_blob_field,2000,900) 来自同一个对象,结果将更接近事实:
斑点 = "A234ABC4536AE7...."
问题是:1. 如何通过 SAS 从 blob 字段中正确获取二进制数据?我的错误是什么?
谢谢。
编辑 1:
我得到了信息,但最大字符串是 2000 kb。
PROC SQL 使用 SQL 与 SAS 数据集交互(创建表、查询表、聚合数据、外部连接等)。该过程主要遵循 ANSI 标准和一些 SAS 特定扩展。每个 RDMS 都扩展了 ANSI,包括 Oracle 及其 XML 处理,例如将内容保存在 blob 列中。 SAS 可能无法正确读取特定于 Oracle 的(非 ANSI)二进制大对象类型。通常 SAS 处理字符串、数字、日期时间和少数其他类型。
作为替代方案,考虑将来自 Oracle 的 XML 内容保存为 .xml
文件并使用 SAS 的 XML 引擎将内容读入 SAS 数据集:
** STORING XML CONTENT;
libname tempdata xml 'C:\Path\To\XML\File.xml';
** APPEND CONTENT TO SAS DATASET;
data Work.XMLData;
set tempdata.NodeName; /* CHANGE TO REPEAT PARENT NODE OF XML. */
run;
在 CONNECT 语句(或 LIBNAME 语句)上使用 DBMAX_TEXT 选项以获得最多 32,767 个字符。默认值可能是 1024。
添加为另一个答案,因为我还不能发表评论...您遇到的问题是 dbms_lob.substr 的 return 实际上是一个 varchar,因此 SAS 将其限制为 2,000。为避免这种情况,您可以将其包装在 to_clob( ... ) AND 中,如前所述设置 DBMAX_TEXT 选项。
另一种选择如下...
下面的代码是使用大型 CLOB 检索单个记录的有效方法。它不是计算将 clob 拆分成多少个字段以产生非常宽的记录,而是将其拆分为多行。请参阅底部的预期输出。
免责声明:虽然有效,但可能效率不高,即可能无法很好地扩展到多行,因此普遍接受的方法是行流水线 PLSQL。话虽这么说,如果你不能做一个程序,下面的内容让我摆脱了困境...
PROC SQL;
connect to oracle (authdomain=YOUR_Auth path=devdb DBMAX_TEXT=32767 );
create table clob_chunks (compress=yes) as
select *
from connection to Oracle (
SELECT id
, key
, level clob_order
, regexp_substr(clob_value, '.{1,32767}', 1, level, 'n') clob_chunk
FROM (
SELECT id, key, clob_value
FROM schema.table
WHERE id = 123
)
CONNECT BY LEVEL <= regexp_count(clob_value, '.{1,32767}',1,'n')
)
order by id, key, clob_order;
disconnect from oracle;
QUIT;
预期输出:
ID KEY CHUNK CLOB
1 1 1 short_clob
2 2 1 long clob chunk1of3
2 2 2 long clob chunk2of3
2 2 3 long clob chunk3of3
3 3 1 another_short_one
解释:
- DBMAX_TEXT 告诉 SAS 调整 clob 字段的默认值 1024。
- 正则表达式 .{1,32767} 告诉 Oracle 至少匹配一次但不超过 32767 次。这会拆分输入并捕获长度可能小于 32767 的最后一个块。
- regexp_substr 正在从 clob (param2) 的开头从 clob (param1) 中拉出一个块,跳到第“级别”出现 (param3) 并将 clob 视为一个大块字符串 (param4 'n').
- connect by 重新运行正则表达式来计算块数以停止级别递增超出 clob 的末尾。
参考文献:
- SAS KB article for DBMAX_TEXT
- Oracle docs for REGEXP_COUNT
- Oracle docs for REGEXP_SUBSTR
- Oracle regex syntax
- Whosebug example of regex splitting
祝大家一天愉快。 我在上周的工作中遇到了一个大问题。 这是一笔交易:
我需要通过 SAS 从 ORACLE 数据库下载 exel 文件 (blob)。 我正在使用:
第一步我需要从 oracle 获取数据。我用的构造(blob文件将近100kb):
proc sql; connect to oracle; create table SASTBL as select * from connection to oracle ( select dbms_lob.substr(myblobfield,1,32767) as blob_1, dbms_lob.substr(myblobfield,32768,32767) as blob_2, dbms_lob.substr(myblobfield,65535,32767) as blob_3, dbms_lob.substr(myblobfield,97302,32767) as blob_4 from my_tbl; ); quit;
结果是:
blob_1 = 70020202020202...02
blob_2 = 02020202020...02
blob_3 = 02020202...02
我不明白为什么该字段由“02”(整个文件)组成
并且sas中任意变量的长度都是1024(而不是37767)$HEX2024格式。 如果我要:
dbms_lob.substr(my_blob_field,2000,900) 来自同一个对象,结果将更接近事实: 斑点 = "A234ABC4536AE7...."
问题是:1. 如何通过 SAS 从 blob 字段中正确获取二进制数据?我的错误是什么?
谢谢。
编辑 1:
我得到了信息,但最大字符串是 2000 kb。
PROC SQL 使用 SQL 与 SAS 数据集交互(创建表、查询表、聚合数据、外部连接等)。该过程主要遵循 ANSI 标准和一些 SAS 特定扩展。每个 RDMS 都扩展了 ANSI,包括 Oracle 及其 XML 处理,例如将内容保存在 blob 列中。 SAS 可能无法正确读取特定于 Oracle 的(非 ANSI)二进制大对象类型。通常 SAS 处理字符串、数字、日期时间和少数其他类型。
作为替代方案,考虑将来自 Oracle 的 XML 内容保存为 .xml
文件并使用 SAS 的 XML 引擎将内容读入 SAS 数据集:
** STORING XML CONTENT;
libname tempdata xml 'C:\Path\To\XML\File.xml';
** APPEND CONTENT TO SAS DATASET;
data Work.XMLData;
set tempdata.NodeName; /* CHANGE TO REPEAT PARENT NODE OF XML. */
run;
在 CONNECT 语句(或 LIBNAME 语句)上使用 DBMAX_TEXT 选项以获得最多 32,767 个字符。默认值可能是 1024。
添加为另一个答案,因为我还不能发表评论...您遇到的问题是 dbms_lob.substr 的 return 实际上是一个 varchar,因此 SAS 将其限制为 2,000。为避免这种情况,您可以将其包装在 to_clob( ... ) AND 中,如前所述设置 DBMAX_TEXT 选项。
另一种选择如下...
下面的代码是使用大型 CLOB 检索单个记录的有效方法。它不是计算将 clob 拆分成多少个字段以产生非常宽的记录,而是将其拆分为多行。请参阅底部的预期输出。
免责声明:虽然有效,但可能效率不高,即可能无法很好地扩展到多行,因此普遍接受的方法是行流水线 PLSQL。话虽这么说,如果你不能做一个程序,下面的内容让我摆脱了困境...
PROC SQL;
connect to oracle (authdomain=YOUR_Auth path=devdb DBMAX_TEXT=32767 );
create table clob_chunks (compress=yes) as
select *
from connection to Oracle (
SELECT id
, key
, level clob_order
, regexp_substr(clob_value, '.{1,32767}', 1, level, 'n') clob_chunk
FROM (
SELECT id, key, clob_value
FROM schema.table
WHERE id = 123
)
CONNECT BY LEVEL <= regexp_count(clob_value, '.{1,32767}',1,'n')
)
order by id, key, clob_order;
disconnect from oracle;
QUIT;
预期输出:
ID KEY CHUNK CLOB
1 1 1 short_clob
2 2 1 long clob chunk1of3
2 2 2 long clob chunk2of3
2 2 3 long clob chunk3of3
3 3 1 another_short_one
解释:
- DBMAX_TEXT 告诉 SAS 调整 clob 字段的默认值 1024。
- 正则表达式 .{1,32767} 告诉 Oracle 至少匹配一次但不超过 32767 次。这会拆分输入并捕获长度可能小于 32767 的最后一个块。
- regexp_substr 正在从 clob (param2) 的开头从 clob (param1) 中拉出一个块,跳到第“级别”出现 (param3) 并将 clob 视为一个大块字符串 (param4 'n').
- connect by 重新运行正则表达式来计算块数以停止级别递增超出 clob 的末尾。
参考文献:
- SAS KB article for DBMAX_TEXT
- Oracle docs for REGEXP_COUNT
- Oracle docs for REGEXP_SUBSTR
- Oracle regex syntax
- Whosebug example of regex splitting