AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 56172
Accepted
Amir Pashazadeh
Amir Pashazadeh
Asked: 2014-01-06 05:07:03 +0800 CST2014-01-06 05:07:03 +0800 CST 2014-01-06 05:07:03 +0800 CST

Oracle 使用波斯历按时间间隔分区

  • 772

Oracle 在 DDL 查询中支持波斯 (Jalali) 日历,我可以轻松地说:

select to_char(register_date, 'YYYY-MM-DD', 'nls_calendar=persian')
  from my_table;

我创建了一个表:

create table test_temp_times (
  id number(18) not null,
  xdate date not null,
  str varchar2(20))
partition by range(xdate)
interval(NUMTOYMINTERVAL(1, 'MONTH'))
(partition p0 values less than (to_date('13920101', 'YYYYMMDD', 'nls_calendar=persian')))
enable row movement;

该表是正常创建的,但是当我向其中添加记录并且 oracle 创建新分区时,分区是:

create table TEMP_TIMES (
  id    NUMBER(18) not null,
  xdate DATE not null,
  str   VARCHAR2(20)
)
partition by range (XDATE)
(
  partition P0 values less than (TO_DATE(' 2013-03-21 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')),
  partition SYS_P61 values less than (TO_DATE(' 2013-04-21 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')),
  partition SYS_P62 values less than (TO_DATE(' 2013-05-21 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')),
  partition SYS_P63 values less than (TO_DATE(' 2013-06-21 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')),
  partition SYS_P64 values less than (TO_DATE(' 2013-07-21 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')));

如您所见,数据库将 NLS_CALENDAR 更改为gregorian(与 13920101 同一天)并且每个分区都是根据gregorian日历而不是persian日历创建的。

有什么方法可以强制 Oracle 使用波斯日历来创建新分区?

oracle partitioning
  • 2 2 个回答
  • 3224 Views

