叽里呱啦实习第十天

主键:
数据库主键设计之思考

主键的必要性:

有些朋友可能不提倡数据库表必须要主键,但在我的思考中,觉得每个表都应该具有主键,不管是单主键还是双主键,主键的存在就代表着表结构的完整性,表的记录必须得有唯一区分的字段,主键主要是用于其他表的外键关联,本记录的修改与删除,当我们没有主键时,这些操作会变的非常麻烦。

主键的无意义性:

我强调主键不应该具有实际的意义,这可能对于一些朋友来说不太认同,比如订单表吧,会有“订单编号”字段,而这个字段呢在业务实际中本身就是应该具有唯一性,具有唯一标识记录的功能,但我是不推荐采用订单编号字段作为主键的,因为具有实际意义的字段,具有“意义更改”的可能性,比如订单编号在刚开始的时候我们一切顺利,后来客户说“订单可以作废,并重新生成订单,而且订单号要保持原订单号一致”,这样原来的主键就面临危险了。因此,具有唯一性的实际字段也代表可以作为主键。因此,我推荐是新设一个字段专门用为主键,此主键本身在业务逻辑上不体现,不具有实际意义。而这种主键在一定程序增加了复杂度,所以要视实际系统的规模大小而定,对于小项目,以后扩展不会很大的话,也查允许用实际唯一的字段作主键的。

主键的选择

我们现在在思考一下,应该采用什么来作表的主键比较合理,申明一下,主键的设计没有一个定论,各人有各人的方法,哪怕同一个,在不同的项目中,也会采用不同的主键设计原则。

第一:编号作主键

此方法就是采用实际业务中的唯一字段的“编号”作为主键设计,这在小型的项目中是推荐这样做的,因为这可以使项目比较简单化,但在使用中却可能带来一些麻烦,比如要进行“编号修改”时,可能要涉及到很多相关联的其他表,就象黎叔说的“后果很严重”;还有就是上面提到的“业务要求允许编号重复时”,我们再那么先知,都无法知道业务将会修改成什么?

第二:自动编号主键

这种方法也是很多朋友在使用的,就是新建一个ID字段,自动增长,非常方便也满足主键的原则,优点是:数据库自动编号,速度快,而且是增量增长,聚集型主键按顺序存放,对于检索非常有利;数字型的,占用空间小,易排序,在程序中传递也方便;如果通过非系统增加记录(比如手动录入,或是用其他工具直接在表里插入新记录,或老系统数据导入)时,非常方便,不用担心主键重复问题。

缺点:其实缺点也就是来自其优点,就是因为自动增长,在手动要插入指定ID的记录时会显得麻烦,尤其是当系统与其他系统集成时,需要数据导入时,很难保证原系统的ID不发生主键冲突(前提是老系统也是数字型的);如果其他系统主键不是数字型那就麻烦更大了,会导致修改主键数据类型了,这也会导致其他相关表的修改,后果同样很严重;就算其他系统也是数字型的,在导入时,为了区分新老数据,可能想在老数据主键前统一加一个“o”(old)来表示这是老数据,那么自动增长的数字型又面临一个挑战。

第三:Max加一

由于自动编号存在那些问题,所以有些朋友就采用自己生成,同样是数字型的,只是把自动增长去掉了,采用在Insert时,读取Max值后加一,这种方法可以避免自动编号的问题,但也存在一个效率问题,如果记录非常大的话,那么Max()也会影响效率的;更严重的是并发性问题,如果同时有两人读到相同的Max后,加一后插入的ID值会重复,这已经是有经验教训的了。

第四:自制加一

考虑Max加一的效率后,有人采用自制加一,也就是建一个特别的表,字段为:表名,当前序列值。这样在往表中插入值时,先从此表中找到相应表的最大值后加一,进行插入,有人可能发现,也可能会存在并发处理,这个并发处理,我们可以采用lock线程的方式来避免,在生成此值的时,先Lock,取到值以后,再unLock出来,这样不会有两人同时生成了。这比Max加一的速度要快多了。但同样存在一个问题:在与其他系统集成时,脱离了系统中的生成方法后,很麻烦保证自制表中的最大值与导入后的保持一致,而且数字型都存在上面讲到的“o”老数据的导入问题。因此在“自制加一”中可以把主键设为字符型的。字符型的自制加一我倒是蛮推荐的,应该字符型主键可以应付很多我们意想不到的情况。

