尝试通过 PL/SQL 导出 Oracle 的日期为 0000-00-00

Trying to export a Oracle via PL/SQL gives a date of 0000-00-00(尝试通过 PL/SQL 导出 Oracle 的日期为 0000-00-00)
本文介绍了尝试通过 PL/SQL 导出 Oracle 的日期为 0000-00-00的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我继承了一个 Oracle .dmp 文件,我正在尝试将其导入 CSV,以便将其加载到 MySQL 中.

I have inherited an Oracle .dmp file which I'm trying to get into CSV so that I can load it into MySQL.

描述了我使用的一般方法 这里.不过,我在一行中遇到了问题.它包含 5544-09-14 的日期,如下所示:

The general approach I'm using is described here. I'm having a problem with one row though. It contains a date of 5544-09-14 like so:

alter session set nls_date_format = 'dd-MON-yyyy';
select OID, REF, TRADING_DATE From LOAN WHERE REF = 'XXXX';

OID REF                  TRADING_DATE
--- -------------------- ------------
1523 XXXX                 14-SEP-5544

这是来自未验证输入日期的旧系统的垃圾数据.我想知道为什么 我的 PL/SQL 导出数据函数会卡住不过这个值?

This is garbage data from the legacy system which didn't validate the input dates. I'm wondering why my PL/SQL function to export the data chokes on this value though?

它导出了 TRADING_DATE 值为0000-00-00T00:00:00"的那一行,我不知道为什么?

It exports that row with a TRADING_DATE value of '0000-00-00T00:00:00' and I'm not sure why?

SELECT dump(TRADING_DATE) FROM LOAN WHERE REF = 'XXXX';

DUMP(TRADING_DATE)
--------------------------------------------------------------------------------
Typ=12 Len=7: 44,156,9,14,1,1,1

SELECT to_char(trading_date, 'YYYYMMDDHH24MISS') FROM LOAN WHERE REF = 'XXXX';
TO_CHAR(TRADIN
--------------
00000000000000

推荐答案

存储在该列中的值不是有效日期.dump 的第一个字节应该是世纪,根据 Oracle 支持说明 69028.1 以excess-100"表示法存储,这意味着它的值应该是 100 + 实际世纪;所以 1900 是 119,2000 是 120,5500 是 155.所以 44 代表 -5600;您存储的日期似乎实际上代表 5544-09-14 BC.由于 Oracle 仅支持年份介于 -4713 和 +9999 之间的日期,因此无法识别.

The value stored in that column is not a valid date. The first byte of the dump should be the century, which according to Oracle support note 69028.1 is stored in 'excess-100' notation, which means it should have a value of 100 + the actual century; so 1900 would be 119, 2000 would be 120, and 5500 would be 155. So 44 would represent -5600; the date you have stored appears to actually represent 5544-09-14 BC. As Oracle only supports dates with years between -4713 and +9999, this isn't recognised.

你可以很容易地重新创建它;最棘手的一点是首先将无效日期输入数据库:

You can recreate this fairly easily; the trickiest bit is getting the invalid date into the database in the first place:

create table t42(dt date);

Table created.

declare
    d date;
begin
    dbms_stats.convert_raw_value('2c9c090e010101', d);
    insert into t42 (dt) values (d);
end;
/

PL/SQL procedure successfully completed.

select dump(dt), dump(dt, 1016) from t42;

DUMP(DT)
--------------------------------------------------------------------------------
DUMP(DT,1016)
--------------------------------------------------------------------------------
Typ=12 Len=7: 45,56,9,14,1,1,1
Typ=12 Len=7: 2d,38,9,e,1,1,1

所以这有一行包含与您相同的数据.使用 alter session 我可以看到看起来像一个有效日期:

So this has a single row with the same data you do. Using alter session I can see what looks like a valid date:

alter session set nls_date_format = 'DD-Mon-YYYY';
select dt from t42;

DT
-----------
14-Sep-5544

alter session set nls_date_format = 'YYYYMMDDHH24MISS';
select dt from t42;

DT
--------------
55440914000000

但如果我使用显式日期掩码,它只会得到零:

But if I use an explicit date mask it just gets zeros:

select to_char(dt, 'DD-Mon-YYYY'), to_char(dt, 'YYYYMMDDHH24MISS') from t42;

TO_CHAR(DT,'DD-MON-Y TO_CHAR(DT,'YY
-------------------- --------------
00-000-0000          00000000000000

如果我运行你的程序:

exec dump_table_to_csv('T42');

生成的 CSV 具有:

The resultant CSV has:

"DT"
"0000-00-00T00:00:00"

我认为不同之处在于那些试图显示日期的人坚持使用内部日期数据类型 12,而那些显示零的人使用外部数据类型 13,如注释 69028.1 中所述.

I think the difference is that those that attempt to show the date are sticking with internal date data type 12, while those that show zeros are using external data type 13, as mentioned in note 69028.1.

简而言之,您的程序没有做错任何事情,它尝试导出的日期在内部无效.除非您知道它应该是什么日期,考虑到您的起点,这似乎不太可能,否则我认为除了猜测或忽略它之外,您无能为力.除非,也许,您知道数据是如何插入的,并且可以弄清楚它是如何损坏的.

So in short, your procedure isn't doing anything wrong, the date it's trying to export is invalid internally. Unless you know what date it was supposed to be, which seems unlikely given your starting point, I don't think there's much you can do about it other than guess or ignore it. Unless, perhaps, you know how the data was inserted and can work out how it got corrupted.

我认为它更有可能来自 OCI 程序,而不是我在这里所做的;这个原始"技巧最初来自 此处.您可能还想查看注释 331831.1.和前面的问题有些相关.

I think it's more likely to be from an OCI program than what I did here; this 'raw' trick was originally from here. You might also want to look at note 331831.1. And this previous question is somewhat related.

这篇关于尝试通过 PL/SQL 导出 Oracle 的日期为 0000-00-00的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

SQL to Generate Periodic Snapshots from Transactions Table(用于从事务表生成定期快照的SQL)
MyBatis support for multiple databases(MyBatis支持多个数据库)
Oracle 12c SQL: Missing column Headers in result(Oracle 12c SQL:结果中缺少列标题)
SQL query to find the number of customers who shopped for 3 consecutive days in month of January 2020(查询2020年1月连续购物3天的客户数量)
How to get top 10 data weekly (This week, Previous week, Last month, 2 months ago, 3 month ago)(如何每周获取前十大数据(本周、前一周、上个月、2个月前、3个月前))
Select the latest record for an Id per day - Oracle pl sql(选择每天ID的最新记录-Oracle pl SQL)