我在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;
我知道错误这个脚本..请帮帮我..顺便说一下我在oracle的新手抱歉..
答案 0 :(得分:3)
您不需要任何循环,您应该跳过所有这些TO_CHAR
,TO_NUMBER
,TO_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
运行
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';
答案 1 :(得分:3)
正如@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
...
或@bone在评论中建议,使用更简单的循环:
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个月
听起来你需要按月对表进行分区,并使用分区交换来将旧月从现场转移到备份表。分区成本更高,但如果您拥有这些数据量,则可能是合理的。
如果没有,您可以考虑将当前表重命名为备份,重新创建原始表,然后只复制两个月的时间。值得您关注的数据。但这是一次性的事情,你仍然存在从主表和备份中老化记录的持续问题。它有自己的依赖关系,约束等问题。
答案 2 :(得分:2)
假设您的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;
答案 3 :(得分:1)
您可以使用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;
答案 4 :(得分:0)
为什么不使用简单的INSERT(例如
)来执行此操作INSERT INTO file_backup
SELECT *
FROM file_core
WHERE datecreated BETWEEN DATE '2017-01-01' AND DATE '2018-01-01';
如果您只是练习PL / SQL和循环,那么,从LOOP中删除COMMIT。 START和END_DATE都应该&#34;转换&#34;使用适当的格式掩码(即yyyymmdd)的数字。 FOR循环索引应该从1到END到START_DATE之间的差异。
[编辑,阅读MT0评论后]
[编辑#2,在阅读了更多评论后]
呸,我的代码是垃圾,应该考虑我在做什么。基本上,如果我打算写得恰到好处,它看起来就像是@Kaushik Nayak,并且两次这样做真的没有意义。