Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle 比较两个日期字段时,“文字与格式字符串不匹配”_Oracle_Plsql - Fatal编程技术网

Oracle 比较两个日期字段时,“文字与格式字符串不匹配”

Oracle 比较两个日期字段时,“文字与格式字符串不匹配”,oracle,plsql,Oracle,Plsql,我有一种奇怪的行为,我希望有人能解释给我听 我在一个查询中有两个字段。一个是数字字段,它通过转换为日期'01/01/1960'、'mm/dd/yyyy'+某物来转换为日期。另一个是文本字段,其中至少包含一个非日期值,该值被转换为具有to_datetextField“mm/dd/rrrrr”的日期。如果我运行查询,它运行得很好。但是,如果我将查询括在select*from where field1>field2中,则会出现ORA-01861:literal不匹配格式字符串错误。如果我尝试在子查询的

我有一种奇怪的行为,我希望有人能解释给我听

我在一个查询中有两个字段。一个是数字字段,它通过转换为日期'01/01/1960'、'mm/dd/yyyy'+某物来转换为日期。另一个是文本字段,其中至少包含一个非日期值,该值被转换为具有to_datetextField“mm/dd/rrrrr”的日期。如果我运行查询,它运行得很好。但是,如果我将查询括在select*from where field1>field2中,则会出现ORA-01861:literal不匹配格式字符串错误。如果我尝试在子查询的where子句中排除提取文本字段的已知非日期值,则没有任何帮助


我知道如果没有代码,这几乎是不可能的,但我想知道是否有人能向我解释为什么它在没有过滤器的情况下工作,但当我添加它时,它会爆炸。谢谢。

我猜您的varchar2列中的一个日期-注意不一致性-不是您指定的格式。请不要在字符列中存储日期。如果使用日期列,它将阻止这种情况发生

创建以下函数:

create or replace function is_date
        ( Pdate varchar2
        , Pformatstring varchar2 ) return number is

   l_date date;

begin

   l_date := to_date(Pdate, Pformatstring);

   return 1;
-- raise an exception when you can-t convert to a date.
exception when others then
   return 0;

end;
然后在你的桌子上跑步:

select <columns>
  from my_table
 where is_date(textfield,  'mm/dd/rrrr') = 0
那么Oracle不一定会按照您想要的顺序对所有内容进行评估。您必须将其更改为:

select x.*
  from ( select a, b, to_date(replace(a.textfield,'?'),'mm/dd/rr') as another_date
           from my_table ) x
  join another_table b
    on another_date = b.a_date

我猜您的varchar2列中的一个日期-注意不一致性-不是您指定的格式。请不要在字符列中存储日期。如果使用日期列,它将阻止这种情况发生

创建以下函数:

create or replace function is_date
        ( Pdate varchar2
        , Pformatstring varchar2 ) return number is

   l_date date;

begin

   l_date := to_date(Pdate, Pformatstring);

   return 1;
-- raise an exception when you can-t convert to a date.
exception when others then
   return 0;

end;
然后在你的桌子上跑步:

select <columns>
  from my_table
 where is_date(textfield,  'mm/dd/rrrr') = 0
那么Oracle不一定会按照您想要的顺序对所有内容进行评估。您必须将其更改为:

select x.*
  from ( select a, b, to_date(replace(a.textfield,'?'),'mm/dd/rr') as another_date
           from my_table ) x
  join another_table b
    on another_date = b.a_date

我将使用DBMS\u Xplan.display查看执行计划,以查看您提供的过滤器是否以某种微妙的方式进行了修改,从而解释了这种行为。

我将使用DBMS\u Xplan.display查看执行计划,查看您提供的筛选器是否以某种微妙的方式进行了修改,以解释这种行为。

一般的问题是,由于SQL是一种基于集合的语言,Oracle可以按照其选择的任何顺序对谓词进行评估。如果您有一个存储一些日期值和一些非日期值的VARCAHR2列,这意味着Oracle可以自由地计算先过滤掉所有非日期值的谓词,或者计算检查转换后的日期值之一是否大于另一个值的谓词。如果在筛选出非日期值之前,碰巧计算了日期不平等谓词field1>field2,您将得到一个错误

SQL是基于集合的,这一事实是使用错误的数据类型非常有问题的主要原因之一——在调用转换函数之前,您无法确定查询是否总是过滤掉不可转换的数据。即使您设置了抽象障碍,如过滤无效数据的视图,优化器也可以自由地对谓词重新排序,这样您就可以很容易地发现您的查询最终打破了抽象障碍,或者您的查询大部分时间都在工作,除非优化器选择了不同的执行计划。乔纳森·根尼克(Jonathan Gennick)有一篇非常有趣的文章讨论了这个具体问题

您可以编写自己的转换函数来忽略异常,并在查询中使用该函数。例如,您可以创建一个函数

CREATE OR REPLACE FUNCTION my_to_date( p_date_str    IN VARCHAR2,
                                       p_format_mask IN VARCHAR2 )
  RETURN DATE
