Sysdate 作为 char 而不是 date
Posted
技术标签:
【中文标题】Sysdate 作为 char 而不是 date【英文标题】:Sysdate as char instead of date 【发布时间】:2017-02-19 20:25:07 【问题描述】:我有一个问题。
我有一个配置表 AB,其中一行标记为“sysdate-360”
col1 ||col2
AB || sysdate-360
BC || sysdate -2
当我编写一个程序从我使用的配置表 AB 中获取日期值时。
v_date varchar(20);
cursor c1 as
select col2 from AB;
then
for ab_date in c1
loop
select ab_date.col2 into v_date from dual;
v_sql := 'delete from any_table where load_date <='||v_date;
execute immediate v_sql ;
commit;
end loop;
程序已编译,但当我执行时出现以下错误
ORA-01722: 无效号码 ORA-06512: 在“程序”第 46 行 ORA-06512: 在第 1 行 01722. 00000 - “无效号码” *原因: *行动:
sysdate -360 被视为 char 但不是日期,因为 SYSDATE 本身就是一个日期,对吧?
请帮忙。
【问题讨论】:
大概load_date
是一个日期类型。由于您的光标查询看起来不正确,您的混淆有点令人困惑 - 真的是from config_table where col1 = AB
吗?并且您没有指出哪一行对应于错误中的第 46 行。 col1
是什么数据类型,因为你让它看起来像一个 varchar?如果它是一个字符串,AB
是一个数字,并且您没有将它括在引号中,并且 col1
的值不是 数字吗?我认为错误来自游标查询,与日期无关......
我认为您应该对传递给execute immediate
的v_sql
中的值进行调试。这可能会揭示您的问题,例如 v_sql
中缺少空格。
【参考方案1】:
如果你只处理表达式SYSDATE +/- N
我建议修改配置表如下
ID SYSDATE_OFFSET
-- --------------
AB -360
BC -2
所以你有一个 sysdate 的数字偏移量,可以这样查询:
select sysdate + (select SYSDATE_OFFSET from config where id = 'AB') s_360
from dual;
S_360
-----------------
25.02.16 21:46:50
所以你可以用上面的查询打开一个游标。
如果您无法更改表格 - 定义一个删除字符串 sysdate
并转换为数字的视图!
【讨论】:
让我检查一下,我可以更改配置表。 我现在有另一个问题。我的 v_sql 现在正在给出正确的查询,但是当我在立即执行中运行它时,它给了我以下错误。 00911. 00000 - “无效字符” *原因:标识符不能以字母和数字以外的任何 ASCII 字符开头。在第一个字符之后也允许使用 $#_。用双引号括起来的标识符可以包含除双引号之外的任何字符。替代引号 (q'#...#') 不能使用空格、制表符或回车作为分隔符。 @AmjathAK 使用新配置,您根本不需要立即执行。将 DELTE 中的偏移量作为绑定变量传递。 我必须找到我的表的分区名称,所以所有内容都写在 v_sql 中,包括日期。所以我对 v_sql 的删除查询是从 my_table 分区 (partitionname) 中删除,其中 load_date 要遵循@MarmiteBomber 的建议,您可以在光标上添加一列sysdate - ab.sysdate_offset as maxdate
,然后您的删除语句将类似于delete sometable t where t.load_date < ab_date.maxdate
。无需动态 SQL。但是,分区的要求是什么?【参考方案2】:
这对我来说看起来很不错。但是为什么选择v_date
呢?你从光标中得到一个字符串,你可以直接连接:
for ab_date in c1 loop
v_sql := 'delete from any_table where load_date <=' || ab_date.col2;
execute immediate v_sql ;
commit;
end loop;
最后,这只是两个字符串 'delete from any_table where load_date <='
和 'sysdate-360'
的串联,这使得 'delete from any_table where load_date <= sysdate-360'
- 正是您想要的 SQL 字符串。
(如果使用正确的列名,例如 date_expression
而不是 col2
,这看起来会更好。)
更详细的解释:光标为您获取字符串“sysdate-360”。查询select ab_date.col2 into v_date from dual;
就是v_date := ab_date.col2;
。但是v_date
是字符串吗?如果不是,你会得到一个转换错误,因为 'sysdate-360' 只是一个字符串,仅此而已。如果您希望 DBMS 看到字符串包含“sysdate”,它也恰好是当前时间的系统变量的名称,然后神奇地转换它,那么您期望很高。
【讨论】:
是的,我的 'sysdate-360" 被视为字符串,v_date 是定义的日期。如何使 dbms 将 ssydate 视为系统定义的而不是字符串。 当您使用它来构建 SQL 字符串 时,您无需执行任何操作。我的脚本不适合你吗?【参考方案3】:试试 to_date 函数
TO_DATE(v_date)
【讨论】:
希望你能好好阅读我的问题。我有一个读取数据的游标,包含“sysdate-360”的列被读取为字符而不是日期 col2 有什么类型?我没有先看到你的程序。你会把它格式化成代码吗?以上是关于Sysdate 作为 char 而不是 date的主要内容,如果未能解决你的问题,请参考以下文章