第五:GUID主键

目前一个比较好的主键是采用GUID,当然我是推荐主键还是字符型的,但值由GUID生成,GUID是可以自动生成,也可以程序生成,而且键值不可能重复,可以解决系统集成问题,几个系统的GUID值导到一起时,也不会发生重复,就算有“o”老数据也可以区分,而且效率很高,在.NET里可以直接使用System.Guid.NewGuid()进行生成,在SQL里也可以使用 NewID()生成。优点是:

同 IDENTITY 列相比,uniqueidentifier 列可以通过 NewID() 函数提前得知新增加的行 ID,为应用程序的后续处理提供了很大方便。

便于数据库移植,其它数据库中并不一定具有 IDENTITY 列,而 Guid 列可以作为字符型列转换到其它数据库中,同时将应用程序中产生的 GUID 值存入数据库,它不会对原有数据带来影响。

便于数据库初始化,如果应用程序要加载一些初始数据, IDENTITY 列的处理方式就比较麻烦,而 uniqueidentifier 列则无需任何处理,直接用 T-SQL 加载即可。

便于对某些对象或常量进行永久标识,如类的 ClassID,对象的实例标识,UDDI 中的联系人、服务接口、tModel标识定义等。

缺点是:

GUID 值较长,不容易记忆和输入,而且这个值是随机、无顺序的。

GUID 的值有 16 个字节,与其它那些诸如 4 字节的整数相比要相对大一些。这意味着如果在数据库中使用 uniqueidentifier 键,可能会带来两方面的消极影响:存储空间增大;索引时间较慢。

我也不是推荐GUID最好,其实在不同的情况,我们都可以采用上面的某一种方式,思考了一些利与弊,也方便大家在进行设计时参考。这些也只是我的一点思考而已,而且可能我知识面限制,会有一些误论在里面,希望大家有什么想法欢迎讨论。

