PL/SQL - 使用异常插入数据
PL/SQL - Inserting data using Exception
我有以下未正确执行的代码。我将数据存储在 date_tmp (varchar) 中,其中包括日期和非日期。我想将该列中的日期移至 date_run(日期),非日期的数据将移至注释 (varchar) 列。当我 运行 下面的代码时,整个数据集都被移到了注释中。 运行 当我编辑掉插入语句并且只是 运行 dbms_outputline 行时它很好。我可能做错了什么?
DECLARE
CURSOR getrow IS
SELECT a.id, a.date_tmp
FROM mycolumn a
WHERE a.id < 1300;
v_date date;
BEGIN
FOR i in getrow LOOP
BEGIN
v_date := to_date(i.date_tmp, 'mm/dd/yy');
INSERT INTO mycolumn a(a.date_run)
VALUES(i.date_tmp);
EXCEPTION
WHEN OTHERS THEN
--dbms_output.put_line(i.date_tmp);
update mycolumn a
SET a.comments = i.date_tmp
where a.id = i.id;
END;
END LOOP;
END;
您尝试将 varchar i.date_tmp
插入日期字段。而是插入 v_date
.
...
INSERT INTO mycolumn a (a.date_run)
VALUES(v_date);
...
但其实你的要求是出招。这实际上需要更新。所以我认为你真正想做的是:
...
update mycolumn a
SET a.date_run = v_date
where a.id = i.id
...
实际上你可以有一个函数来检查你是否有一个有效的日期,然后你可以使用一个简单的更新语句来处理整个任务。
create or replace function is_a_date(i_date varchar2, i_pattern varchar2)
return date
is
begin
return to_date(i_date, i_pattern);
exception
when others return null;
end is_a_date;
使用该函数,您可以编写两个更新语句
update mycolumn
set date_run = to_date(date_tmp,'dd/mm/yy')
where is_a_date(date_tmp, 'dd/mm/yy') is not null;
update mycolumn
set comment = date_tmp
where is_a_date(date_tmp, 'dd/mm/yy') is null;
我设计函数的方式可以让您以多种方式使用它,因为它 returns 您是一个日期或 null 但如果 varchar 不符合日期模式也不例外。
您有一个 insert
,看起来您需要一个 update
,就像在异常处理程序中一样。所以只需将其更改为:
v_date := to_date(i.date_tmp, 'mm/dd/yy');
update mycolumn
set date_run = v_date
where id = i.id;
或者您可以将其缩短为:
update mycolumn
set date_run = to_date(i.date_tmp, 'mm/dd/yy')
where id = i.id;
@hol 解决方案对我来说是最好的方法。
如果您可以使用简单的 SQL 语句来完成,请避免始终可以循环和过程,您的代码会更快。
另外,如果你总是有一个数据固定格式,你可以使用 PL/SQL 函数 is_a_date 函数并用 SQL 做所有事情......但是代码变得有点丑陋像这样:
update mycolumn
set date_run = to_date(date_tmp,'dd/mm/yy')
where substr(date_tmp,1,2) between '1' and '31'
and substr(date_tmp,4,2) between '1' and '12'
and substr(date_tmp,7,2) between '00' and '99';
如果您需要更快的查询速度或者您在 date_tmp 中有大量数据,因为函数 is_a_date 是确定性的(总是 returns 给定相同的值X,Y,的值),你可以为它创建一个索引:
create index mycol_idx on mycolumn(is_a_date(date_tmp));
并且当您使用该函数时,Oracle 将使用您的索引,就像在那些选择中一样:
SELECT a.id, a.date_tmp
FROM mycolumn a
WHERE a.id < 1300
and is_a_date(a.date_tmp) is not null;
SELECT a.id, a.date_tmp
FROM mycolumn a
WHERE a.id < 1300
and (is_a_date(a.date_tmp) is not null and is_a_date(a.date_tmp)>sysdate-5);
我有以下未正确执行的代码。我将数据存储在 date_tmp (varchar) 中,其中包括日期和非日期。我想将该列中的日期移至 date_run(日期),非日期的数据将移至注释 (varchar) 列。当我 运行 下面的代码时,整个数据集都被移到了注释中。 运行 当我编辑掉插入语句并且只是 运行 dbms_outputline 行时它很好。我可能做错了什么?
DECLARE
CURSOR getrow IS
SELECT a.id, a.date_tmp
FROM mycolumn a
WHERE a.id < 1300;
v_date date;
BEGIN
FOR i in getrow LOOP
BEGIN
v_date := to_date(i.date_tmp, 'mm/dd/yy');
INSERT INTO mycolumn a(a.date_run)
VALUES(i.date_tmp);
EXCEPTION
WHEN OTHERS THEN
--dbms_output.put_line(i.date_tmp);
update mycolumn a
SET a.comments = i.date_tmp
where a.id = i.id;
END;
END LOOP;
END;
您尝试将 varchar i.date_tmp
插入日期字段。而是插入 v_date
.
...
INSERT INTO mycolumn a (a.date_run)
VALUES(v_date);
...
但其实你的要求是出招。这实际上需要更新。所以我认为你真正想做的是:
...
update mycolumn a
SET a.date_run = v_date
where a.id = i.id
...
实际上你可以有一个函数来检查你是否有一个有效的日期,然后你可以使用一个简单的更新语句来处理整个任务。
create or replace function is_a_date(i_date varchar2, i_pattern varchar2)
return date
is
begin
return to_date(i_date, i_pattern);
exception
when others return null;
end is_a_date;
使用该函数,您可以编写两个更新语句
update mycolumn
set date_run = to_date(date_tmp,'dd/mm/yy')
where is_a_date(date_tmp, 'dd/mm/yy') is not null;
update mycolumn
set comment = date_tmp
where is_a_date(date_tmp, 'dd/mm/yy') is null;
我设计函数的方式可以让您以多种方式使用它,因为它 returns 您是一个日期或 null 但如果 varchar 不符合日期模式也不例外。
您有一个 insert
,看起来您需要一个 update
,就像在异常处理程序中一样。所以只需将其更改为:
v_date := to_date(i.date_tmp, 'mm/dd/yy');
update mycolumn
set date_run = v_date
where id = i.id;
或者您可以将其缩短为:
update mycolumn
set date_run = to_date(i.date_tmp, 'mm/dd/yy')
where id = i.id;
@hol 解决方案对我来说是最好的方法。 如果您可以使用简单的 SQL 语句来完成,请避免始终可以循环和过程,您的代码会更快。 另外,如果你总是有一个数据固定格式,你可以使用 PL/SQL 函数 is_a_date 函数并用 SQL 做所有事情......但是代码变得有点丑陋像这样:
update mycolumn
set date_run = to_date(date_tmp,'dd/mm/yy')
where substr(date_tmp,1,2) between '1' and '31'
and substr(date_tmp,4,2) between '1' and '12'
and substr(date_tmp,7,2) between '00' and '99';
如果您需要更快的查询速度或者您在 date_tmp 中有大量数据,因为函数 is_a_date 是确定性的(总是 returns 给定相同的值X,Y,的值),你可以为它创建一个索引:
create index mycol_idx on mycolumn(is_a_date(date_tmp));
并且当您使用该函数时,Oracle 将使用您的索引,就像在那些选择中一样:
SELECT a.id, a.date_tmp
FROM mycolumn a
WHERE a.id < 1300
and is_a_date(a.date_tmp) is not null;
SELECT a.id, a.date_tmp
FROM mycolumn a
WHERE a.id < 1300
and (is_a_date(a.date_tmp) is not null and is_a_date(a.date_tmp)>sysdate-5);