Oracle在日期上使用LIKE '%'

10

我的表myTab有一列startDate,它的数据类型是“DATE”。这个列中的数据存储为dd.mm.yyyy格式。

现在我正在尝试使用以下查询获取数据:

SELECT * FROM myTab WHERE startDate like '%01.2015"

不知何故它不起作用,我不知道为什么。

希望有人能帮忙。


如果您想要2015年1月的所有行,请使用where to_char(startDate ,'Mon-YYYY')='Jan-2015'; - Mihai
请查看Oracle SQL比较日期返回错误结果 - Lalit Kumar B
8个回答

22

要在日期上进行文本搜索,您需要将日期转换为文本。

如果您计算要查找的第一个和最后一个日期并获取它们之间的所有内容,这样会更有效率。这样做是通过数字比较而不是文本模式匹配完成的,并且如果有索引可以利用它。

SELECT * FROM myTab WHERE startDate >= DATE '2015-01-01' AND startDate < DATE '2015-02-01'

如果您能提到为什么在这里使用日期范围条件更好,我将不胜感激。基本上,这是关于性能的问题,即是否使用了B*Tree索引(如果有的话)。 - Lalit Kumar B
1
我很感激。但是,请将“数字比较”替换为“日期比较”,因为这更合适。日期与数字(Oracle中的数字)不同。 - Lalit Kumar B
@LalitKumarB:我想知道你认为字节是什么?当数据库比较这些字节值时,你认为它使用的方式除了进行数字比较之外还有其他方式吗? - Guffa
Lalit是正确的,日期比较与数字比较处理方式不同。然而,我明白你想说什么Guffa - 实际上,比较是以数字形式进行的,将它们视为这种方式很有用(即每个日期值表示最接近秒的特定时间点,并且可以被视为相对于特定时期过去的秒数 - 这就是为什么我们可以比较日期,“减去”一个日期和另一个日期,并向它们添加数字值)。 - Jeffrey Kemp
@JeffreyKemp:自然日期比较与比较“数字”数据类型不同,但我从未说过日期是作为“数字”值进行比较的,我说的是比较方式是数值比较。 - Guffa
显示剩余4条评论

3
SELECT * FROM myTab WHERE TO_CHAR(startDate,'dd.mm.yyyy') LIKE '%01.2015'

你的方法有点用。现在我遇到了其他日期不起作用的问题。如果我尝试使用“%01.2013”,我将得不到任何数据,但我知道在这个范围内有日期... - Mihawk
@Lalit,我可以谦虚地建议您放松一下语气吗?这个答案并不是“完全错误”的,只是不是最好的。实际上,这个答案可以工作,尽管有更好的解决问题的方法,并且实际上不依赖于隐式数据类型转换 - Jeffrey Kemp
@Jeffrey,好的,没问题 :-) - Lalit Kumar B

2

如果字段类型为“DATE”,则其值不会被存储为字符串,而是由Oracle管理的数字,因此您需要将其转换为字符串:

SELECT * FROM myTab WHERE to_char(startDate, 'MM.YYYY') = '01.2015';

在 SQL 查询中,您还可以使用日期范围:

SELECT * FROM myTab 
WHERE startDate 
BETWEEN to_date('01.01.2015', 'DD.MM.YYYY') 
AND     to_date('31.01.2015', 'DD.MM.YYYY');

1
请先阅读有关隐式数据转换的内容:在这里http://docs.oracle.com/cd/E11882_01/server.112/e41084/sql_elements002.htm#i53062 Oracle 在此情况下自动将日期转换为 varchar,因此您的答案不是很准确。 - krokodilko
to_char()是显式的:http://docs.oracle.com/cd/E11882_01/server.112/e41084/sql_elements002.htm#SQLRF51054 - mbk

1
关于你的实际问题“不知道为什么它不起作用。”
Oracle将DATE隐式转换为VARHCAR2,但它使用默认的NLS_DATE_FORMAT,这可能与你在查询中使用的格式不同。

1
这一列中的数据以dd.mm.yyyy的形式存储。Oracle不会按你所看到的格式存储日期。它使用7个字节以专有格式在内部存储日期时间值的不同组成部分。你正在比较DATE和STRING,这是没有意义的。从性能角度考虑,您应该使用日期范围条件,以便如果日期列上有任何常规索引,则可以使用它。
SELECT * FROM table_name WHERE date_column BETWEEN DATE '2015-01-01' AND DATE '2015-02-01'

为了理解为什么使用日期范围条件在性能方面更好,请查看我的答案这里

0
为了提供更详细的答案并解决https://dev59.com/LVwX5IYBdhLWcg3w-Tlv#42429550中提出的问题。
在Oracle中,“日期”类型的列既不是数字也不是字符串,它是一个带有年、月、日、小时、分钟和秒的“日期时间”值。默认时间始终是午夜“00:00:00”。
查询:
Select * From bdPedidos Where Data Like '%" + data + "%'" 

在所有情况下都不起作用,因为日期列不是字符串,在使用"like"强制Oracle从日期值转换为字符串值。 字符串值可以是年-月-日-时间或月-日-年-时间或日-月-年-时间,这完全取决于特定的Oracle实例如何设置参数NLS_DATE_FORMAT来显示日期。

涵盖一天中所有可能的时间的正确方法是:

Select * 
From bdPedidos 
Where Data between to_date('" + data + " 00:00:00','yyyy-mm-dd hh24:mi:ss')
               and to_date('" + data + " 23:59:59','yyyy-mm-dd hh24:mi:ss')

查询是在C#中构建的字符串,因此需要起始引号和最后一个引号。 - alvalongo

0

我用这种方法解决了我的问题。感谢您提供的改进建议。C#示例。

string dd, mm, aa, trc, data;
dd = nData.Text.Substring(0, 2);
mm = nData.Text.Substring(3, 2);
aa = nData.Text.Substring(6, 4);
trc = "-";
data = aa + trc + mm + trc + dd;

"Select * From bdPedidos Where Data Like '%" + data + "%'";

0
SELECT * FROM myTab WHERE startDate like '%-%-2015';

这将搜索2015年的所有日期。如果不起作用,请尝试:

SELECT * FROM myTab WHERE startDate like '%-%-15';

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接