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_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
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,而且确实没有意义。