我在存储过程中发现了一种奇怪的行为,该存储过程在将标准化报告历史记录到我们的 Oracle 数据库中时在 99% 的情况下都能正常工作。
对于某些报告,我收到错误 ORA-01489:字符串连接的结果太长。该过程创建一个包含所有数据的临时表,并添加复合主哈希键和哈希业务键。
如果我只执行
SELECT
声明而不执行 CREATE TABLE temp_tbl
对于导致麻烦的报告,它就可以正常工作。 CREATE TABLE ... AS
功能是否有任何已知限制?
sql_cmd varchar2(32767);
BEGIN
sql_cmd:= 'CREATE TABLE temp_tbl AS (
SELECT
ID_00010, ID_00020, ID_00030, ID_00040, to_timestamp(ID_00050, 'YYYY-MM-DD hh24:mi:ss') as ID_00050, ID_00060, [...],
to_timestamp("PARSER_TIMESTAMP", 'YYYY-MM-DD hh24:mi:ss') as "PARSER_TIMESTAMP",
CAST(STANDARD_HASH(
STANDARD_HASH(
UTL_RAW.CAST_TO_RAW(ID_00010|| ID_00020|| ID_00030|| ID_00040|| ID_00050|| [...])
|| UTL_RAW.CAST_TO_RAW(ID_11040|| ID_12000|| ID_13000|| ID_20000|| [...])
, 'SHA1')
||
STANDARD_HASH(UTL_RAW.CAST_TO_RAW(ID_20160|| ID_20170|| ID_20180|| ID_20190|| ID_20200|| [...])
|| UTL_RAW.CAST_TO_RAW(ID_20680|| ID_20690|| ID_20700|| ID_20710|| [...])
, 'SHA1')
||
STANDARD_HASH(UTL_RAW.CAST_TO_RAW(ID_30780|| ID_30790|| ID_30800|| [...])
|| UTL_RAW.CAST_TO_RAW(ID_30980|| ID_30990|| [...])
|| UTL_RAW.CAST_TO_RAW(ID_31820|| ID_31830|| [...])
|| UTL_RAW.CAST_TO_RAW(ID_32680|| ID_32690|| [...])
|| UTL_RAW.CAST_TO_RAW(ID_50710|| ID_50720|| [...])
, 'SHA1')
, 'SHA1') as CHAR(160)) as PK_HASH_KEY,
CAST(STANDARD_HASH(utl_raw.cast_to_raw(id_20000), 'SHA1') as CHAR(160)) as BK_HASH_KEY
FROM stg_tbl
)'
EXECUTE IMMEDIATE sql_cmd;
END;
附加信息
cmd_sql
字符串的长度为13969,不应成为问题的原因,因为它是静态文本并且适用于相同类型的其他报告。
由于 4000 个字符的串联限制,我将 PK_HASH_KEY 生成拆分为多个“子哈希键”。导致上述错误的报告的子哈希键远低于限制:
错误报告-ORA-01489:字符串连接结果太长 ORA-06512: 在“DATAENGINEER.LOAD_PROC”,第 38 行 ORA-06512: 在 2号线 01489. 00000 - “字符串连接的结果太长” *原因:字符串拼接结果超过最大长度。 *操作:确保结果小于最大尺寸。
将问题分成更小的问题并解决更小的问题。
您有疑问:
CREATE TABLE ... AS SELECT ...
错误可能出现在
SELECT ...
中,因此请尝试运行 SELECT
语句,而不是在 PL/SQL 中并且不创建表:
SELECT ID_00010,
ID_00020,
ID_00030,
ID_00040,
to_timestamp(ID_00050, 'YYYY-MM-DD hh24:mi:ss') as ID_00050,
ID_00060,
-- ...,
to_timestamp("PARSER_TIMESTAMP", 'YYYY-MM-DD hh24:mi:ss') as "PARSER_TIMESTAMP"
FROM stg_tbl
如果运行(应该),那么问题出在散列中,因此运行用于第一个散列的串联:
SELECT UTL_RAW.CAST_TO_RAW(
ID_00010
|| ID_00020
|| ID_00030
|| ID_00040
|| ID_00050
-- || ...
)
FROM stg_tbl
重复代码的下一部分,直到找到有问题的代码部分。