ORA-01401: 对于 CHAR 列,插入的值太大

Posted

技术标签:

【中文标题】ORA-01401: 对于 CHAR 列,插入的值太大【英文标题】:ORA-01401: inserted value too large for column CHAR 【发布时间】:2016-07-24 08:41:05 【问题描述】:

我对 SQL Oracle 还是很陌生,目前我的班级正在学习批量加载。我几乎明白这个想法,但是我很难让它读取我的所有记录。

这是我的 SQL 文件;

PROMPT Creating Table 'CUSTOMER'
CREATE TABLE CUSTOMER
(CustomerPhoneKey CHAR(10) PRIMARY KEY
,CustomerLastName VARCHAR(15)
,CustomerFirstName VARCHAR(15)
,CustomerAddress1 VARCHAR(15)
,CutomerAddress2 VARCHAR(30)
,CustomerCity VARCHAR(15)
,CustomerState VARCHAR(5)
,CustomerZip VARCHAR(5)
);

快速简单。现在这是我要加载数据的控制文件

LOAD DATA
INFILE Customer.dat
INTO TABLE Customer
FIELDS TERMINATED BY"|"
(CustomerPhoneKey, CustomerLastName, CustomerFirstName, CustomerAddress1 , CutomerAddress2, CustomerCity, CustomerState, CustomerZip)

然后是数据文件

2065552123|Lamont|Jason|NULL|161 South Western Ave|NULL|NULL|98001
2065553252|Johnston|Mark|Apt. 304|1215 Terrace Avenue|Seattle|WA|98001
2065552963|Lewis|Clark|NULL|520 East Lake Way|NULL|NULL|98002
2065553213|Anderson|Karl|Apt 10|222 Southern Street|NULL|NULL|98001
2065552217|Wong|Frank|NULL|2832 Washington Ave|Seattle|WA|98002
2065556623|Jimenez|Maria|Apt 13 B|1200 Norton Way|NULL|NULL|98003

问题是,只有最后一条记录

2065556623|Jimenez|Maria|Apt 13 B|1200 Norton Way|NULL|NULL|98003

正在加载中。其余的都在我的坏文件中

所以我查看了我的日志文件,我得到的错误是

记录 1:被拒绝 - 表 CUSTOMER 中的 CUSTOMERZIP 列出错。 ORA-01401: 插入的值对于列来说太大

记录 2:被拒绝 - 表 CUSTOMER 的 CUSTOMERZIP 列出错。 ORA-01401: 插入的值对于列来说太大

记录 3:被拒绝 - 表 CUSTOMER 中的 CUSTOMERZIP 列出错。 ORA-01401: 插入的值对于列来说太大

记录 4:被拒绝 - 表 CUSTOMER 的 CUSTOMERZIP 列出错。 ORA-01401: 插入的值对于列来说太大

记录 5:被拒绝 - 表 CUSTOMER 的 CUSTOMERZIP 列出错。 ORA-01401: 插入的值对于列来说太大

表客户:1 行已成功加载。 5 行未加载到期 到数据错误。 0 行未加载,因为所有 WHEN 子句均已加载 失败的。 0 行未加载,因为所有字段均为空。

关于这个问题。我看到 CustomerZip 是问题所在,最初我将它作为 CHAR(5) - 我这样做是因为我对数据类型的理解是,对于像邮政编码这样的数值,我不会用它进行算术运算,因此最好将其存储为 CHAR。另外我最初没有使用 VARCHAR2 (5),因为看到它是一个邮政编码,我不希望值变化,它应该总是 5。现在也许我只是误解了这一点。因此,如果有人可以解决这个问题,那就太棒了。

我的第二个问题是“我该如何解决这个问题?”鉴于以上对这些数据类型的理解,为什么 CHAR(5) NOR VARCHAR2(5) 起作用是没有意义的。因为我对两者都有相同的错误。

一条记录(最后一条)实际上有效,这更没有意义。

提前感谢您的帮助