2 个回答

  • Voted
  1. Best Answer
    Alex Poole
    2014-01-07T04:24:16+08:002014-01-07T04:24:16+08:00

    我看不出有任何方法可以在与数据库级 NLS_CALENDAR 不同的日历中定义间隔。您可以通过使用虚拟列对每个日期所在的(波斯)月份的数字表示进行分区来获得相同的效果:

    create table test_temp_times (
      id number(18) not null,
      xdate date not null,
      str varchar2(20),
      ydate as (to_number(to_char(xdate, 'YYYYMM', 'nls_calendar=persian')))
    )
    partition by range(ydate)
    interval(1)
    (partition p0 values less than (139201))
    enable row movement;
    

    如果在示例开始日期之后的一年中的每一天都填充了记录:

    insert into test_temp_times (id, xdate, str)
    select level, date '2013-03-20' + level, null
    from dual
    connect by level < 366;
    

    创建的分区如下所示:

    select table_name, partition_name, high_value
    from user_tab_partitions where table_name = 'TEST_TEMP_TIMES';
    
    TABLE_NAME                     PARTITION_NAME                 HIGH_VALUE
    ------------------------------ ------------------------------ ----------
    TEST_TEMP_TIMES                P0                             139201     
    TEST_TEMP_TIMES                SYS_P479                       139202     
    TEST_TEMP_TIMES                SYS_P480                       139203     
    TEST_TEMP_TIMES                SYS_P481                       139204     
    TEST_TEMP_TIMES                SYS_P482                       139205     
    TEST_TEMP_TIMES                SYS_P483                       139206     
    TEST_TEMP_TIMES                SYS_P484                       139207     
    TEST_TEMP_TIMES                SYS_P485                       139208     
    TEST_TEMP_TIMES                SYS_P486                       139209     
    TEST_TEMP_TIMES                SYS_P487                       139210     
    TEST_TEMP_TIMES                SYS_P488                       139211     
    TEST_TEMP_TIMES                SYS_P489                       139212     
    TEST_TEMP_TIMES                SYS_P490                       139213     
    
     13 rows selected 
    

    您可以检查月份边界属于哪些分区:

    select utp.partition_name, min(ttt.xdate), max(ttt.xdate)
    from test_temp_times ttt
    join user_objects uo on uo.object_id = dbms_rowid.rowid_object(ttt.rowid)
    join user_tab_partitions utp on utp.table_name = uo.object_name
    and utp.partition_name = uo.subobject_name
    group by utp.partition_name
    order by partition_name;
    
    PARTITION_NAME                 MIN(TTT.XDATE) MAX(TTT.XDATE)
    ------------------------------ -------------- --------------
    P0                             2013-03-20     2013-03-20     
    SYS_P479                       2013-03-21     2013-04-20     
    SYS_P480                       2013-04-21     2013-05-21     
    SYS_P481                       2013-05-22     2013-06-21     
    SYS_P482                       2013-06-22     2013-07-22     
    SYS_P483                       2013-07-23     2013-08-22     
    SYS_P484                       2013-08-23     2013-09-22     
    SYS_P485                       2013-09-23     2013-10-22     
    SYS_P486                       2013-10-23     2013-11-21     
    SYS_P487                       2013-11-22     2013-12-21     
    SYS_P488                       2013-12-22     2014-01-20     
    SYS_P489                       2014-01-21     2014-02-19     
    SYS_P490                       2014-02-20     2014-03-19
    

    至少,我认为这就是您想要实现的目标......不幸的是,我无法添加演示,因为 SQL Fiddle 没有分区选项,但这是针对 11.2.0.3 进行的测试。

    当然,你必须让它使用分区进行查询......如果我只是这样做:

    select * from test_temp_times
    where xdate = date '2013-11-01';
    

    它找到带有计划的行:


    -----------
    | Id  | Operation           | Name            | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
    -------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT    |                 |     1 |    47 |   164   (0)| 00:00:02 |       |       |
    |   1 |  PARTITION RANGE ALL|                 |     1 |    47 |   164   (0)| 00:00:02 |     1 |1048575|
    |*  2 |   TABLE ACCESS FULL | TEST_TEMP_TIMES |     1 |    47 |   164   (0)| 00:00:02 |     1 |1048575|
    -------------------------------------------------------------------------------------------------------
    

    如果我将虚拟列显式添加到查询中:

    select * from test_temp_times
    where xdate = date '2013-11-01'
    and ydate = to_number(to_char(date '2013-11-01', 'YYYYMM', 'nls_calendar=persian'));
    

    然后它知道要查询哪个分区:

    ----------------------------------------------------------------------------------------------------------
    | Id  | Operation              | Name            | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
    ----------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT       |                 |     1 |    47 |    14   (0)| 00:00:01 |       |       |
    |   1 |  PARTITION RANGE SINGLE|                 |     1 |    47 |    14   (0)| 00:00:01 |     9 |     9 |
    |*  2 |   TABLE ACCESS FULL    | TEST_TEMP_TIMES |     1 |    47 |    14   (0)| 00:00:01 |     9 |     9 |
    ----------------------------------------------------------------------------------------------------------
    

    显然我还没有创建任何索引。如果您正在寻找一整月的数据,您只需要查询一个ydate值,然后忽略xdate; 但大概你至少在某些时候需要混合。

    • 5
  2. hmmftg
    2014-01-07T01:03:41+08:002014-01-07T01:03:41+08:00

    萨拉姆!您对 oracle 说要使用 30 天的间隔,因此它将该间隔添加到 sysdate 并使用它!我认为您最好使用 numtodsinterval(month_days(column_name), 'DAY') 而不是 numtodsinterval(1, 'MONTH') 哪个 month_days 计算波斯月的天数,如下所示:

    FUNCTION MONTH_DAYS (P_DATE IN DATE)
        RETURN NUMBER
    IS
        V_MONTH_ID   NUMBER;
    BEGIN
        V_MONTH_ID := TO_NUMBER (TO_CHAR (P_DATE, 'MM', 'NLS_CALENDAR=PERSIAN'));
    
        CASE V_MONTH_ID
            WHEN 1
            THEN
                RETURN 31;
                ...
        END CASE;
    END;
    
    • 1

相关问题

  • Oracle 中的数据库备份 - 导出数据库还是使用其他工具?

  • ORDER BY 使用文本列的自定义优先级

  • 舒服的sqlplus界面?[关闭]

  • 如何在数据库中找到最新的 SQL 语句?

  • 如何使用正则表达式查询名称?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve