循环插入日期日期日期为日时间戳Oracle



im在Oracle中执行查询。我需要每天插入数据以这样的循环:

DECLARE
   start_date      NUMBER;
   end_date        NUMBER;
   business_date   VARCHAR2 (8);
BEGIN
   start_date := TO_NUMBER (TO_CHAR (TO_DATE ('2017-01-01', 'yyyy-MM-dd')));
   end_date := TO_NUMBER (TO_CHAR (TO_DATE ('2018-01-01', 'yyyy-MM-dd')));
   FOR cur_r IN start_date .. end_date
   LOOP
      INSERT INTO file_backup
         SELECT *
           FROM file_core
          WHERE TO_NUMBER (TO_CHAR (TO_DATE (datecreated, 'yyyy-MM-dd')))>=start_date+cur_r
            AND TO_NUMBER (TO_CHAR (TO_DATE (datecreated, 'yyyy-MM-dd')))<=end_date;
            COMMIT;
   END LOOP;
END;

我不知道这个脚本。

正如@boneist指出的那样,您使用数字的操作行不通。您应该保留数据类型,并与相同数据类型的值进行比较。

假设您有合法的需要在循环中执行此操作,您可以做这样的事情:

BEGIN
  FOR r IN (
    select date '2017-01-01' + level -1 as this_date
    from dual
    connect by level <= date '2018-01-01' - date '2017-01-01'
  )
  LOOP
    INSERT INTO file_backup
      SELECT *
        FROM file_core
       WHERE datecreated >= r.this_date
         AND datecreated < r.this_date + 1;
    COMMIT;
  END LOOP;
END;
/

或数据类型实际上是时间戳,而不是评论中建议的日期,例如:

BEGIN
  FOR r IN (
    select timestamp '2017-01-01 00:00:00'
      + (level -1) * interval '1' day as this_timestamp
    from dual
    connect by level <= extract(day from timestamp '2018-01-01 00:00:00'
      - timestamp '2017-01-01 00:00:00')
  )
  LOOP
    INSERT INTO file_backup
      SELECT *
        FROM file_core
       WHERE datecreated >= r.this_timestamp
         AND datecreated < r.this_timestamp + interval '1' day;
    COMMIT;
  END LOOP;
END;
/

...尽管您可能想处理连接查询的条件,例如

  FOR r IN (
    select timestamp '2017-01-01 00:00:00'
      + numtodsinterval(level -1, 'DAY') as this_timestamp
    from dual
    connect by timestamp '2017-01-01 00:00:00'
      + numtodsinterval(level -1, 'DAY') < timestamp '2018-01-01 00:00:00'
  )
  LOOP
  ...

或@boneist在评论中建议的,更简单的循环:

BEGIN
  FOR num_days in 0..(date '2018-01-01' - date '2017-01-01' - 1)
  LOOP
    INSERT INTO file_backup
      SELECT *
        FROM file_core
       WHERE datecreated >= timestamp '2017-01-01 00:00:00'
               + numtodsinterval(num_days, 'DAY')
         AND datecreated < timestamp '2017-01-01 00:00:00'
               + numtodsinterval(num_days + 1, 'DAY');
    COMMIT;
  END LOOP;
END;
/

这种方法的主要问题是重新启动性。如果循环中有错误部分,您不能仅重新运行它,因为您将插入重复。

多个插入物和提交的效率也不如单个插入物,甚至多个插入物和单个提交。如果您没有足够的撤消空间来允许单个交易完成所有需要的工作,则应修复数据库配置以允许这样做,而不是围绕它进行工作并可能损害数据完整性。

我需要备份此表。在新表中仅插入2个月

听起来您需要按月划分桌子,然后使用分区掉期将过去从现场演出转移到备用桌子。分区成本更高,但是如果您有这些数据量,则可能是合理的。

如果您可以考虑将当前表重命名为备份,重新创建原始表格,并仅复制要回到这一点的两个月的数据价值。但这是一件一次性的事情,您仍然存在持续的衰老记录的问题,从主桌出来并进入备份。它在依赖项,约束等方面有自己的问题。

您不需要任何循环,您应该跳过所有这些TO_CHARTO_NUMBERTO_DATE转换。尝试以下操作:

INSERT INTO file_backup
SELECT *
FROM file_core
WHERE datecreated BETWEEN DATE '2017-01-01' AND DATE '2018-01-01';

也许datecreated的时间值与00:00:00不同,在这种情况下,您应该运行

INSERT INTO file_backup
SELECT *
FROM file_core
WHERE TRUNC(datecreated) BETWEEN DATE '2017-01-01' AND DATE '2018-01-01';

或如果datecreated是VARCHAR2数据类型而不是DATE Run

INSERT INTO file_backup
SELECT *
FROM file_core
WHERE TO_DATE(datecreated, 'YYYY-MM-DD') BETWEEN DATE '2017-01-01' AND DATE '2018-01-01';

假设您的datecreated列是数据类型DATE,而您只需要表的一行的副本,那么您不需要PL/SQL:

INSERT INTO file_backup
  SELECT *
  FROM file_core
  WHERE datecreated BETWEEN DATE '2017-01-01' AND DATE '2018-01-01';
COMMIT;

您可以使用DATE字面来设置start_date和end_date并使用这样的 loop

DECLARE
   start_date      NUMBER;
   end_date        NUMBER;
BEGIN
   start_date := DATE '2017-01-01';
   end_date   := DATE '2018-01-01';
   FOR cur_r IN 0 .. (end_date - start_date)
   LOOP
      INSERT INTO file_backup
         SELECT *
           FROM file_core
          WHERE  TRUNC (datecreated) = start_date + cur_r;
   COMMIT;                              
   END LOOP;
 END;

为什么不使用简单的插入(例如

(进行
INSERT INTO file_backup
   SELECT *
     FROM file_core
    WHERE datecreated BETWEEN DATE '2017-01-01' AND DATE '2018-01-01';

如果您只是在练习PL/SQL并循环,那么请删除提交循环。启动和end_date都应使用适当的格式掩码(即yyyymmdd("转换"到数字。因为循环的索引应从1到end_date之间的差异。

[编辑,阅读MT0的评论后]

[编辑#2,阅读了更多评论后]

bah,我的代码是垃圾,应该考虑我在做什么。基本上,如果我打算正确地写它,那看起来像@kaushik nayak's,而且确实没有意义。

最新更新