如何解决 Oracle 在特定时间删除数据的问题?

huangapple go评论129阅读模式
英文:

How Do I solve the problem of Oracle deleting data at a specific time?

问题

我的SQL语句如下:
delete from "result" where DATA_DATE < TO_DATE('2023-04-06 00:00:00', 'YYYY-MM-DD HH24-MI-SS')

错误信息是:
ORA-01861: 文本与格式字符串不匹配

我该怎么办?

英文:

My SQL statement is as follows:
delete from &quot;result&quot; where DATA_DATE &lt; TO_DATE(&#39;2023-04-06 00:00:00&#39;, &#39;YYYY-MM-DD HH24-MI-SS&#39;)

the error message is:
ORA-01861: literal does not match format string
What should I do?

This is part of the information in the table:
enter image description here

答案1

得分: 3

如果DATA_DATE列存储为DATE数据类型:

创建表 "result" (data_date DATE);

插入到 "result" (data_date)
值(TO_DATE('2023-04-05 12:34:56', 'YYYY-MM-DD HH24-MI-SS'));

然后你的查询有效:

从 "result" 中删除
其中 DATA_DATE &lt; TO_DATE('2023-04-06 00:00:00', 'YYYY-MM-DD HH24-MI-SS');
影响了 1 行

如果你的DATA_DATE列是字符串数据类型:

CREATE TABLE "result" (data_date VARCHAR2(19));

INSERT INTO "result" (data_date) VALUES ('2023-04-05 12:34:56');

然后你的查询:

从 "result" 中删除
其中 DATA_DATE &lt; TO_DATE('2023-04-06 00:00:00', 'YYYY-MM-DD HH24-MI-SS');

比较一个字符串和一个日期,Oracle 会隐式地将字符串转换为日期,以便比较相同的数据类型,查询实际上是:

从 "result" 中删除
其中 TO_DATE(
        DATA_DATE,
        (SELECT value FROM nls_session_parameters WHERE parameter = 'NLS_DATE_FORMAT')
      )
      &lt; TO_DATE('2023-04-06 00:00:00', 'YYYY-MM-DD HH24-MI-SS');

如果NLS_DATE_FORMAT会话参数匹配:

ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';

然后查询有效。

但如果会话参数不匹配:

ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY';

然后可能会出现错误:

ORA-01861: 文字与格式字符串不匹配

解决问题,可以选择:

  1. 总是将日期存储为DATE数据类型(而不是字符串)。

  2. 不要比较不同数据类型,因为Oracle会执行隐式类型转换,以便比较它们。

    • 要么将两边都比较为字符串:

      从 "result" 中删除
      其中 DATA_DATE &lt; '2023-04-06 00:00:00';
      
    • 要么将两边都比较为日期:

      从 "result" 中删除
      其中 TO_DATE(data_date, 'YYYY-MM-DD HH24:MI:SS')
            &lt; TO_DATE('2023-04-06 00:00:00', 'YYYY-MM-DD HH24:MI:SS');
      
  3. 设置NLS_DATE_FORMAT,以便隐式转换正常工作。

虽然这些选项都能起效,但应该选择第一种,修复表,使数据存储在正确的数据类型中。如果实在不能更改表格,那么选择第二种,并确保你的查询比较相同的数据类型(如果需要,可以在类型之间使用显式转换)。选项3只是为了完整起见,它只允许你继续使用依赖隐式类型转换的不良习惯,不要使用它。

英文:

If the DATA_DATE column is stored as a DATE data type:

CREATE TABLE &quot;result&quot; (data_date DATE);

INSERT INTO &quot;result&quot; (data_date)
VALUES (TO_DATE(&#39;2023-04-05 12:34:56&#39;, &#39;YYYY-MM-DD HH24-MI-SS&#39;));

Then your query works:

delete from &quot;result&quot;
where DATA_DATE &lt; TO_DATE(&#39;2023-04-06 00:00:00&#39;, &#39;YYYY-MM-DD HH24-MI-SS&#39;);

> lang-none
&gt; 1 rows affected
&gt;


If your DATA_DATE column is a string data type:

CREATE TABLE &quot;result&quot; (data_date VARCHAR2(19));

INSERT INTO &quot;result&quot; (data_date) VALUES (&#39;2023-04-05 12:34:56&#39;);

Then your query:

delete from &quot;result&quot;
where DATA_DATE &lt; TO_DATE(&#39;2023-04-06 00:00:00&#39;, &#39;YYYY-MM-DD HH24-MI-SS&#39;);

Is comparing a string to a date and Oracle will implicitly convert the string to a date so that it compares the same data types and the query is effectively:

delete from &quot;result&quot;
where TO_DATE(
        DATA_DATE,
        (SELECT value FROM nls_session_parameters WHERE parameter = &#39;NLS_DATE_FORMAT&#39;)
      )
      &lt; TO_DATE(&#39;2023-04-06 00:00:00&#39;, &#39;YYYY-MM-DD HH24-MI-SS&#39;);

If the NLS_DATE_FORMAT session parameter matches:

ALTER SESSION SET NLS_DATE_FORMAT = &#39;YYYY-MM-DD HH24:MI:SS&#39;;

Then the query works.

But if the session parameter does not match:

ALTER SESSION SET NLS_DATE_FORMAT = &#39;DD-MON-YYYY&#39;;

Then you may get the error:

> error
&gt; ORA-01861: literal does not match format string
&gt;


To solve the problem, either:

  1. Always store dates in a DATE data type (and not as strings).

  2. Do not compare different data types as Oracle will perform an implicit type conversion so that it can compare them.

    • Either compare both sides as strings:

      delete from &quot;result&quot;
      where DATA_DATE &lt; &#39;2023-04-06 00:00:00&#39;;
      
    • Or compare both sides as dates:

      delete from &quot;result&quot;
      where TO_DATE(data_date, &#39;YYYY-MM-DD HH24:MI:SS&#39;)
            &lt; TO_DATE(&#39;2023-04-06 00:00:00&#39;, &#39;YYYY-MM-DD HH24:MI:SS&#39;);
      
      
      
  3. Set the NLS_DATE_FORMAT so that the implicit conversion works.

While any of the options will work; you should use #1 and fix your table so the data is stored in the correct data type. If you really can't change the table then use #2 and ensure that your queries are comparing the same data types (and, if you need to, use explicit conversions between types). Option #3 is just there for completeness and is just going to allow you to continue using bad habits of relying on implicit type conversions; don't use it.

fiddle

huangapple
  • 本文由 发表于 2023年6月1日 14:34:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76379243.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定