首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Oracle内部日期转换: ORA-00932和奇怪的东西

Oracle内部日期转换: ORA-00932和奇怪的东西
EN

Stack Overflow用户
提问于 2016-12-16 20:37:03
回答 1查看 127关注 0票数 0

在这里,我们的许多开发人员正在使用Oracle分层子查询来构建日期列表,例如:

代码语言:javascript
复制
WITH mydays AS (
  SELECT CAST( TO_DATE('20161201', 'YYYYMMDD') + ROWNUM AS DATE) AS d
  FROM DUAL CONNECT BY TO_DATE('20161201', 'YYYYMMDD') + ROWNUM <= to_date('20161215', 'YYYYMMDD')
) 

对我来说它看起来像是演员。AS DATE应该是无用的,因为我们要将一个日期转换为一个日期,对吧?实际上并非如此。如果我像这样创建并填充一个表(我的演示需要一个连接...):

代码语言:javascript
复制
create table t(d date, i number);
insert into t(d, i) values (to_date('20161204', 'YYYYMMDD'), 1);
commit;

在没有强制转换的情况下,尝试使用这样的连接进行查询,我得到了以下解释计划:

代码语言:javascript
复制
WITH mydays AS (
  SELECT  TO_DATE('20161201', 'YYYYMMDD') + ROWNUM  AS d
  FROM DUAL CONNECT BY TO_DATE('20161215', 'YYYYMMDD') + ROWNUM <= to_date('20161201', 'YYYYMMDD')
) 
select mydays.d from mydays join t on t.d = mydays.d;

代码语言:javascript
复制
----------------------------------------------------------------------------------------
| Id  | Operation                       | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                |      |     1 |    15 |     6  (17)| 00:00:01 |
|*  1 |  HASH JOIN                      |      |     1 |    15 |     6  (17)| 00:00:01 |
|   2 |   VIEW                          |      |     1 |     6 |     2   (0)| 00:00:01 |
|   3 |    COUNT                        |      |       |       |            |          |
|*  4 |     CONNECT BY WITHOUT FILTERING|      |       |       |            |          |
|   5 |      FAST DUAL                  |      |     1 |       |     2   (0)| 00:00:01 |
|   6 |   TABLE ACCESS FULL             | T    |     1 |     9 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - access("T"."D"=INTERNAL_FUNCTION("MYDAYS"."D"))
4 - filter(TO_DATE(' 2016-12-15 00:00:00', 'syyyy-mm-dd 
          hh24:mi:ss')+ROWNUM<=TO_DATE(' 2016-12-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))

使用强制转换时,INTERNAL_FUNCTION()就消失了:

代码语言:javascript
复制
4 - filter(TO_DATE(' 2016-12-01 00:00:00', 'syyyy-mm-dd 
          hh24:mi:ss')+ROWNUM<=TO_DATE(' 2016-12-15 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))

我用谷歌搜索了一下,发现转换应该在两种内部日期格式之间进行,这两种格式由id为12和13的Oracle内部处理,因为我们可以找到对DUMP()的调用。没有演员阵容:

代码语言:javascript
复制
Typ=13 Len=8: 7,224,12,4,0,0,0,0

对于演员阵容:

代码语言:javascript
复制
Typ=12 Len=7: 120,116,12,4,1,1,1

这解释了使用强制转换比不使用(!)的转换更少。

但当我使用绑定变量时,情况会变得更糟。如果我想要得到这个SQL的解释计划:

代码语言:javascript
复制
WITH mydays AS (
  SELECT  TO_DATE(:beginning, 'YYYYMMDD') + ROWNUM  AS d
  FROM DUAL CONNECT BY TO_DATE(:end, 'YYYYMMDD') + ROWNUM <= to_date(:beginning, 'YYYYMMDD')
) 
select mydays.d from mydays join t on t.d = mydays.d

我得到一个错误: ORA-00932:不一致的数据类型:预期的日期得到了数字。如果我添加了施法魔法,这个错误就被修复了。我知道当我生成一个计划时,所有的绑定变量都被认为是VARCHAR2。但是对于TO_DATE(),我们应该只处理DATE,对吧?这个数字是从哪里来的?

如果你能给我任何解释,谢谢你,因为我的大脑开始被那些奇怪的东西弄得乱七八糟。

EN

回答 1

Stack Overflow用户

发布于 2016-12-16 21:24:20

非常有趣的查询获取日历。更易于阅读:

代码语言:javascript
复制
SELECT to_date('20160101','yyyymmdd') + LEVEL 
  FROM DUAL 
CONNECT BY LEVEL <= 90;

您是在寻找解决方案,还是只是在调查当地的问题?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41184593

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档