【问题讨论】:

我应该提一下,我试图和我的教授一起去上班,但是她无法识别问题,只是指示我做一个完全不同的表(基本上忽略这个问题,做一个更简单的一)。这对我来说似乎很简单,我想知道我做错了什么,所以我求助于你们 您是否在 Windows 中创建了数据文件,并在 Linux/Unix 中运行 SQL*Loader? 是的,我在 Unix 中运行了 sqlldr 【参考方案1】:

您的数据文件有额外的不可见字符。我们看不到原始文件,但推测它是在 Windows 中创建的,并且具有 CRLF new line separators;并且您在只需要换行符 (LF) 的 UNIX/Linux 环境中运行 SQL*Loader。回车 (CR) 字符仍在文件中,Oracle 将它们视为文件中 ZIP 字段的一部分。

最后一行没有 CRLF(或任何换行符),因此在该行 - 并且 该行 - ZIP 字段被视为 5 个字符,对于所有其他的被视为六个,例如98001^M.

你可以阅读更多关于默认行为in the documentation:

在基于 UNIX 的平台上,如果未指定 terminator_string,则 SQL*Loader 默认为换行符 \n。

在 Windows NT 上,如果没有指定 terminator_string,则 SQL*Loader 使用 \n 或 \r\n 作为记录终止符,这取决于它在数据文件中首先找到的终止符。这意味着,如果您知道数据文件中的一条或多条记录已\n 嵌入到某个字段中,但您希望将 \r\n 用作记录终止符,那么您必须指定它。

李>

如果您在 vi 或 vim 等编辑器中打开数据文件,您会看到那些额外的 ^M 控制字符。

有几种方法可以解决此问题。可以修改文件;最简单的做法是将数据复制并粘贴到在您将运行 SQL*Loader 的环境中创建的新文件中。如果您愿意,可以使用实用程序来转换行尾,例如dos2unix。或者您的 Windows 编辑器可能能够在没有 CR 的情况下保存文件。您还可以按照 Ditto 的建议在数据文件中添加额外的字段分隔符。

或者您可以通过更改 INFILE 行来告诉 SQL*Loader 期待 CRLF:

LOAD DATA
INFILE Customer.dat "str '\r\n'"
INTO TABLE Customer
...

...不过,如果您确实提供了在 Linux 中创建的没有 CR 字符的文件,那么这将导致问题。

【讨论】:

我认为他还可以添加一个额外的管道“|”在决赛之后,不是吗?然后甲骨文将忽略“额外字段”..因为它没有被列出去任何地方。 :) 或者他可以指定:RECORDS DELIMITED BY newline; ?? :) (虽然仍然可能无法从 Windows 中发现额外的 CR/LF) @Ditto - 这是默认设置,我认为问题在于对 NEWLINE 的解释...... 好吧,你们说的绝对有道理。那么我实际上可以重新制作数据文件而不输入任何换行符吗?让它成为一条带有“|”的连续线分隔符。或者我可以添加其中一个“也由换行符分隔”的语句 嗯,你需要一种方法来告诉它“嘿,这是一条新记录”……那是(默认情况下)换行符。在 Windows 中:CR+LF .. 在 Unix 中只是 LF ...【参考方案2】:

几乎所有 UNIX 机器上都有一个实用程序 dos2unix。如果你运行它,你可以输出去除了 DOS/Windows CRLF 组合的数据文件。

【讨论】:

以上是关于ORA-01401: 对于 CHAR 列,插入的值太大的主要内容,如果未能解决你的问题,请参考以下文章

Access数据库通过ODBC导出到Oracle的两个小问题ora-24801Ora-01401

在 DB2 中将 CHAR 插入 DATE

为 NUMBER 列插入 NULL

列值采用 0 或 nul 代替 HIVE 中的 char 数据类型

MySQL—— 数据库的约束 (nulluniqueprimary keydefaultforeign keycheck)

在Oracle中插入后返回标识列的值