01 MySQL日期列中存储的日期
在MySQL中,日期和时间类型用于存储日期和时间的值。日期和时间类型在很多应用程序中都是很有用的,尤其是在 Web 应用程序和数据库应用程序之中。MySQL支持多种日期和时间类型,包括:DATE、DATETIME、TIMESTAMP 和 YEAR。
其中,DATE 类型用于存储日期,格式为 YYYY-MM-DD,例如 2022-08-10;DATETIME 类型用于存储日期和时间,格式为 YYYY-MM-DD HH:MM:SS,例如 2022-08-10 05:36:14;TIMESTAMP 类型存储从 UNIX 纪元(1970 年 1 月 1 日 00:00:00 UTC)开始的秒数,但仅限于 1970 年至 2038 年之间;YEAR 类型用于存储 2 位或 4 位格式的年份。
02 MySQL中日期的限制
在MySQL中,日期有一些限制条件,其最小日期是1000-01-01,最大日期是9999-12-31。如果您输入的日期超出这个范围,将会在 INSERT 或 UPDATE 语句时收到错误消息。
03 MySQL中日期列插入非法日期
如果您在MySQL的日期列中,尝试插入一个不合法的日期,MySQL将会抛出一个错误消息,该错误消息是“Incorrect date value: '2000-02-30' for column 'date' at row 1”。
04 存储不合法的日期的方法
在MySQL中,如果您必须存储像 02 月 30 日这样的日期,则可以使用以下方法:
(1)将日期类型修改为字符类型
如果您想要存储不合法的日期,但不需要对日期进行计算、排序或比较,则最简单的方法是将日期列的数据类型从日期类型更改为字符类型。您可以使用 VARCHAR 或 TEXT 数据类型来存储日期。由于日期被存储为字符串,因此您可以存储任何您喜欢的日期值,而不必担心MySQL是否认为该日期是合法的。
(2)存储为 NULL 值
如果您使用 DATE 或 DATETIME 数据类型存储日期,但您不需要在必须记录不合法日期的情况下强制其成为有效日期,或者您不想使用字符类型,那么您可以将不合法日期存储为 NULL 值。这种方法需要您指定列允许 NULL 值并插入 NULL 值。
(3)修改MySQL内置ctype库
在MySQL内部,使用ctype库来检查输入的数据是否有效。除了进行基本的数据检查之外,ctype库还可以检查日期和时间是否在允许的范围内。如果您对MySQL进行编译,则可以更改 ctype 库以允许无效的日期。这种方法需要您具有一些编程技能才能进行MySQL的编译。
05 修改MySQL内置ctype库的方法
如果您想要在MySQL中存储无效的日期,您可以尝试修改MySQL内置ctype库。修改 ctype 库的方法是:
(1)找到 ctype_cp932.c 文件
ctype_cp932.c 文件位于 MySQL 的安装源代码中的“strings”目录中。在此文件中添加以下代码:
static const unsigned char my_ctype_utf8[] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00-0F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 10-1F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20-2F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 30-3F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40-4F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 50-5F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60-6F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 70-7F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 80-8F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 90-9F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // A0-AF
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // B0-BF
0,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,0, // C0-CF
0,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,0, // D0-DF
0,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,0, // E0-EF
0,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,0, // F0-FF
};
static const uchar my_ctype_8bit[] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
static const ulong my_ctype_mb_wc[32]= {
0x00000000,0x00000001,0x00000002,0x00000003,
0x00000004,0x00000005,0x00000006,0x00000007,
0x00000008,0x00000009,0x0000000A,0x0000000B,
0x0000000C,0x0000000D,0x0000000E,0x0000000F,
0x00000010,0x00000011,0x00000012,0x00000013,
0x00000014,0x00000015,0x00000016,0x00000017,
0x00000018,0x00000019,0x0000001A,0x0000001B,
0x0000001C,0x0000001D,0x0000001E,0x0000001F,
};
#define my_isalpha(c) (my_ctype_utf8[(uchar)(c)] & 0x20)
#undef my_mb_wc
#define my_mb_wc(my_str, end) \
((end > my_str + 1) ? (((uint) my_str[0] << 24) | \
(((uchar) my_str[1]) << 16) | \
(((uchar) my_str[2]) << 8) | \
(((uchar) my_str[3]))) : \
(end > my_str) ? \
(my_ctype_mb_wc[(uchar) \
my_str[0]] & ((1UL << 31) | 0x00FFFFFFUL)) : \
1)
这将允许 ctype 库接受任何输入字符,并允许您存储不合法的日期。在添加此代码后,您需要重新编译所有MySQL程序,以便ctype库的更改得到正确的编码。
06 总结
在MySQL中,有一些方法可以用于存储非法的日期。如果您只是想存储日期,但不需要对其进行计算或排序,则最简单的方法是将日期列的数据类型从 DATE 或 DATETIME 更改为 VARCHAR 或 TEXT。如果您需要在必须记录不合法日期的情况下强制其成为有效日期,则可以将不合法日期存储为 NULL 值。或者,如果您具有编程技能并知道如何进行MySQL的编译,则可以修改 ctype 库以允许无效日期的存储。