1、显示某个数据库中的所有表:
show tables;
2、显示数据表的结构:desc 表名;
示例:
desc personTable;
或:show columns from 表名;
示例:
show columns from personTable;
3、创建数据表:
(1)设置主键primary key唯一性:create tabel 表名(字段名称 字段类型, ……);
示例:
create table personTable (personID int, name varchar(20), gender varchar(10), primary key(personID));
或判断表是否不存在 if not exists才新建: create table if not exists personTable (personID int, name varchar(20),gender varchar(10),primary key(personID));
或某个字段自增auto_increment:
create table if not exists moneyTable (moneyID int auto_increment,personID int,date varchar(10),money decimal,primary key(moneyID));
(2)创建临时表temporary(临时表只在当前连接可见,当关闭连接时,Mysql会自动删除表并释放所有空间。如果你使用了其他MySQL客户端程序连接MySQL数据库服务器来创建临时表,那么只有在关闭客户端程序时才会销毁临时表,当然你也可以手动销毁。):create temporary table 表名 (字段名称 字段类型,…);
示例:
create temporary table bookTable (bookID int, bookName varchar(20),bookMoney double);
(3)复制表
()只复制表结构(没有表数据):create table 新表名 like 旧表名;
示例:
create table moneyTmp like moneyTable;
(b)复制表结构和表数据:create table 新表名 select * from 旧表名;
示例:
create table moneyTmp select * from moneyTable;
(c)复制指定表字段并改字段名称和表数据:create table 新表名 as select 旧字段名 as 新字段名,… from 旧表名;
示例:
create table moneyTmp as select moneyID as id,personID,date as time,money from moneyTable;
4、数据表中列的操作:
(1)添加新列:alter table 表名 add 字段名称 字段类型;
示例:
alter table personTable add age int;
(2)删除列:alter table 表名 drop 字段名称;
示例:
alter table personTable drop age;
(3)修改列名称:alter table 表名 change 修改前字段名称 修改后字段名称 修改后字段类型;
示例:
alter table personTable change job gangwei varchar(20);
(4)修改列类型:alter table 表名 modify 字段名称 修改后字段类型;
示例:
alter table personTable modify name char(30);
5、删除数据表:drop table 表名;
示例:
drop table personTable;
6、复制表:create table 新表名 like 被复制表名;
示例:
create table personTmp like personTable;
7、数据简单操作
(1)查询数据:select * from 表名 where 字段 = 值;
示例:
查询全部:
select * from personTable;
条件查询:
select * from personTable where age = 35;
或:
select name,age,gender from personTable;
或某个值非空的条件:
select * from personTable where schoolID is not null;
或某个值为空的条件:
select * from personTable where schoolID is null;
或:
select name,age,gender from personTable where personID=1000;
或:
select * from personTable where age=30 or age=35;
或like模糊匹配:
select * from personTable where name like ‘ios%’;
或like模糊匹配时的并列多条件:
select * from personTable where name like ‘ios%’ and age=35;
或升序(默认升序):
select * from personTable order by age asc;
或降序:
select * from personTable order by age desc;
或双表查询去掉重复使用union:
select schoolID from personTable union select schoolID from schoolTable;
或双表查询不去掉重复union all:
select schoolID from personTable union all select schoolID from schoolTable;
或结果分组group by计算个数count():
select job,count(
) from personTable group by job;
或结果分组(含计算个数,总数):
select coalesce(job,‘总数’),count(*) from personTable group by job with rollup;
或join连表查询某个值相同:
select a.personID,a.name,a.gender,a.age,b.name from personTable a join schoolTable b on a.schoolID=b.schoolID;
(2)插入数据:
()insert into 表名 (字段1, ……) values (值1, ……);
示例:
insert into personTable (personId, name, gender, age) values (1000, ‘devZhang’, “male”, 35);
(b)避免重复数据ignore需要设置primary key主键:insert ignore into 表名 (字段名,…) values (值,…);
示例:
insert ignore into tmpTable (name,time) values (‘devZhang’,‘201806’);
(3)更新数据:update 表名 字段=值,…,字段n=值n where 字段=值;
示例:
update personTable set age = 25,name = “uiChen”,gender=‘female’ where personId = 1001;
(4)删除数据:delete from 表名 where 字段=值;
示例:
delete from personTable where age = 23;


登录MysQL

在终端下输入以下命令

  1. mysql -u root -p
  2. 输入密码

(1)显示所有数据库列表:show databases;

(2)建库:create database Mytest;(Mytest库名)

(3)打开某个数据库(比如数据库:Mytest):use Mytest;

(4)显示本库中的所有表:show tables;

(5)建表:create table 表名 (字段设定列表); // :creat table mytest_acount (col1 INT, col2 CHAR(5), col3 DATE); 表至少一列。

(6)显示某表的结构:describe table1;

(7)删库:drop database 库名;

(8)删表:drop table 表名;

(9)将表中的记录清空:delete from 表名;

(10)显示表中的记录:select * from 表名;

6、退出mysql:exit

7、启动和停止mysql

启动:/usr/local/mysql/share/mysql.server start

停止:/usr/local/mysql/bin/mysqladmin -u root -p shutdown

输入root密码。

快捷路径配置方法:

  1. 打开终端输入: pico .bash_profile; 回车

  2. 将此路径配置进去: export PATH=$PATH:/usr/local/mysql/bin/

  3. 重新打开终端,然后 直接: mysql -u -p ;

(即可一般都会添加这个路径,否则很不方便使用mysql的说~)

修改MySQL登录密码的方法:

  1. $ ./mysql

2.$ FLUSH PRIVILEGES;

3.$ SET PASSWORD FOR ‘root’@‘localhost’ = PASSWORD(‘你的新密码’);

(至此,密码修改完成,可以成功登陆。)

mysql验证功能的方法:

1.登录管理员权限$ sudo su

2.禁止mysql验证功能 $ ./mysqld_safe --skip-grant-tables &

3.mysql会自动重启(偏好设置中mysql的状态会变成running)

(注意:设置完成以后就不能手动关闭了,除非开机重启)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值