【问题标题】:compare month and year in SQL比较SQL中的月份和年份
【发布时间】:2014-12-19 05:02:01
【问题描述】:

我想将表中的月份和年份列与我用来放置此表达式的用户提供的月份和年份参数进行比较

 select  ca_expense_mst.trans_id, trans_no
 from ca_expense_mst , CA_EXPENSE_FINANCE_DTL fndDtl     
 where  ca_expense_mst.TRANS_ID=fndDtl.TRANS_ID    
 and TO_DATE(''|| fndDtl.year ||'/'|| fndDtl.month || '/01', 'yyyy/mm/dd')  between  TO_DATE(''|| :fromYear ||'/'|| :fromMonth || '/01', 'yyyy/mm/dd')  and TO_DATE(''|| :toYear ||'/'|| :toMonth || '/01', 'yyyy/mm/dd')     
 and  fndDtl.account_id= nvl(to_number(:account_no),fndDtl.account_id)

它工作正常,但如果我添加聚合函数 count() 我会得到这个异常:

由:java.sql.SQLDataException:ORA-01841:(完整)年份必须介于 -4713 和 +9999 之间,并且不能为 0

我需要一种方法,以便我可以将 moth 和 year 列与月份和年份参数进行比较

这是引发异常的 SQL:

select  count(ca_expense_mst.trans_id)  as all_trans
from ca_expense_mst , CA_EXPENSE_FINANCE_DTL fndDtl     
where  ca_expense_mst.TRANS_ID=fndDtl.TRANS_ID    
and TO_DATE(''|| fndDtl.year ||'/'|| fndDtl.month || '/01', 'yyyy/mm/dd')  between  TO_DATE(''|| 
:fromYear ||'/'|| :fromMonth || '/01', 'yyyy/mm/dd')  and TO_DATE(''|| :toYear ||'/'|| :toMonth || '/01', 'yyyy/mm/dd') 
and  fndDtl.account_id= nvl(to_number(:account_no),fndDtl.account_id)

这是我的表的脚本

CREATE TABLE SAS_ADF.CA_EXPENSE_FINANCE_DTL
(
  EXP_FIN_ID          NUMBER,
  ACCOUNT_ID          NUMBER,
  TRANS_ID            NUMBER,
  AMOUNT_BY_CD        NUMBER,
  DEBIT_CREDIT        VARCHAR2(2 BYTE),
  CHEQUE_STATUS       VARCHAR2(20 BYTE),
  REFERENCE_NO        VARCHAR2(500 BYTE),
  REFERENCE_DATE      DATE,
  ENT_BY              VARCHAR2(50 BYTE),
  ENT_DATE            DATE,
  MODIFY_BY           VARCHAR2(50 BYTE),
  MODIFY_DATE         DATE,
  REFUND_TYPE_ID      NUMBER,
  STUDENT_ID          NUMBER,
  STD_FIN_APP_FLAG    VARCHAR2(2 BYTE),
  STD_AUDIT_APP_FLAG  VARCHAR2(2 BYTE),
  ACTION_DATE         DATE,
  MONTH               NUMBER,
  YEAR                NUMBER,
  CANCEL_FLAG         VARCHAR2(2 BYTE),
  EXP_FIN_ID_M        NUMBER,
  USER_TRANS_ID       VARCHAR2(500 BYTE),
  OLD_STUDENT_ID      NUMBER,
  CD                  VARCHAR2(10 BYTE),
  CURRENCY_RATE       NUMBER,
  AMOUNT_BY_CD_L      NUMBER,
  CURR_ISO            VARCHAR2(4 BYTE),
  STDUENT_ID_W        NUMBER,
  AMOUNT_BY_CD_C      NUMBER,
  DEBIT_CREDIT_C      VARCHAR2(10 BYTE)
)

这里是一些数据的屏幕截图

【问题讨论】:

  • 如果这曾经工作但停止工作,我会怀疑数据问题。是否存在包含无效月份或年份值的行?
  • 不,我在 toad 中使用相同的数据和相同的参数值对其进行测试,我认为这是错误,但我需要用其他方法进行比较。这个问题不仅是我的 SQL 独有的,请使用您自己的表自己尝试,您会得到相同的错误,这就是为什么我说它是错误的原因。我只是想过滤掉不相关的数据
  • 在任何情况下,您都不需要为每次比较重新计算 FromYear、fromMonth、toYear 和 toMonth 的 TO_STRING 转换。我会声明 4 个变量并在顶部计算它们,然后在查询中与变量进行比较。
  • 顺便说一句,这里的逻辑不是有缺陷吗? BETWEEN 包含在内,您的 上限 是月底的 第一天 天?
  • @user1512999 “它工作正常” - 在从查询中获取所有记录后,您是否得出结论?因为如果您只获取前 10/50/1000 行,那么有可能其中 2 行中没有空年份,所以没有为它们完成 to_date,尽管另一方面 count 必须处理它们。

标签: sql oracle datetime


【解决方案1】:

fndDtl.year 列中有一个 NULL 值。

不知何故,这会以您的格式引发ORA-01841: (full) year must be between -4713 and +9999, and not be 0

select TO_DATE(''|| NULL ||'/'|| 12 || '/01', 'yyyy/mm/dd') from dual;

ORA-01841:(完整)年份必须介于 -4713 和 +9999 之间,并且不能为 0


事实上,您可以将这种行为追踪到那个简单的案例:

select TO_DATE('/', 'yyyy/') from dual

ORA-01841:(完整)年份必须介于 -4713 和 +9999 之间,并且不能为 0

然而,正如 be here now 在上面的评论中所注意到的:

select TO_DATE('/', 'syyyy/') from dual

ORA-01858:在需要数字的地方发现了一个非数字字符

【讨论】:

  • 我删除了 year 的 null 值并且它工作正常,让我从不同的方向思考的是,当我删除计数时它工作正常。我不知道为什么。无论如何,现在它在删除年份的空值后正在工作
  • @user1512999 很可能您在遇到 to_date(null) 之前刚刚停止获取行。使用 count 这是不可能的 - 它会在您向客户端获取任何内容之前处理所有行。
  • 我明白了,谢谢,因为我知道在 toa 上执行 sql 时,它每次获取 500 行,当然 year =null 不在其中。再次感谢您
【解决方案2】:

从年份和月份中排除空值

select CA_EXPENSE_MST.TRANS_ID,
       TRANS_NO
  from CA_EXPENSE_MST
 inner join CA_EXPENSE_FINANCE_DTL FNDDTL on CA_EXPENSE_MST.TRANS_ID = FNDDTL.TRANS_ID
 where CA_EXPENSE_MST.TRANS_ID is not null
   and FNDDTL.YEAR is not null
   and FNDDTL.MONTH is not null
   and FNDDTL.ACCOUNT_ID = NVL(TO_NUMBER(:ACCOUNT_NO), FNDDTL.ACCOUNT_ID)
   and TO_DATE(FNDDTL.YEAR || '/' || FNDDTL.MONTH || '/01', 'yyyy/mm/dd') between TO_DATE(:FROMYEAR || '/' || :FROMMONTH || '/01', 'yyyy/mm/dd') and
       TO_DATE(:TOYEAR || '/' || :TOMONTH || '/01', 'yyyy/mm/dd');

这里是链接:sqlFiddle

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-11
    • 1970-01-01
    • 2018-07-12
    • 1970-01-01
    相关资源
    最近更新 更多