我有一个列保存为字符数据类型。本专栏将作为日期使用。该列以该格式显示“YYYY-MM-DD”。
这是一个问题,因为如果我需要按日期过滤,我必须去
select col_1, col_2
from table
where date LIKE '2016-04%;
如果我想搜索日期范围,这会变成一个巨大的复杂混乱。
将此转换为“日期”数据类型的最简单方法是什么?我希望它继续以YYYY-MM-DD顺序(没有时间戳)。
我的最终目标是能够以这样的格式搜索日期:
select col_1, col_2
from table
where date between 2016-01-01 AND 2016-05-31;
你们推荐什么?我很害怕如果我使用alter语句来转换我的数据类型,我将破坏我的约会。 (我有一份保存的数据副本,可以再次上传,但需要永久上传。)
编辑:这是一个非常大的表。
编辑第2部分:我最初将数据存储为varchar数据类型,因为我的日期没有正确上传,当我尝试保存为日期数据类型时收到错误消息。此列中的每个日期都是“YYYY-MM-DD”顺序。我的解决方案是将其保存为varchar以避免错误消息(我无法弄清楚出了什么问题。我甚至摆脱了前导和尾随空格。)
答案 0 :(得分:5)
将日期存储为varchar
是错误的选择。你想要改变它是非常好的。
第一步是使用ALTER TABLE
语句转换列:
alter table the_table
ALTER COLUMN col_1 TYPE date using col_1::date,
ALTER COLUMN col_2 TYPE date using col_2::date;
请注意,如果这些列中的任何值无法转换为正确的日期,则会失败。如果你得到了,你需要先修复这些无效字符串,然后才能更改数据类型。
我希望它继续以YYYY-MM-DD顺序
这是一种误解。 DATE
(或timestamp
)没有“格式”。一旦将其存储为日期,您就可以以任何您想要的格式显示它。
我的最终目标是能够以这样的格式搜索日期:
2016-01-01
不是有效的日期文字,可以指定适当的(即正确输入的)日期常量,例如使用date '2016-01-01'
(注意单引号!
所以你的查询变为:
select col_1, col_2
from table
where col_1 between date '2016-01-01' AND date '2016-05-31';
如果你有很多这样的查询,你应该考虑在日期列上创建一个索引。
关于日期常量格式:
你是否告诉我,尽管有varchar数据类型,我仍然可以(截至目前)在特定日期之间搜索,只需输入单词date并在两个日期之间放置单引号
不,事实并非如此。 SQL是一种强类型语言,因此只会比较相同类型的值。
使用ANSI日期文字(或例如to_date()
)会产生类型常量(即具有特定数据类型的值)。
date '2016-01-01' and '2016-01-01' is the same as between
42 (a number) and
'42'`(一个字符串)之间的差异。
如果将字符串与日期进行比较,则表示您正在比较苹果和橙子,并且数据库将执行从一种类型到另一种类型的隐式数据类型转换。应该不惜一切代价避免这种情况。
如果您不想更改表,则应使用提供的查询sagi,它将字符串显式转换为日期,然后对(实际)日期值(而不是字符串)进行比较
答案 1 :(得分:1)
您可以使用POSTGRES
TO_DATE()
强制转换功能:
SELECT col_1,col_2
FROM Your_Table
WHERE to_date(date_col,'yyyy-mm-dd') between to_date('2016-05-31','yyyy-mm-dd') and to_date('2016-01-01','yyyy-mm-dd')
答案 2 :(得分:0)
Plus ,如果由于某些奇怪的原因无法更改数据类型,to_date()
是转换列上列的安全选项,但没有必要使用提供常量的相同表达式。所以:
SELECT col_1, col_2
FROM tbl
WHERE to_date(date, 'YYYY-DD-MM') BETWEEN date '2016-05-31' AND date '2016-01-01';
或者只使用没有类型的字符串文字。类型date
从此表达式中的上下文推迟。你甚至不需要to_date()
。由于您已经使用ISO格式。普通演员是安全的:
WHERE date::date BETWEEN '2016-05-31' AND '2016-01-01';
请务必对所有日期字符串使用ISO 8601格式,因此它们对任何语言环境都是明确无误的。
您甚至可以使用表达式索引来支持查询。匹配查询中使用的实际表达式:
CREATE INDEX tbl_date_idx ON tbl ((date::date)); -- parentheses required!
但我不会使用基本类型名称date
作为标识符开始。