IS
  l_date DATE;
BEGIN
  l_date := to_date( p_date_Str, p_format_mask ); 
  RETURN l_date;
EXCEPTION
  WHEN OTHERS THEN
    RETURN null;
END;
然后在查询中使用该函数

SELECT *
  FROM (SELECT to_date('01/01/1960', 'mm/dd/yyyy') + somethingorother field1,
               my_to_date( textField, 'mm/dd/rrrr' ) field2
          FROM your_table
         WHERE some_condition)
 WHERE field1 > field2

这将起作用,因为对任何字符串调用my_to_date都是有效的,无论其计算结果是否为有效日期,因此您的查询不再取决于Oracle选择计算谓词的顺序。

一般的问题是,由于SQL是一种基于集合的语言,Oracle可以自由地按其选择的任何顺序评估谓词。如果您有一个存储一些日期值和一些非日期值的VARCAHR2列,这意味着Oracle可以自由地计算先过滤掉所有非日期值的谓词,或者计算检查转换后的日期值之一是否大于另一个值的谓词。如果在筛选出非日期值之前,碰巧计算了日期不平等谓词field1>field2,您将得到一个错误

SQL是基于集合的,这一事实是使用错误的数据类型非常有问题的主要原因之一——在调用转换函数之前,您无法确定查询是否总是过滤掉不可转换的数据。即使您设置了抽象障碍,如过滤无效数据的视图,优化器也可以自由地对谓词重新排序,这样您就可以很容易地发现您的查询最终打破了抽象障碍,或者您的查询大部分时间都在工作,除非优化器选择了不同的执行计划。乔纳森·根尼克 有一篇非常有趣的文章讨论了这个具体问题

您可以编写自己的转换函数来忽略异常,并在查询中使用该函数。例如,您可以创建一个函数

CREATE OR REPLACE FUNCTION my_to_date( p_date_str    IN VARCHAR2,
                                       p_format_mask IN VARCHAR2 )
  RETURN DATE
IS
  l_date DATE;
BEGIN
  l_date := to_date( p_date_Str, p_format_mask ); 
  RETURN l_date;
EXCEPTION
  WHEN OTHERS THEN
    RETURN null;
END;
然后在查询中使用该函数

SELECT *
  FROM (SELECT to_date('01/01/1960', 'mm/dd/yyyy') + somethingorother field1,
               my_to_date( textField, 'mm/dd/rrrr' ) field2
          FROM your_table
         WHERE some_condition)
 WHERE field1 > field2

这将起作用,因为对任何字符串调用my_to_date都是有效的,无论它的计算结果是否为有效日期,因此您的查询不再取决于Oracle选择计算谓词的顺序。

我的猜测是,如果省略where子句,Toad选择的前500行之外的某个地方有一个无效值。如果滚动到最后,是否会抛出错误?否。在理论上,它只是将现有的日期字段与现有的日期字段进行比较。我猜想,如果省略where子句,Toad选择的前500行之外的某个地方会有一个无效值。如果滚动到最后,是否会抛出错误?否。它没有where子句,但在理论上它只是将现有日期字段与现有日期字段进行比较时出错。不幸的是,我无法控制字段的类型-它用于存储医疗观察结果,并且需要是varchar才能处理存储的任何内容。从理论上讲,该字段的输入框应该强制它为日期类型,但这似乎有点不对劲。@SarekOfVulcan,它仍然可以在进入数据库之前转换为日期。相信我,我有经验。转换为日期将立即解决所有此类问题。当然不可能,那就不可能了。也许定期扫描表格以确定问题记录?我无法控制前端-这是GE的Centricity EMR。我用它给我的东西工作-带有replace的新查询只有在日期正确的情况下才有效,除非有问号。由于这些字段包含用户键入的内容,因此可能会有许多不同形式的错误日期。@ShannonSeverance,这是一个例子,说明Oracle如何以不同于您预期的方式评估查询,以及如何绕过查询。显然,如果有很多糟糕的日期,那么它就不起作用了。不幸的是,我无法控制它是什么类型的字段-它用于存储医学观察结果,并且需要是varchar,以便处理存储在其中的任何内容。从理论上讲,该字段的输入框应该强制它为日期类型,但这似乎有点不对劲。@SarekOfVulcan,它仍然可以在进入数据库之前转换为日期。相信我,我有经验。转换为日期将立即解决所有此类问题。当然不可能,那就不可能了。也许定期扫描表格以确定问题记录?我无法控制前端-这是GE的Centricity EMR。我用它给我的东西工作-带有replace的新查询只有在日期正确的情况下才有效,除非有问号。由于这些字段包含用户键入的内容,因此可能会有许多不同形式的错误日期。@ShannonSeverance,这是一个例子,说明Oracle如何以不同于您预期的方式评估查询,以及如何绕过查询。显然,如果有很多糟糕的约会,那么它就不会起作用。