【问题标题】:ORA-01858: a non-numeric character was found when a numeric was expectedORA-01858: 在需要数字时发现非数字字符
【发布时间】:2018-04-10 18:50:45
【问题描述】:

我创建了以下两个表。

CREATE TABLE DELETE_CUSTOM
(
 column1 varchar2(30),
 column2 varchar2(30)
)

CREATE TABLE DELETE_CUSTOM_HIST
(
 column1 varchar2(30),
 column2 varchar2(30),
 ARCHIVAL_DATE DATE
)

我曾经像下面这样将数据插入DELETE_CUSTOM_HIST

INSERT INTO DELETE_CUSTOM_HIST
      (SELECT DE.*, to_date('12/31/2017','mm/dd/yyyy')
         FROM DELETE_CUSTOM DE);

现在,我必须在两个表中添加一个新列。

ALTER TABLE DELETE_CUSTOM ADD column3 VARCHAR2(30);
ALTER TABLE DELETE_CUSTOM_HIST ADD column3 VARCHAR2(30);

如果我尝试使用以下 INSERT 语句将数据插入DELETE_CUSTOM_HIST 表, 我收到 ORA-01858 错误。

INSERT INTO DELETE_CUSTOM_HIST
      (SELECT DE.*, to_date('12/31/2017','mm/dd/yyyy')
         FROM DELETE_CUSTOM DE);
--ORA-01858: a non-numeric character was found when a numeric was expected.

我需要对我的 INSERT 语句进行哪些更改才能解决此问题。

注意:上面的插入语句在PLSQL包中。上面两张表其实有 许多列。我刚刚提到了几列,以简单的方式解释我的问题。

【问题讨论】:

  • 为什么不在DELETE_CUSTOM 表上使用触发器而不是SELECT 查询?
  • 这里的问题是你懒得修改你的代码来写所有的列。看起来您(或您自己)之前的某个人通过在插入的任何地方都包含select * from 来粗心地编写包/程序,现在您应该在所有这些地方进行更改。我建议您将此代码更改为一次性活动,以便您未来的工作变得更加简单,即每当添加新列时,您只需将其添加到代码中即可。这是一个更好的做法。
  • 仅供参考,您可以使用 DATE'2017-12-31'(ANSI DATE 文字)代替 to_date('12/31/2017','mm/dd/yyyy')

标签: sql oracle


【解决方案1】:
INSERT INTO DELETE_CUSTOM_HIST(column1,column2,column3)
      (SELECT de.column1,de.column2,de.column3, 
to_date('12/31/2017','mm/dd/yyyy')
         FROM DELETE_CUSTOM DE);

明确写入列列表并重试。

【讨论】:

  • 这是一种直截了当的方法。正如我所提到的,我在表格中有很多列。因此,我正在寻找一种更好的方法,其中不明确提及列名。
  • 我什至可以删除表并重新创建它以匹配我的 INSERT 语句。
  • 创建表 delete_custom_hist 作为 select * from delete_custom 。再次创建第二个表,然后添加archival_date 列。然后再试一次。但在更改现有的 delete_custom_hist 表名之前,如果您不想丢失其中的数据。
  • 明确列出列名更好的方法。您不希望每次需要添加列时都删除并重新创建表。
【解决方案2】:

你有:

CREATE TABLE DELETE_CUSTOM_HIST
(
 column1 varchar2(30),
 column2 varchar2(30),
 ARCHIVAL_DATE DATE,
 column3 varchar2(30)
);

尝试INSERT

一个varchar2 类型列(COLUMN3 列的DELETE_CUSTOM 表)列到

date 类型列(DELETE_CUSTOM_HIST 表的 ARCHIVAL_DATE 列)。

引发的错误是由于与 varchar2date 不匹配造成的。

【讨论】:

    【解决方案3】:

    两点。第一个是始终明确列出此类语句的列。不要在生产代码中使用*——除非你真的知道自己在做什么。

    INSERT INTO DELETE_CUSTOM_HIST (column1, column2, column3, archival_date)
         SELECT DE.column1, DE.column2, DE.column3, DATE '2017-12-31'
         FROM DELETE_CUSTOM DE;
    

    注释(除了列出列):

    • SELECT 周围的括号不合适。
    • 使用日期文字。 Oracle 在这里支持 ANSI 标准,使用它。
    • 您确定只需要存档日期的日期部分吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多