我有一个 ID 字段,我希望它具有以下格式: YYMMDDXXXXXXXX,其中 YY 是年份,MM 是月份,DD 是日期,XXXXXXXX 是带前导零的实际 ID 号。此外,当日期更改时,ID 号应重置为 0。
首先,对于也将成为主键的 ID 字段来说,这是一个不太好的做法/格式吗?
实现:
我正在将数据插入到我的数据库中,我想出了两种方法来实现上述格式。
- 使用 php 插入查询手动插入(没有 AUTO_INCREMENT )
字段),我选择 MAX(id),将其拆分(日期-id),检查这一天是否有
更改,然后将其加一或替换为
新日期+0s。这种方式的问题是我必须做额外的事情
SELECT 并检查/更改字符串,如果我有超过 20 个,SELECT 可能会返回相同的 MAX(id)
请求/秒以及
date('Ymd')
导致 apache 崩溃 每秒超过 60 个请求。 - 在 ID 字段上添加 AUTO_INCRMENT 并将 AUTO_INCRMENT 设置为
YYMMDD00000000 当日期改变时,则让 auto_increment
做这份工作。我试过
ALTER TABLE foo AUTO_INCREMENT=(SELECT CURDATE()*100000000)
但正如我所料 CURDATE() 不能 像这样使用。
对我的尝试有任何想法和/或帮助都会很棒,感谢您的宝贵时间。
最佳答案
理智的方式:
- 告诉您的团队经理,此设计存在严重缺陷。
请改为呈现以下架构:
CREATE TABLE foo ( id INTEGER AUTO_INCREMENT, date DATETIME DEFAULT=NOW(), PRIMARY KEY (id), INDEX (date) );
如有必要,使用查询生成类似样式的 ID:
SELECT CAST(DATE_FORMAT(date,'%Y%m%d') AS UNSIGNED)*100000000 + id AS 'weird_id'
尽管如果您的 ID 超过 10,000,000,这就会偏离轨道,但我的测试表明,针对此方案使用 BIGINT 应该能够处理一两个以上的零。您还可以通过选择此 ID 作为字符串来绕过整数类型限制,例如:
SELECT CONCAT(DATE_FORMAT(date, '%Y%m%d'), LPAD(id,10,'0')) AS 'weird_id'
其中
LPAD()
中的10
可以是任意数量的数字。
不理智、保全面子、导致 future 噩梦的方式:
你几乎已经拥有它了。 CURDATE()
返回一个字符串,而 ALTER TABLE foo AUTO_INCRMENT=
期望一个整数,但只能是一个整数。没有函数、变量等。以下内容将起作用:
重击:
mysql -u root -e "ALTER TABLE dbname.foo AUTO_INCREMENT = $(date +%Y%m%d0000000000);"
PHP:
$query = sprintf("ALTER TABLE dbname.foo AUTO_INCREMENT = %s;", str_pad(date("Ymd", time()), 18, '0'));
这会破坏:
- 每当 crond 出现问题时
- 可能是在夏令时变更期间
- 随机且没有明显原因
- 9999 年 12 月 31 日午夜之后
请您自己以及从您那里继承此项目的人帮忙,并在此表中保留一个单独的 DATETIME
列,以便将来仍可以从中收集有意义的、未损坏的信息。
关于php - 在 mysql id 上添加日期前缀,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26021765/