MySQL中国家/地区的数据类型

MySQL中国家/地区的数据类型,mysql,database,Mysql,Database,我正在为自己创建一个数据库,我有一个登记表,询问人们的姓名、密码、电子邮件、手机、年龄和位置。它有望成为一个交友网站 到目前为止,我已经(为我的数据库) 编辑忘了问问题 位置应使用什么数据类型,数据库看起来是否足够安全 位置按国家/地区排列,并通过下拉菜单选择。创建一个国家/地区表,该表将存储您想要支持的所有国家/地区 code CHAR(2) PRIMARY KEY, name VARCHAR(50) NOT NULL UNIQUE code | name =====|===== FR

我正在为自己创建一个数据库,我有一个登记表,询问人们的姓名、密码、电子邮件、手机、年龄和位置。它有望成为一个交友网站

到目前为止,我已经(为我的数据库)

编辑忘了问问题

位置应使用什么数据类型
,数据库看起来是否足够安全


位置按国家/地区排列,并通过下拉菜单选择。

创建一个
国家/地区
表,该表将存储您想要支持的所有国家/地区

code CHAR(2) PRIMARY KEY,
name VARCHAR(50) NOT NULL UNIQUE

code | name
=====|=====
  FR | France
  GB | United Kingdom
  US | United States of America
  .. | ...
您可以在此处找到ISO 3166-1代码:

使用此表创建下拉菜单

在“成员”表中定义列

country_code CHAR(2) NOT NULL
它应该是引用
国家/地区表的外键

CONSTRAINT FOREIGN KEY fk_members_countries (country_code) REFERENCES countries(code)
数据库看起来足够安全吗

不,这需要一点时间来解释

让我们从所有这些限制开始。过度使用列限制是一个非常常见的问题

这些限制的工作原理经常被误解,例如,您询问了安全问题,或者您可能认为您在节省空间。真正的问题是,它硬编码了关于软件其余部分在数据库中的行为的不必要的限制,而您的限制非常小

你问这是否使桌子更安全。列限制实际上与安全性无关,虽然我想理论上它们会阻止某人填满你的磁盘,但这不是你的限制

例如,您的密码限制为16个字符。这不是数据库应该做的决定,而是安全考虑。当您稍后研究密码安全性时,您会发现16个字符的密码几乎不够。您需要更像64或128的数据,这将需要一个昂贵的
altertable

更重要的是,您将密码存储在clear中。这是一个很大的安全问题

然后你的电子邮件(大概是电子邮件地址)设置为320个字符?!那是一个该死的电子邮件地址!但是用户的名字只能得到16个

一个常见的误解是,这些限制会减少磁盘使用量。他们没有
varchar
将仅存储该行所需的数据
age INT(3)
使用的空间并不小于
age INT
,而是固定大小。好的,它确保你的交友网站上没有12938岁的人,甚至没有。它只是显示了多少字段,这肯定不应该出现在您的模式中。MySQL做了一些奇怪的事情

您可以使用在1字节中存储0到255的。。。但一旦你担心单个字节,它就会变得愚蠢。这都是毫无意义的,根本不要考虑他们的年龄。储存他们的生日。因为人们变老了


关于使用极限的错误方法已经足够了,什么是正确的方法

限制用于强制执行数据完整性(和技术限制,请参见注释)。就这样。您希望创建一个足够灵活的模式来支持您的应用程序想要成为的任何东西,同时确保数据是它所说的,而不必不断地猜测它

更好的模式可能如下所示:

create table members(
    id primary key auto_increment,

    username varchar(64) unique,
    password_hash varchar(128),
    email varchar(64) unique,
    mobile varchar(32),
    birthday datetime,

    location integer references(locations),

    index(birthday)
)
您的表缺少主键,这是一个大问题。用户名可以更改,如果更改,您不希望引用该用户的所有内容都中断。相反,请使用简单的自动递增整数。“但我不会让用户更改他们的名字!”是的,还记得我说过的关于将软件硬编码到数据模型中的限制吗?您构建模式的方式影响了多年

最初,我取消了字段的所有限制,并将其切换为无限
文本
。他们都没有令人信服的限制理由。除非有很好的理由,否则只需使用
text
varchar
。限制在数据模型中处理,可由程序员和设计师更改。
text
varchar
字段将只使用所需的空间

……但@PaulSpiegel在评论中指出。我已经习惯了没有这种限制的博士后考试。因此,我将它们切换到
varchar
,并选择了慷慨的限制。技术限制可能是使用限制的原因

用户名
(不是
用户
,因为它可以指整个用户,而不仅仅是他们的名字)和
电子邮件
都被标记为
唯一
。这是关于数据完整性的,您不希望两个人使用相同的用户名,并且您希望确保每个帐户都有一个单一的联系人(您可能会认为这是在将行为放入数据库,您可能是对的,但是删除唯一索引比添加索引更容易)

然后我们来谈谈突出的安全问题从不存储密码永远。永远永远。而是存储密码的散列。如果你不知道我在说什么,现在就停下来读

我们不存储
年龄
,而是将他们的
生日
存储为
日期时间
。存储用户的年龄不是前瞻性的,明年会发生什么?根据他们的生日,你可以计算他们的年龄,甚至给他们生日礼物!通过将其存储为
datetime
,您可以使用它进行各种日期计算

你问我该怎么处理这个位置。位置可能意味着很多事情,而且可能变得相当复杂。这不是您现在需要做的决定,所以最好是这样做,以便以后可以扩展和更改它。将它放在自己的表中,并使用外键引用它。我们稍后再谈,这就是重点

最后是索引。你不必吝啬于磁盘空间,只存储用户名的前6个字符!通过用户名查找用户将非常困难
create table members(
    id primary key auto_increment,

    username varchar(64) unique,
    password_hash varchar(128),
    email varchar(64) unique,
    mobile varchar(32),
    birthday datetime,

    location integer references(locations),

    index(birthday)
)
create table locations (
    id integer primary key,

    city text,
    province text,
    country text,
    postal_code text
);