在Oracle中从一个表插入另一个表时,将多个VARCHAR字段组合为1 DATE?

时间:2015-04-14 21:35:08

标签: sql oracle sql-insert toad oracle12c

我正在尝试创建一个简短的脚本,它将获取Table1中的所有字段并将它们插入Table2。基本字段(col1,col2,col3等)我已经被这样的事情所覆盖:

INSERT INTO Table1 (col1, col2, col3, col4, col5, col6, col7)
             SELECT col1, col2, col3, col4, col5, SYSDATE, USER
FROM Table2

对于表1中的col8col9,我有点卡住了。例如,col8/col9DATE数据类型,需要通过将Table1中的col6/col7/col8col9/col10/col11分别组合在一起来插入。其中每个定义如下:

col6/col9  -- VARCHAR2 (2Byte) // Month
col7/col10 -- VARCHAR2 (2Byte) // Day
col8/col11 -- VARCHAR2 (4Byte) // Year

在线查看我尝试过以下内容,但收到"not a valid month"

INSERT INTO Table1 (......)
SELECT ...., TO_DATE(TOCHAR(col6, '00') || TO_CHAR(col7, '00') || TO_CHAR(col8, '9999'), 'MM/DD/YYYY'), .....
FROM Table 2

有没有人知道如何获得我在此之后的内容并将3个特定的VARCHAR字段组合为DATE以作为表1中的1字段插入?

3 个答案:

答案 0 :(得分:2)

如果你的列中的无效值总是为零,正如你在评论中所说的那样,那么你可以使用一个固定值 - 一个虚拟日期,或者可能更合理地将新列留空 - 用case语句:< / p>

SELECT ...., CASE
    WHEN TRIM('0' FROM col6) IS NULL OR TRIM('0' FROM col7) IS NULL
      OR TRIM('0' FROM col8) IS NULL THEN NULL
    ELSE TO_DATE(LPAD(col6, 2, '0') || LPAD(col7, 2, '0') || LPAD(col8, 4, '0'),
      'MMDDYYYY')
  END, ...

TRIM从值中删除零,然后检查是否有任何内容,一次性捕获0和00(以及col8的000和0000)。

LPAD左边用零填充值,所以例如值7将变为07 - 这很重要因为你需要连接的值来匹配日期格式模型,并且没有前导零你终止非常困惑和无效的结果。

请注意,我根本不使用TO_CHAR。由于您的源列已经是字符串,因此您实际上是对数字进行隐式转换,然后显式转换回字符串。使用与LPAD具有相同效果的FM修饰符或TRIM,但会做更多的工作。

作为CTE中一些样本值的快速演示:

with t as (
  select '0' as col6, '0' as col7, '0' as col8 from dual
  union all select '00', '00', '0000' from dual
  union all select '08', '31', '2008' from dual
  union all select '7', '4', '2012' from dual
)
select col6, col7, col8,
  CASE
    WHEN TRIM('0' FROM col6) IS NULL OR TRIM('0' FROM col7) IS NULL
      OR TRIM('0' FROM col8) IS NULL THEN NULL
    ELSE TO_DATE(LPAD(col6, 2, '0') || LPAD(col7, 2, '0') || LPAD(col8, 4, '0'),
      'MMDDYYYY')
  END as my_date
from t;

COL6 COL7 COL8 MY_DATE  
---- ---- ---- ----------
0    0    0              
00   00   0000           
08   31   2008 2008-08-31
7    4    2012 2012-07-04

如果您有其他无效值,这仍然会超过它们 - 例如,09/31/2000,其中月份的天数是错误的。如果您的数据可能属于这种情况,则不清楚。如果是,那么你可以编写一个函数来尝试转换传递的内容,如果它因任何原因无效,则默默返回null。

答案 1 :(得分:1)

我无法肯定地说这是你遇到的,但是当我跑步时

SELECT TO_CHAR(1,'00') FROM dual;

输出在预期的01前面有一个额外的空格。我会在调用TO_CHAR()时将调用打包到TRIM()以删除任何此类空格。

SELECT TRIM(TO_CHAR(1,'00') FROM dual;

我还注意到您的连接与您提供的格式掩码不匹配。您的格式掩码已分隔/&#39; s,但您不是将它们连接到字符串中。您的输出最多为MMDDYYYY。考虑将其添加到连接中,或者更改掩码。

答案 2 :(得分:0)

INSERT INTO Table1 (......) SELECT ...., TO_DATE(TO_CHAR(col6, 'FM00') || TO_CHAR(col7, 'FM00') || TO_CHAR(col8, 'FM9999'), 'MMDDYYYY'), ..... FROM Table 2
恕我直言,这个帮助。您的日期格式字符串错误,也是to_char格式。应该工作......