当前位置:首页 » 数据仓库 » 数据库表设计案例
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

数据库表设计案例

发布时间: 2023-05-25 05:12:47

数据库课程设计实例

数据库课程设计

题目:小型超市管理系统
1、项目计划
1.1系统开发目的
(1)大大提高超市的运作效率;
(2)通过全面的信息采集和处理,辅助提高超市的决策水平;
(3)使用本系统,可以迅速提升超市的管理水平,为降低经营成本, 提高效益,增强超市扩张力, 提供有效的技术保障。
1.2背景说明
21世纪,超市的竞争也进入到了一个全新的领域,竞争已不再是规模的竞争,而是技术的竞争、管理的竞争、人才的竞争。技术的提升和管理的升级是超市业的竞争核心。零售领域目前呈多元发展趋势,多种业态:超市、仓储店、便利店、特许加盟店、专卖店、货仓等相互并存。如何在激烈的竞争中扩大销售额、降低经营成本、扩大经营规模,成为超市营业者努力追求的目标。
1.3项目确立
针对超市的特点,为了帮助超市解决现在面临的问题,提高小型超市的竞争力,我们将开发以下系统:前台POS销售系统、后台管理系统,其中这两个子系统又包含其它一些子功能。
1.4应用范围
本系统适应于各种小型的超市。
1.5 定义
(1)商品条形码:每种商品具有唯一的条形码,对于某些价格一样的商品,可以使用自定义条形码。
(2)交易清单:包括交易的流水账号、每类商品的商品名、数量、该类商品的总金额、交易的时间、负责本次收银的员工号。
(3)商品积压:在一定时期内,远无法完成销售计划的商品会造成积压。
(4)促销:在一定时期内,某些商品会按低于原价的促销价格销售。
库存告警提示:当商品的库存数量低于库存报警数量时发出提示。
(5)盘点:计算出库存、销售额、盈利等经营指标。
1.6 参考资料
《数据库原理及设计》 陶宏才编 清华大学出版社
sql Server 2000 实用教程》范立南编 清华大学出版社
《SQL Server 2000 编程员指南》李香敏编 北京希望电子出版社
《轻松搞定 SQL Server 2000 程序设计》Rebecca M.Riordan编
《软件工程规范》Watts S.Humphrey编 清华大学出版社
《软件工程理论与实践》 Shari Lawrence Pfleeger编 清华大学出版社
《软件需求分析》 Swapna Kishore编 机械工业出版社
《软件工程思想》 林锐编

2、逻辑分析与详细分析
2.1系统功能
(1)、零售前台(POS)管理系统,本系统必须具有以下功能:
 商品录入:根据超巿业务特点制定相关功能,可以通过输入唯一编号、扫描条形码、商品名称等来实现精确或模糊的商品扫描录入。该扫描录入方法可以充分保证各种电脑操作水平层次的人员均能准确快速地进行商品扫描录入。
 收银业务:通过扫描条形码或者直接输入商品名称(对于同类多件商品采用一次录入加数量的方式)自动计算本次交易的总金额。在顾客付款后,自动计算找零,同时打印交易清单(包括交易的流水账号、每类商品的商品名、数量、该类商品的总金额、交易的时间、负责本次收银的员工号)。如果顾客是本店会员并持有本人会员卡,则在交易前先扫描会员卡,并对所购物品全部实行95折优惠,并将所购物品的总金额累计到该会员的总消费金额中。 会员卡的有效期限为一年,满一年未续卡者,该会员卡将被注销。
 安全性:OS登陆、退出、换班与操作锁定等权限验证保护;断电自动保护最大限度防止意外及恶意非法操作。
 独立作业:有的断网收银即在网络服务器断开或网络不通的情况下,收银机仍能正常作业
(2)、后台管理系统,本系统必须具备以下功能
 进货管理: 根据销售情况及库存情况,自动制定进货计划(亦可手工制定修改),可以避免盲目进货造成商品积压。 按计划单有选择性地进行自动入库登记。 综合查询打印计划进货与入库记录及金额。
 销售管理: 商品正常销售、促销与限量、限期及禁止销售控制。 综合查询各种销售明细记录、各地收银员收银记录以及交结账情况等。 按多种方式统计生成销售排行榜,灵活察看和打印商品销售日、月、年报表。
 库存管理: 综合查询库存明细记录。 库存状态自动告警提示。如库存过剩、少货、缺货等。软件为您预警,避免库存商品积压损失和缺货。 库存自动盘点计算。
 人员管理: 员工、会员、供货商、厂商等基本信息登记管理。 员工操作权限管理。 客户销售权限管理。

(3)系统结构
系统总体结构

模块子系统结构

功能描述:商品录入子系统要求能快速录入商品,因此必须支持条形码扫描。

功能描述:收银业务子系统能计算交易总额,打印交易清单,并根据会员卡打折。

功能描述:进货管理子系统可以根据库存自动指定进货计划,进货时自动等级,以及提供查询和打印计划进货与入库记录的功能。

功能描述:销售管理子系统可以控制某商品是否允许销售,查询每种商品的销售情况并产生年、月、日报表,同时可以生成销售排行榜。

功能描述:库存管理子系统提供查询库存明细记录的基本功能,并根据库存的状态报警,以及自动盘点计算。

功能描述:人员管理子系统提供基本信息登记管理,员工操作权限管理,客户销售权限管理的功能。
2.2、流程图
前台管理系统

顶层DFD图

第0层DFD图

第1层DFD图

2.3、户类型与职能
(1)、员工(营业员):
 通过商品条形码扫描输入商品到购买清单
 操作软件计算交易总金额
 操作软件输出交易清单
 对会员进行会员卡扫描以便打折
(2)、:超市经理
 操作软件录入商品,供货商,厂商
 操作软件制定进货计划
 查询打印计划进货与入库记录
 操作软件控制商品销售与否
 查询打印销售情况
 操作软件生成销售排行榜
 查询库存明细记录
 根据软件发出的库存告警进行入货
 操作软件进行盘点计算
(3)、总经理:
 基本信息登记管理
 员工操作权限管理
 客户销售权限管理
2.4、统开发步骤
 确定参与者和相关的用况
 为每个用况设计过程
 建立顺序图,确定每个脚本中对象的协作
 创建类,确定脚本中的对象
 设计, 编码, 测试, 集成类
 为过程编写系统测试案例
 运行测试案例,检验系统
2.5、系统环境需求
 系统模式

本系统采用C/S模式作为开发模式
 硬件环境
服务器端:
高性能的计算机一台,
普通的双绞线作为连接。
客户端: 普通的计算机或者工作站,
普通的双绞线作为连接。
 软件环境
服务器端:安装SQL Server 2000的服务器版本,
安装windows 2000服务器版本,
配置了诺顿等必须的防毒软件。
客户端: 安装SQL Server2000的服务器版本,
安装了VB等可视化开发工具软件,
安装windows2000服务器版本。

2.6、系统安全问题
信息系统尽管功能强大,技术先进,但由于受到自身体系结构,设计思路以及运行机制等限制,也隐含许多不安全因素。常见因素有:数据的输入,输出,存取与备份,源程序以及应用软件,数据库,操作系统等漏洞或缺陷,硬件,通信部分的漏洞,企业内部人员的因素,病毒,“黑客”等因素。因此,为使本系统能够真正安全,可靠,稳定地工作,必须考虑如下问题:为保证安全,不致使系统遭到意外事故的损害,系统因该能防止火,盗或其他形式的人为破坏。
 系统要能重建
 系统应该是可审查的
 系统应能进行有效控制,抗干扰能力强
 系统使用者的使用权限是可识别的
3、基于UML的建模
3.1语义规则
用例模型(use cases view)(用例视图)的基本组成部件是用例(use case)、角色(actor)和系统(system)。用例用于描述系统的功能,也就是从外部用户的角度观察,系统应支持哪些功能,帮助分析人员理解系统的行为,它是对系统功能的宏观描述,一个完整的系统中通常包含若干个用例,每个用例具体说明应完成的功能,代表系统的所有基本功能(集)。角色是与系统进行交互的外部实体,它可以是系统用户,也可以是其它系统或硬件设备,总之,凡是需要与系统交互的任何东西都可以称作角色。系统的边界线以内的区域(即用例的活动区域)则抽象表示系统能够实现的所有基本功能。在一个基本功能(集)已经实现的系统中,系统运转的大致过程是:外部角色先初始化用例,然后用例执行其所代表的功能,执行完后用例便给角色返回一些值,这个值可以是角色需要的来自系统中的任何东西。
UML:是一种标准的图形化建模语言,它是面向对象分析与设计的一种标准表示;它不是一种可视化的程序设计语言而是一种可视化的建模语言;不是工具或知识库的规格说明而是一种建模语言规格说明是一种表示的标准;不是过程也不是方法但允许任何一种过程和方法使用它。

用例(use case):

参与者(actor):

3.2、UML模型
3.21、系统UML模型

3.22、子系统UML模型
(1)零售前台(POS)管理系统用例视图

(2)后台管理系统用例视图

3.3、系统实现图

4、超市销售系统概念设计文档
(1)、系统ER图

(2)、系统ER图说明
1) 商店中的所有用户(员工)可以销售多种商品,每种商品可由不同用户(员工)销售;
2) 每个顾客可以购买多种商品,不同商品可由不同顾客购买;
3) 每个供货商可以供应多种不同商品,每种商品可由多个供应商供应。
(3)、视图设计
1) 交易视图(v_Dealing)——用于查询交易情况的视图;
2) 计划进货视图(v_PlanStock)——用于查询进货计划的视图;
3) 销售视图(v_Sale)——用于查询销售明细记录的视图;
4) 入库视图(v_Stock)——用于查询入库情况的视图。
5、逻辑设计文档
(1)、系统关系模型
a) 商品信息表(商品编号,商品名称,价格,条形码,促销价格,促销起日期,促销止日期,允许打折,库存数量,库存报警数量,计划进货数,允许销售,厂商编号,供货商编号)
b) 用户表(用户编号,用户名称,用户密码,用户类型)
c) 会员表(会员编号,会员卡号,累积消费金额,注册日期)
d) 销售表(销售编号,商品编号,销售数量,销售金额,销售日期)
e) 交易表(交易编号,用户名称,交易金额,会员卡号,交易日期)
f) 进货入库表(入库编号,入库商品编号,入库数量,单额,总额,入库日期,计划进货日期,入库状态)
g) 供货商表(供货商编号,供货商名称,供货商地址,供货商电话)
h) 厂商表(厂商编号,厂商名称,厂商地址,厂商电话)

(2)、系统数据库表结构
数据库表索引
表名 中文名
MerchInfo 商品信息表
User 用户表
Menber 会员表
Sale 销售表
Dealing 交易表
Stock 进货入库表
Provide 供货商表
Factory 厂商表

商品信息表(MerchInfo)
字段名 字段类型 长度 主/外键 字段值约束 对应中文名
MerchID int 4 P Not null 商品编号
MerchName Varchar 50 Not null 商品名称
MerchPrice Money 4 Not null 价格
MerchNum Int 4 Not null 库存数量
CautionNum Int 4 Not null 库存报警数量
PlanNum Int 4 null 计划进货数
BarCode Varchar 50 Not null 条形码
SalesProPrice Money 4 促销价格
SalesProDateS Datetime 8 促销起日期
SalesProDateE Datetime 8 促销止日期
AllowAbate Int 4 Not null 允许打折
AllowSale Int 4 Not null 允许销售
FactoryID Varchar 10 F Not null 厂商编号
ProvideID Varchar 10 F Not null 供货商编号

用户表(User)
字段名 字段类型 长度 主/外键 字段值约束 对应中文名
UserID varchar 10 P Not null 用户编号
UserName Varchar 25 Not null 用户名称
UserPW Varchar 50 Not null 用户密码
UserStyle Int 4 Not null 用户类型

会员表(Menber)
字段名 字段类型 长度 主/外键 字段值约束 对应中文名
MemberID Varchar 10 P Not null 会员编号
MemberCard Varchar 20 Not null 会员卡号
TotalCost Money 4 Not null 累积消费金额
RegDate Datetime 8 Not null 注册日期

销售表(Sale)
字段名 字段类型 长度 主/外键 字段值约束 对应中文名
SaleID Varchar 10 P Not null 销售编号
MerChID Varchar 10 F Not null 商品编号
SaleDate Datetime 8 Not null 销售日期
SaleNum Int 4 Not null 销售数量
SalePrice Money 4 Not null 销售单额

交易表(Dealing)
字段名 字段类型 长度 主/外键 字段值约束 对应中文名
DealingID Varchar 10 P Not null 交易编号
DealingPrice Money 4 Not null 交易金额
DealingDate Money 4 Not null 交易日期
MemberID Varchar 10 会员卡号
UserName Varchar 10 F Not null 用户名称

入库纪录表(Stock)
字段名 字段类型 长度 主/外键 字段值约束 对应中文名
StockID Varchar 10 P Not null 入库编号
MerchID Varchar 10 F Not null 入库商品编号
MerchNum Int 4 Not null 入库数量
MerchPrice Money 4 Not null 单额
TotalPrice Money 4 Not null 总额
StockDate Datetime 8 Datetime 入库日期
PlanDate Datetime 8 Datetime 计划进货日期
StockState Int 4 Not null 入库状态

供货商表(Provide)
字段名 字段类型 长度 主/外键 字段值约束 对应中文名
ProvideID varchar 10 P Not null 供货商编号
ProvideName Varchar 50 Not null 供货商名称
ProvideAddress Varchar 250 供货商地址
ProvidePhone Varchar 25 供货商电话

厂商表(Provide)
字段名 字段类型 长度 主/外键 字段值约束 对应中文名
FactoryID varchar 10 P Not null 厂商编号
FactoryName Varchar 50 Not null 厂商名称
FactoryAddress Varchar 250 厂商地址
FactoryPhone Varchar 25 厂商电话
6、物理设计文档
/*----------创建数据库----------*/
create database SuperMarketdb
on primary
(
name=SuperMarketdb,
filename='C:\Program Files\Microsoft SQL Server\MSSQL\Data\SuperMarketdb.mdf',
size=100MB,
maxsize=200MB,
filegrowth=20MB
)
log on
(
name=SuperMarketlog,
filename='C:\Program Files\Microsoft SQL Server\MSSQL\Data\SuperMarketdb.ldf',
size=60MB,
maxsize=200MB,
filegrowth=20MB
)
go

/*----------创建基本表----------*/
use [SuperMarketdb]
go
/*创建交易表*/
CREATE TABLE Dealing (
DealingID int identity(1,1) Primary key ,
DealingDate datetime NOT NULL ,
DealingPrice money NOT NULL ,
UserName varchar(25) NULL ,
MemberCard varchar(20) NULL
)
GO
/*创建厂商表*/
CREATE TABLE Factory (
FactoryID varchar(10) Primary key ,
FactoryName varchar(50) NOT NULL ,
FactoryAddress varchar(250) NULL ,
FactoryPhone varchar(50) NULL
)
GO
/*创建会员表*/
CREATE TABLE Member (
MemberID varchar(10) Primary key ,
MemberCard varchar(20) NOT NULL ,
TotalCost money NOT NULL ,
RegDate datetime NOT NULL
)
GO
/*创建商品信息表*/
CREATE TABLE MerchInfo (
MerchID int identity(1,1) Primary key ,
MerchName varchar(50) Unique NOT NULL ,
MerchPrice money NOT NULL ,
MerchNum int NOT NULL ,
CautionNum int NOT NULL ,
PlanNum int NOT NULL ,
BarCode varchar(20) Unique NOT NULL ,
SalesProPrice money NULL ,
SalesProDateS datetime NULL ,
SalesProDateE datetime NULL ,
AllowAbate int NOT NULL ,
AllowSale int NOT NULL ,
FactoryID int NOT NULL ,
ProvideID int NOT NULL
)
GO
/*创建供应商表*/
CREATE TABLE Provide (
ProvideID varchar(10) Primary key ,
ProvideName varchar(50) NOT NULL ,
ProvideAddress varchar(250) NULL ,
ProvidePhone varchar(25) NULL
)
GO
/*创建销售表*/
CREATE TABLE Sale (
SaleID int identity(1,1) Primary key ,
MerChID int NOT NULL ,
SaleDate datetime NOT NULL ,
SaleNum int NOT NULL,
SalePrice money NOT NULL
)
GO
/*创建入库表*/
CREATE TABLE Stock (
StockID int identity(1,1) Primary key ,
MerchID int NOT NULL ,
MerchNum int NOT NULL ,
MerchPrice money NULL ,
TotalPrice money NULL ,
PlanDate datetime NULL ,
StockDate datetime NULL,
StockState int NOT NULL
)
GO
/*创建用户表*/
CREATE TABLE User (
UserID varchar(10) Primary key ,
UserName varchar(25) NOT NULL ,
UserPW varchar(50) NOT NULL ,
UserStyle int NOT NULL ,
)
GO

/*----------创建表间约束----------*/
/*商品信息表中厂商编号、供应商编号分别与厂商表、供应商表之间的外键约束*/
ALTER TABLE MerchInfo ADD
CONSTRAINT [FK_MerchInfo_Factory] FOREIGN KEY
(
[FactoryID]
) REFERENCES Factory (
[FactoryID]
),
CONSTRAINT [FK_MerchInfo_Provide] FOREIGN KEY
(
[ProvideID]
) REFERENCES Provide (
[ProvideID]
)
GO
/*销售表中商品编号与商品信息表之间的外键约束*/
ALTER TABLE Sale ADD
CONSTRAINT [FK_Sale_MerchInfo] FOREIGN KEY
(
[MerChID]
) REFERENCES MerchInfo (
[MerchID]
) ON DELETE CASCADE
GO
/*入库表中商品编号与商品信息表之间的外键约束*/
ALTER TABLE Stock ADD
CONSTRAINT [FK_Stock_MerchInfo] FOREIGN KEY
(
[MerchID]
) REFERENCES MerchInfo (
[MerchID]
) ON DELETE CASCADE
GO

/*----------创建索引----------*/
/*在交易表上建立一个以交易编号、交易日期为索引项的非聚集索引*/
CREATE nonclustered INDEX IX_Dealing ON Dealing(DealingID, DealingDate)
GO
/*在商品信息表上建立一个以商品编号为索引项的非聚集索引*/
CREATE nonclustered INDEX IX_MerchInfo ON MerchInfo(MerchID)
GO
/*在销售表上建立一个以销售编号、销售日期为索引项的非聚集索引*/
CREATE nonclustered INDEX IX_Sale ON Sale(SaleID, SaleDate)
GO
/*在入库表上建立一个以入库编号、入库日期、商品编号为索引项的非聚集索引*/
CREATE nonclustered INDEX IX_Stock ON Stock(StockID, StockDate, MerchID)
GO

/*----------创建视图----------*/
/*创建用于查询交易情况的视图*/
CREATE VIEW v_Dealing
AS
SELECT DealingDate as 交易日期,
UserName as 员工名称,
MemberCard as 会员卡号,
DealingPrice as 交易金额
FROM Dealing
GO
/*创建用于查询进货计划的视图*/
CREATE VIEW v_PlanStock
AS
SELECT Stock.StockID as SID,
MerchInfo.MerchName as 商品名称,
MerchInfo.BarCode as 条形码,
Factory.FactoryName as 厂商,
Provide.ProvideName as 供货商,
Stock.MerchNum as 计划进货数量,
Stock.PlanDate as 计划进货日期
FROM Stock,MerchInfo,Provide,Factory
Where Stock.MerchID = MerchInfo.MerchID
and Provide.ProvideID=MerchInfo.ProvideID
and Factory.FactoryID=MerchInfo.FactoryID
and Stock.StockState=0
GO
/*创建用于查询销售明细记录的视图*/
CREATE VIEW v_Sale
AS
SELECT MerchInfo.MerchName as 商品名称,
MerchInfo.BarCode as 条形码,
MerchInfo.MerchPrice as 商品价格,
Sale.SalePrice as 销售价格,
Sale.SaleNum as 销售数量,
Sale.SaleDate as 销售日期
FROM Sale INNER JOIN
MerchInfo ON Sale.MerChID = MerchInfo.MerchID
GO
/*创建用于查询入库情况的视图*/
CREATE VIEW v_Stock
AS
SELECT MerchInfo.MerchName as 商品名称,
MerchInfo.BarCode as 条形码,
Factory.FactoryName as 厂商,
Provide.ProvideName as 供货商,
Stock.MerchPrice as 入库价格,
Stock.MerchNum as 入库数量,
Stock.TotalPrice as 入库总额,
Stock.StockDate as 入库日期
FROM Stock,MerchInfo,Provide,Factory
Where Stock.MerchID = MerchInfo.MerchID
and Provide.ProvideID=MerchInfo.ProvideID
and Factory.FactoryID=MerchInfo.FactoryID
and Stock.StockState=1
GO

7、小结
和传统管理模式相比较,使用本系统,毫无疑问会大大提高超市的运作效率,辅助提高超市的决策水平,管理水平,为降低经营成本, 提高效益,减少差错,节省人力,减少顾客购物时间,增加客流量,提高顾客满意度,增强超市扩张能力, 提供有效的技术保障。
由于开发者能力有限,加上时间仓促,本系统难免会出现一些不足之处,例如:
 本系统只适合小型超市使用,不能适合中大型超市使用;
 超市管理系统涉及范围宽,要解决的问题多,功能复杂,实现困难,但由于限于时间,本系统只能做出其中的一部分功能;
对于以上出现的问题,我们深表歉意,如发现还有其它问题,希望老师批评指正。
请采纳。

㈡ 数据库索引的操作案例

最普通的情况,是为出现在where子句的字段建一个索引。为方便讲述,先建立一个如下的表。
CREATE TABLE mytable(
idserial primary key,
category_id int not null default0,
user_id int not null default0,
adddate int not null default0
);
如果在查询时常用类似以下的语句:
SELECT * FROM mytable WHERE category_id=1;
最直接的应对之道,是为category_id建立一个简单的索引:
CREATE INDEX mytable_categoryid ON mytable (category_id);
OK.如果有不止一个选择条件呢?例如:
SELECT * FROM mytable WHERE category_id=1 AND user_id=2;
第一反应可能是,再给user_id建立一个索引。不好,这不是一个最佳的方法。可以建立多重的索引。
CREATE INDEX mytable_categoryid_userid ON mytable(category_id,user_id);
注意到在命名时的习惯了吗?使用表名_字段1名_字段2名的方式。很快就会知道为什么这样做了。
现在已经为适当的字段建立了索引,不过,还是有点不放心吧,可能会问,数据库会真正用到这些索引吗?测试一下就OK,对于大多数的数据库来说,这是很容易的,只要使用EXPLAIN命令:
EXPLAIN
SELECT * FROM mytable
WHERE category_id=1 AND user_id=2;
This is what Postgres 7.1 returns (exactlyasI expected)
NOTICE:QUERY PLAN:
Index Scan using mytable_categoryid_userid on
mytable(cost=0.00..2.02 rows=1 width=16)
EXPLAIN
以上是postgres的数据,可以看到该数据库在查询的时候使用了一个索引(一个好开始),而且它使用的是创建的第二个索引。看到上面命名的好处了吧,马上知道它使用适当的索引了。
接着,来个稍微复杂一点的,如果有个ORDERBY 子句呢?不管你信不信,大多数的数据库在使用orderby的时候,都将会从索引中受益。
SELECT * FROM mytable
WHERE category_id=1 AND user_id=2
ORDER BY adddate DESC;
很简单,就像为where子句中的字段建立一个索引一样,也为ORDER BY的子句中的字段建立一个索引:
CREATE INDEX mytable_categoryid_userid_adddate ON mytable (category_id,user_id,adddate);
注意:mytable_categoryid_userid_adddate将会被截短为mytable_categoryid_userid_addda
CREATE
EXPLAIN SELECT * FROM mytable
WHERE category_id=1 AND user_id=2
ORDER BY adddate DESC;
NOTICE:QUERY PLAN:
Sort(cost=2.03..2.03 rows=1 width=16)
->Index Scanusing mytable_categoryid_userid_addda
on mytable(cost=0.00..2.02 rows=1 width=16)
EXPLAIN
看看EXPLAIN的输出,数据库多做了一个没有要求的排序,这下知道性能如何受损了吧,看来对于数据库的自身运作是有点过于乐观了,那么,给数据库多一点提示吧。
为了跳过排序这一步,并不需要其它另外的索引,只要将查询语句稍微改一下。这里用的是postgres,将给该数据库一个额外的提示--在ORDER BY语句中,加入where语句中的字段。这只是一个技术上的处理,并不是必须的,因为实际上在另外两个字段上,并不会有任何的排序操作,不过如果加入,postgres将会知道哪些是它应该做的。
EXPLAIN SELECT * FROM mytable
WHERE category_id=1 AND user_id=2
ORDER BY category_id DESC,user_id DESC,adddate DESC;
NOTICE:QUERY PLAN:
Index Scan Backward using
mytable_categoryid_userid_addda on mytable(cost=0.00..2.02 rows=1 width=16)
EXPLAIN
现在使用料想的索引了,而且它还挺聪明,知道可以从索引后面开始读,从而避免了任何的排序。
以上说得细了一点,不过如果数据库非常巨大,并且每日的页面请求达上百万算,想会获益良多的。不过,如果要做更为复杂的查询呢,例如将多张表结合起来查询,特别是where限制字句中的字段是来自不止一个表格时,应该怎样处理呢?通常都尽量避免这种做法,因为这样数据库要将各个表中的东西都结合起来,然后再排除那些不合适的行,搞不好开销会很大。
如果不能避免,应该查看每张要结合起来的表,并且使用以上的策略来建立索引,然后再用EXPLAIN命令验证一下是否使用了料想中的索引。如果是的话,就OK。不是的话,可能要建立临时的表来将他们结合在一起,并且使用适当的索引。
要注意的是,建立太多的索引将会影响更新和插入的速度,因为它需要同样更新每个索引文件。对于一个经常需要更新和插入的表格,就没有必要为一个很少使用的where字句单独建立索引了,对于比较小的表,排序的开销不会很大,也没有必要建立另外的索引。
以上介绍的只是一些十分基本的东西,其实里面的学问也不少,单凭EXPLAIN是不能判定该方法是否就是最优化的,每个数据库都有自己的一些优化器,虽然可能还不太完善,但是它们都会在查询时对比过哪种方式较快,在某些情况下,建立索引的话也未必会快,例如索引放在一个不连续的存储空间时,这会增加读磁盘的负担,因此,哪个是最优,应该通过实际的使用环境来检验。
在刚开始的时候,如果表不大,没有必要作索引,意见是在需要的时候才作索引,也可用一些命令来优化表,例如MySQL可用OPTIMIZETABLE。

㈢ 数据库设计案例分析

加到200分吧,我帮你

㈣ [高等院校校园一卡通系统数据库设计概要]完整的数据库设计案例

摘 要以怀化职业技术学院为对象,结合学习借鉴先进国家院校的数字校园集成的丰富经验,概括了适合本院的“一卡通”数据库的设计。 关键词一卡通;数据库;设计 中图分类号TP3 文献标识码A文章编号1673-9671-(2010)041-0016-01

1数据库系统架构
“校园一卡通”系统的网络结构分为两层。第一层为以数据库服务器为中心的局域网的分布式结构。第二层为以第一层局域网的网络工作站作为控制主机的485通讯网络结构,该层网络控制各个IC卡收费终端。我们将以SQLSERVER2000为平台建立数据库,有利于保证数据安全,有良好的扩展功能,而且可支持多种应用程序语言如VB、VC和Delphi等高级语言。
1.1数据库系统设计
数据库是一种存储数据并对数据进行操作的工具。数据库的作用在于组织和表达信息,简而言之,数据库就是信息的集合。计算机的数据库可以分为两类:非关系数据库(flat-file)和关系数据库(relational)。关系数据库中包含了多个数据表的信息,数据库含有各个不同部分的术语,象记录、域等。
1.2系统功能分析
根据各个功能的子系统模块设置和分析,认为以下的模块设计图(图1)适合我院的基本需求。校园内已经完全具备了基础的计算机硬件条件,许多设备只需做升级或改动就可,随着需求的增加,可以在此基础上扩充接口,十分方便。
1.3系统功能模块的设计
对各项功能进行集中、分块,按照结构化程序设计的要求,分析得到系统功能模块图(图2)。
1.4数据库设计
设计数据库系统时应该首先了解用户(师生)各方面的需求,包括现有的以及将姿胡悄来可能增加的需求。作为“校园一卡通”系统会随着硬件安装场所的变动做改动,需要很大的扩展性。用户的需求具体体现在各种信息的提供、保存、更新和查询,这就要求数据库结构能充分满足各种信息的输入输出。收集基本数据、数据结构以及数据处理的流程,组成一份详尽的数据字典。有了数据库结构、数据项和数据流程,我们就可以进行下面的数据库设计。得到数据项和数据结构以后,就可以设计出用户需求的各种实体,以及它们之间的关系,为后面的逻辑结构设计打下基础。实体是通过相互的作用形成数据的流动。现在需要将现行相关的数据库概念结构化转化为SQL Server2000数据库系统所支持的实际数据模型,也就是数据库的逻辑结构。在上面的实体以及实体之间关系的基础上,形成数据库中的表格以及各个表格之间的关系。
经过前面的需求分析和概念结构设计以后,得到数据库的逻辑结构。现在就可以在SQLserver2000数据库系统中实现该逻辑结构.这就是利用sqlserver2000数据库系统中的sql查询分析器实现的。
2数据库的配置
“校园一卡通”需要众多的数据,如学生信息数据、教师信息数据、消费数据等等。在此我们是以sqlserver2000作为数据库平台的。
2.1客户端程序实现
客户端以高级语言开发,运行于局域网中的各个客户机上,提供用户登录、各据的输入与维护、查询打印、提示等功能。客户端软件做毁以相应的数据组件通过TCP/IP协议访问服务器数据。任何用户只迹渣要拥有给定的权限都可以通过网络操纵和查询服务器数据。
当SQL语句在查询分析器执行后,将自动产生需要的所有表格。有关数据库结构的所有后台工作已经完成。现在将通过相关的信息管理系统中各功能模块的实现,使用高级语言来编写数据库系统的客户端程序。
2.2数据库的配置管理
采用流行的SQLServer2000+Windows2003server的数据库服务器配置,系统数据及逻辑驻留在SQLServer数据库中,SQLServer2000以服务器的形式运行于Windows2003server之上,无用户界面,集中存储与管理系统数据。各客户端可使用windowsXP以上系统建立。SQLServer2000具有很好的安全性,可设定访问权限,数据得导入导出极为方便。我们将使用SQL Server2000管理数据库。这里将以一个管理员(DBA)的身份来阐述数据库管理任务。除了检查服务器配置和备份数据库以外,作为DBA,还要执行很多其他任务。必须保证服务器平稳运行和数据库是快而有效的。
SQL Server2000有很好的安全性模型,这使我们能够定义各种安全措施,包括从限制级数据库的访问权限到限制对表中某一列的访问。在SQL Server2000中可以可以限制客户端用户的基本权限,也可以设置系统管理员的最高权限。
在校园一卡通系统中需要对各个用户设置权限。在数据库中定义的每一个用户都属于Public角色。Public角色除了具有允许用户连接数据库的权限外几乎没有其他权限。
在日常的数据库运行中,我们需要按时的尽心数据库的备份,保存数据的安全和完整性,这些工作SQL Server2000都提供了方便。除此以外,可以利用SQL Server2000的许多工具进行管理,十分便利,详细步骤可以参照多种介绍SQL Server2000的书籍资料。
参考文献
[1]王珊,陈红.数据库系统原理教程[M].北京:清华大学出版社,2000,7.
[2]Rob Hawthorne,袁鹏飞编译.SQL SERVER 2000数据库开发从零开始[M].北京:人民邮电出版社.2001,6.
[3]谭开文,孙京宁.对目前中国IC卡行业现状以及发展的几个看法[J]..计算机系统应用,2003,4:72-74.
本文为全文原貌 未安装PDF浏览器用户请先下载安装 原版全文

㈤ 数据库表结构设计,常见的数据库管理系统

一、数据场景 1、表结构简介 任何工具类的东西都是为了解决某个场景下的问题,比如Redis缓存系统热点数据,ClickHouse解决海量数据的实时分析,MySQL关系型数据库存储结构化数据。数据的存储则需要设计对应的表结构,清楚的表结构,有助于快速开发业务,和理解系统。表结构的设计通常从下面几个方面考虑:业务场景、设计规范、表结构、字段属性、数据管理。
2、用户场景
例如存储用户基础信息数据,通常都会下面几个相关表结构:用户信息表、单点登录表、状态管理表、支付账户表等。
用户信息表
存储用户三要素相关信息:姓名,手机号,身份证,登录密码,邮箱等。
CREATE TABLE `ms_user_center` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID', `user_name` varchar(20) NOT NULL COMMENT '用户名', `real_name` varchar(20) DEFAULT NULL COMMENT '真实姓名', `pass_word` varchar(32) NOT NULL COMMENT '密码', `phone` varchar(20) NOT NULL COMMENT '手机号', `email` varchar(32) DEFAULT NULL COMMENT '邮箱', `head_url` varchar(100) DEFAULT NULL COMMENT '用户头像URL', `card_id` varchar(32) DEFAULT NULL COMMENT '身份证号', `user_sex` int(1) DEFAULT '1' COMMENT '用户性别:0-女,1-男', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_time` datetime DEFAULT NULL COMMENT '更新时间', `state` int(1) DEFAULT '1' COMMENT '是否可用,0-不可用,1-可用', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表'; 单点登录表
用意是在多个业务系统中,用户登录一次就可以访问所有相互信任的业务子系统,是聚合业务平台常用的解决方案。
CREATE TABLE `ms_user_sso` ( `user_id` int(11) NOT NULL COMMENT '用户ID', `sso_id` varchar(32) NOT NULL COMMENT '单点信息编号ID', `sso_code` varchar(32) NOT NULL COMMENT '单点登录码,唯一核心标识', `log_ip` varchar(32) DEFAULT NULL COMMENT '登录IP地址', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_time` datetime DEFAULT NULL COMMENT '更新时间', `state` int(1) DEFAULT '1' COMMENT '是否可用,0-不可用,1-可用', PRIMARY KEY (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户单点登录表'; 状态管理表
系统用户在使用时候可能出现多个状态,例如账户冻结、密码锁定等,把状态聚合到一起,可以更加方便的管理和验证。
CREATE TABLE `ms_user_status` ( `user_id` int(11) NOT NULL COMMENT '用户ID', `account_status` int(1) DEFAULT '1' COMMENT '账户状态:0-冻结,1-未冻结', `real_name_status` int(1) DEFAULT '0' COMMENT '实名认证状态:0-未实名,1-已实名', `pay_pass_status` int(1) DEFAULT '0' COMMENT '支付密码是否设置:0-未设置,1-设置', `wallet_pass_status` int(1) DEFAULT '0' COMMENT '钱包密码是否设置:0-未设置,1-设置', `wallet_status` int(1) DEFAULT '1' COMMENT '钱包是否冻结:0-冻结,1-未冻结', `email_status` int(1) DEFAULT '0' COMMENT '邮箱状态:0-未激活,1-激活', `message_status` int(1) DEFAULT '1' COMMENT '短信提醒开启:0-未开启,1-开启', `letter_status` int(1) DEFAULT '1' COMMENT '站内信提醒开启:0-未开启,1-开启', `emailmsg_status` int(1) DEFAULT '0' COMMENT '邮件提醒开启:0-未开启,1-开启', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_time` datetime DEFAULT NULL COMMENT '更新时间', `state` int(1) DEFAULT '1' COMMENT '是否可用,0-不可用,1-可用', PRIMARY KEY (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户状态表'; 支付账户表
用户交易的核心表,存储用户相关的账户资金信息。
CREATE TABLE `ms_user_wallet` ( `wallet_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '钱包ID', `user_id` int(11) NOT NULL COMMENT '用户ID', `wallet_pwd` varchar(32) DEFAULT NULL COMMENT '钱包密码', `total_account` decimal(20,2) DEFAULT '0.00' COMMENT '账户总额', `usable_money` decimal(20,2) DEFAULT '0.00' COMMENT '可用余额', `freeze_money` decimal(20,2) DEFAULT '0.00' COMMENT '冻结金额', `freeze_time` datetime DEFAULT NULL COMMENT '冻结时间', `thaw_time` datetime DEFAULT NULL COMMENT '解冻时间', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_time` datetime DEFAULT NULL COMMENT '更新时间', `state` int(1) DEFAULT '1' COMMENT '是否可用,0-不可用,1-可用', PRIMARY KEY (`wallet_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户钱包'; 二、设计规范 1、涉及模块
通过上面几个表设计的案例,可以看到表设计关联到数据库的各个方面知识:数据类型,索引,编码,存储引擎等。表设计是一个很大的命题,不过也遵循一个基本规范:三范式。
2、三范式 基础概念
一范式

表的列的具有原子性,不可再分解,即列的信息,不能分解,关系型数据库MySQL、Oracle等自动的满足。

二范式

每个事实的数据记录只会出现一次, 不会冗余, 通常设计一个主键来实现。

三范式

要求一个表中不包含已经存在于其它表的非主键信息,例如部门和员工的信息,员工表包含部门表的主键ID,则可以关联获取相关信息,没必要在员工表保存相关信息。
优缺点对比
范式化设计

范式化结构设计通常更新快,因为冗余数据较少,表结构轻巧,也更好的写入内存中。但是查询起来涉及到关联,代价非常高,非常损耗查询性能。

反范式化设计

所有的数据都在一张表中,避免关联查询,索引的有效性更高,但是数据的冗余性极高。
建议结论
上述的两种设计方式在实际开发中都是不存在的,在实际开发中都是混合使用。比如汇总统计,缓存数据,都会基于反范式化的设计。
三、字段属性
合适的字段类型对于高性能来说非常重要,基本原则如下:简单的类型占用资源更少;在可以正确存储数据的情况下,选最小的数据类型。
1、数据类型选择 整数类型
TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,根据数据类型范围合理选择即可。
实数类型
FLOAT、DOUBLE、DECIMAL,建议资金货币相关类型使用高精度DECIMAL存储,或者把数据成倍扩大为整数,采用BIGINT存储,不过处理相对麻烦。
字符类型
CHAR、VARCHAR,长度不确定建议采用VARCHAR存储,不过VARCHAR类型需要额外开销记录字符串长度。CHAR适合存储短字符,或者定长字符串,例如MD5的加密结构。
时间类型
DATETIME、TIMESTAMP,DATETIME保存大范围的值,精度秒。TIMESTAMP以时间戳的格式,范围相对较小,效率也相对较高,所以通常情况建议使用。

MySQL的字段类型有很多种,可以根据数据特性选择合适的,这里只描述常见的几种类型。
2、基础用法操作 数据类型
修改字段类型
ALTER TABLE ms_user_sso MODIFY state CHAR(1) DEFAULT '0' ; ALTER TABLE ms_user_sso MODIFY state INT(1) DEFAULT '1' COMMENT '状态:0不可用,1可用';
修改名称位置
ALTER TABLE ms_user_sso CHANGE log_ip login_ip VARCHAR(32) AFTER update_time ; 索引使用
索引类型:主键索引,普通索引,唯一索引,组合索引,全文索引。这里演示普通索引的操作。MySQL的核心模块,后续详说。

添加索引
ALTER TABLE ms_user_wallet ADD INDEX user_id_index(user_id) ; CREATE INDEX state_index ON ms_user_wallet(state) ;
查看索引
SHOW INDEX FROM ms_user_wallet;
删除索引
DROP INDEX state_index ON ms_user_wallet ;
修改索引

不具有真正意义上的修改,可以把原有的索引删除之后,再次添加索引。
外键关联
用处:外键关联的作用保证多个数据表的数据一致性和完整性,建表时先有主表,后有从表;删除数据表,需要先删从表,再删主表。复杂场景不建议使用,实际开发中用的也不多。

添加外键
ALTER TABLE ms_user_wallet ADD CONSTRAINT user_id_out_key FOREIGN KEY(user_id) REFERENCES ms_user_center(id) ;
删除外键
ALTER TABLE ms_user_wallet DROP FOREIGN KEY user_id_out_key ; 四、表结构管理 1、查看结构 DESC ms_user_status ; SHOW CREATE TABLE ms_user_status ; 2、字段结构 添加字段 ALTER TABLE ms_user_status ADD `delete_time` datetime DEFAULT NULL COMMENT '删除时间' ; 删除字段 ALTER TABLE ms_user_status DROP COLUMN delete_time ; 3、修改表名 ALTER TABLE ms_user_center RENAME ms_user_info ; 4、存储引擎 存储引擎 SELECT VERSION() ; SHOW ENGINES ;
MySQL 5.6 支持的存储引擎有InnoDB、MyISAM、Memory、Archive、CSV、BLACKHOLE等。一般默认使用InnoDB,支持事务管理。该模块MySQL核心,后续详解。
修改引擎
数据量大的场景下,存储引擎修改是一个难度极大的操作,容易会导致表的特性变动,引起各种后续反应,后续会详说。
ALTER TABLE ms_user_sso ENGINE = MyISAM ; 5、修改编码
表字符集默认使用utf8,通用,无乱码风险,汉字3字节,英文1字节,utf8mb4是utf8的超集,有存储4字节例如表情符号时使用。
查看编码 SHOW VARIABLES LIKE 'character%'; 修改编码 ALTER TABLE ms_user_sso DEFAULT CHARACTER SET utf8mb4; 五、数据管理 1、增删改查
添加数据
INSERT INTO ms_user_sso ( user_id,sso_id,sso_code,create_time,update_time,login_ip,state ) VALUES ( '1','SSO7637267','SSO78631273612', '2019-12-24 11:56:57','2019-12-24 11:57:01','127.0.0.1','1' );
更新数据
UPDATE ms_user_sso SET user_id = '1',sso_id = 'SSO20191224',sso_code = 'SSO20191224', create_time = '2019-11-24 11:56:57',update_time = '2019-11-24 11:57:01', login_ip = '127.0.0.1',state = '1' WHERE user_id = '1';
查询数据

一般情况下都是禁止使用 select* 操作。
SELECT user_id,sso_id,sso_code,create_time,update_time,login_ip,state FROM ms_user_sso WHERE user_id = '1';
删除数据
DELETE FROM ms_user_sso WHERE user_id = '2' ;
不带where条件,就是删除全部数据。原则上不允许该操作,优化篇会详解。TRUNCATE TABLE也是清空表数据,但是占用的资源相对较少。
2、数据安全 不可逆加密
这类加密算法,多用来做数据验证操作,比如常见的密码验证。
SELECT MD5('cicada')='' ; SELECT SHA('cicada')=''; SELECT PASSWORD('smile')='*' ; 可逆加密
安全性要求高的系统,需要做三级等保,对数据的安全性极高,数据在存储时必须加密入库,取出时候需要解密,这些就需要可逆加密。
SELECT DECODE(ENCODE('123456','key_salt'),'key_salt') ; SELECT AES_DECRYPT(AES_ENCRYPT('cicada','salt123'),'salt123');
上述数据安全的管理,也可以基于应用系统的服务(代码)层进行处理,相对专业的流程是从数据生成源头处理,规避数据传递过程泄露,造成不必要的风险。

㈥ 如何进行文章分类和标签的数据库设计

几乎在所有web项目中,都涉及文章分类和标签的设计,应该说这是一个比较常见、典型的案例

站长并不保证我的思路就是最好的,只是分享出来大家一起交流一下,互相促进与提高

我们假设的开发项目是一个博客系统,最核心的部分就是与文章相关的,那么我们今天讨论如何设计博客系统的文章分类和标签

1、首先,分类和标签都是要和具体的文章相关联的,当然也可能一些文章既没有分类也没有标签,这一点是大家在写查询的时候容易疏忽的地方

因为我们的第一感觉就是,在查询文章列表的时候关联分类表,查出所有的文章和分类,对应关系一般是文章表的分类id对应分类表的id,使用where子句进行限定

这里就存在一个问题了,由于使用了where子句,那么只能查询有分类的文章,而没有分类的文章就查询不到了

这时候怎么办?应该使用连接查询,leftjoin,这要没有分类的文章,在文章分类id那一栏会显示null

通常我们只使用leftjoin,而很少使用rightjoin

2、一般,一篇文章最好只对应一个分类,当然如果你想要对应多个分类也可以

但站长并不提倡,文章在多个分类中重复会给人很不专业的感觉,即使有些文章可能确实设计到多方面的内容,那么你应就其中的侧重点来分类

而标签就不一样了,一篇文章可能有多个标签

这就意味着我们无法靠一个sql语句既查出所有文章的分类和标签,又做到查询结果中的文章id不重复

通常我们需要把查询出来的结果直接循环出来,那么这个结果一般是二维数组,第二维的都存储了唯一一篇文章的相关信息

但是,标签和文章是多对一的关系,多个标签对应一篇文章,如果你只用一条sql语句的话,那么我们查询出来的结果,当然也是多行,这不符合我们目标数据的要求

应此,需要在查询完文章和分类之后,在前面结果的基础上再查询一次文章标签,把两次的结果结合起来,存在数组中,这是对应文章列表页面的查询方法

对于具体文章页面,可以分两次查询

好了,还没有给出具体的数据库设计,就先说了如何查询结果,相信大家也看烦了,下面就举例说明:一、文章表:post,字段如下:id【唯一标识】,aid【作者id】,title【标题】,content【内容】,cid【分类id】二、分类表,category,字段如下:id【唯一标识,与post表的cid关联】,name【分类名】三、标签表,tag,字段如下:id【唯一标识】,name【标签名】四、标签与文章对应关系表,tag_,字段如下:id【唯一标识】,postid【文章id,与post表的id关联】,tagid【标签id,tag表的id关联】有朋友可能会问:为什么要单独用一个表来存储文章与标签圆伍睁的对应关系,为什么不可以直接在tag表中增加一个文章id字段呢,比如:tag表:id,postid,name这样做的话,并不是不可以,但是,由于一篇文章对应多个标签,所以name字段的值橘陪会出现很多重复,比如一篇文章,假设文章id为1,有2个标签,php和mysql,那么在tag表会这样存储:id:1,postid:1,name:phpid2,postid:1,name:mysql另一篇文章,假设id为2,有2个标签,也是php和mysql,那么在tag表中它会这样存储:id:3,postid:2,name:phpid4,postid:2,name:mysql大家很快就发现了问题,这样的设计name字段也就是标签的名称在同一张表中可能会大量橘岁重复

但是这样设计的好处是,如果你要查询一个标签下有多少篇文章,只要单独查这个表就可以了,比如要查询含有php标签的文章有多少篇,只需要selectcount(name)??fromtagwherename=’php’,就可以查出来

不好的地方是,如果要查询所有标签的集合,使用这种设计需要使用groupbyname语句来去除重复的行

如果用之前的那种,只需要select*fromtag就可以了

一时之间,好像不太好取舍

这两种设计都会有数据冢余,第一种tag_表中,存在tagid字段的重复;而这两种设计又都有各自的好处

那么我们到底该怎么选择呢?站长也说不好,所以无法为大家下结论

但是站长在研究wordpress数据结构的时候,发现wp是采用的单独建表存储文章与标签对应关系的方式

㈦ 数据库具体应用的实例有哪些

数据库的应用领域

1、多媒体数据库: 这类数据库主要存储与多媒体相关的数据,如声音、图像和视频等数据。多媒体数据最大的特点是数据连续,而且数据量比较大,存储需要的空间较大。

2、移动数据库: 该类数据库是在移动计算机系统上发展起来的,如笔记本电脑、掌上计算机等。该数据库最大的特点是通过无线数字通信网络传输的。移动数据库可以随时随地地获取和访问数据,为一些商务应用和一些紧急情况带来了很大的便利。

3、空间数据库: 这类数据库目前发展比较迅速。它主要包括地理信息数据库(又称为地理信息系统,即GIS)和计算机辅助设计(CAD)数据库。其中地理信息数据库一般存储与地图相关的信息数据;计算机辅助设计数据库一般存储设计信息的空间数据库,如机械、集成电路以及电子设备设计图等。

4、信息检索系统: 信息检索就是根据用户输入的信息,从数据库中查找相关的文档或信息,并把查找的信息反馈给用户。信息检索领域和数据库是同步发展的,它是一种典型的联机文档管理系统或者联机图书目录。

5、分布式信息检索: 这类数据库是随着Internet的发展而产生的数据库。它一般用于因特网及远距离计算机网络系统中。特别是随着电子商务的发展,这类数据库发展更加迅猛。

许多网络用户(如个人、公司或企业等)在自己的计算机中存储信息,同时希望通过网络使用发送电子邮件、文件传输、远程登录方式和别人共享这些信息。分布式信息检索满足了这一要求。

6、专家决策系统: 专家决策系统也是数据库应用的一部分。由于越来越多的数据可以联机获取,特别是企业通过这些数据可以对企业的发展作出更好的决策,以使企业更好地运行。由于人工智能的发展,使得专家决策系统的应用更加广泛。

(7)数据库表设计案例扩展阅读

对数据库系统的基本要求是:

①能够保证数据的独立性。数据和程序相互独立有利于加快软件开发速度,节省开发费用。

②冗余数据少,数据共享程度高。

③系统的用户接口简单,用户容易掌握,使用方便。

④能够确保系统运行可靠,出现故障时能迅速排除;能够保护数据不受非受权者访问或破坏;能够防止错误数据的产生,一旦产生也能及时发现。

⑤有重新组织数据的能力,能改变数据的存储结构或数据存储位置,以适应用户操作特性的变化,改善由于频繁插入、删除操作造成的数据组织零乱和时空性能变坏的状况。

⑥具有可修改性和可扩充性。

⑦能够充分描述数据间的内在联系。

㈧ 有没有利用python开发数据库的案例

在Windows平台上安装mysql模块用于Python开发

用python连接mysql的时候,需要用的安装版本,源码版本容易有错误提示。下边是打包了32与64版本。
MySQL-python-1.2.3.win32-py2.7.exe
MySQL-python-1.2.3.win-amd64-py2.7.exe
实例 1、取得 MYSQL 的版本

# -*- coding: UTF-8 -*-
#安装 MYSQL DB for python
import MySQLdb as mdb
con = None
try:
#连接 mysql 的方法: connect('ip','user','password','dbname')
con = mdb.connect('localhost', 'root','root', 'test');

#所有的查询,都在连接 con 的一个模块 cursor 上面运行的
cur = con.cursor()

#执行一个查询
cur.execute("SELECT VERSION()")
#取得上个查询的结果,是单个结果

data = cur.fetchone()
print "Database version : %s " % data
finally:
if con:
#无论如何,连接记得关闭
con.close()

实例 2、创建一个表并且插入数据

import MySQLdb as mdb
import sys

#将 con 设定为全局连接
con = mdb.connect('localhost', 'root', 'root', 'test');
with con:

#获取连接的 cursor,只有获取了 cursor,我们才能进行各种操作
cur = con.cursor()

#创建一个数据表 writers(id,name)
cur.execute("CREATE TABLE IF NOT EXISTS
Writers(Id INT PRIMARY KEY AUTO_INCREMENT, Name VARCHAR(25))")

#以下插入了 5 条数据
cur.execute("INSERT INTO Writers(Name) VALUES('Jack London')")
cur.execute("INSERT INTO Writers(Name) VALUES('Honore de Balzac')")
cur.execute("INSERT INTO Writers(Name) VALUES('Lion Feuchtwanger')")
cur.execute("INSERT INTO Writers(Name) VALUES('Emile Zola')")
cur.execute("INSERT INTO Writers(Name) VALUES('Truman Capote')")

实例 3、 python 使用 slect 获取 mysql 的数据并遍历

import MySQLdb as mdb
import sys

#连接 mysql,获取连接的对象
con = mdb.connect('localhost', 'root', 'root', 'test');
with con:

#仍然是,第一步要获取连接的 cursor 对象,用于执行查询
cur = con.cursor()

#类似于其他语言的 query 函数, execute 是 python 中的执行查询函数
cur.execute("SELECT * FROM Writers")

#使用 fetchall 函数,将结果集(多维元组)存入 rows 里面
rows = cur.fetchall()

#依次遍历结果集,发现每个元素,就是表中的一条记录,用一个元组来显示
for row in rows:
print row

运行结果:

(1L, ‘Jack London')
(2L, ‘Honore de Balzac')
(3L, ‘Lion Feuchtwanger')
(4L, ‘Emile Zola')
(5L, ‘Truman Capote')
上面的代码,用来将所有的结果取出,不过打印的时候是每行一个元祖打印,现在我们使用方法,取出其中的单个数据:

import MySQLdb as mdb
import sys

#获取 mysql 的链接对象
con = mdb.connect('localhost', 'root', 'root', 'test');
with con:
#获取执行查询的对象
cur = con.cursor()
#执行那个查询,这里用的是 select 语句
cur.execute("SELECT * FROM Writers")
#使用 cur.rowcount 获取结果集的条数
numrows = int(cur.rowcount)
#循环 numrows 次,每次取出一行数据
for i in range(numrows):
#每次取出一行,放到 row 中,这是一个元组(id,name)
row = cur.fetchone()
#直接输出两个元素
print row[0], row[1]

运行结果:

1 Jack London
2 Honore de Balzac
3 Lion Feuchtwanger
4 Emile Zola
5 Truman Capote
实例 4、使用字典 cursor 取得结果集(可以使用表字段名字访问值)

import MySQLdb as mdb
import sys
#获得 mysql 查询的链接对象
con = mdb.connect('localhost', 'root', 'root', 'test')
with con:
#获取连接上的字典 cursor,注意获取的方法,
#每一个 cursor 其实都是 cursor 的子类
cur = con.cursor(mdb.cursors.DictCursor)
#执行语句不变
cur.execute("SELECT * FROM Writers")
#获取数据方法不变
rows = cur.fetchall()
#遍历数据也不变(比上一个更直接一点)
for row in rows:
#这里,可以使用键值对的方法,由键名字来获取数据
print "%s %s" % (row["Id"], row["Name"])

实例 5、获取单个表的字段名和信息的方法

import MySQLdb as mdb
import sys
#获取数据库的链接对象
con = mdb.connect('localhost', 'root', 'root', 'test')
with con:
#获取普通的查询 cursor
cur = con.cursor()
cur.execute("SELECT * FROM Writers")
rows = cur.fetchall()
#获取连接对象的描述信息
desc = cur.description
print 'cur.description:',desc
#打印表头,就是字段名字
print "%s %3s" % (desc[0][0], desc[1][0])
for row in rows:
#打印结果
print "%2s %3s" % row

运行结果:

cur.description: ((‘Id', 3, 1, 11, 11, 0, 0), (‘Name', 253, 17, 25, 25, 0, 1))
Id Name
1 Jack London
2 Honore de Balzac
3 Lion Feuchtwanger
4 Emile Zola
5 Truman Capote
实例 6、使用 Prepared statements 执行查询(更安全方便)

import MySQLdb as mdb
import sys

con = mdb.connect('localhost', 'root', 'root', 'test')
with con:
cur = con.cursor()
#我们看到,这里可以通过写一个可以组装的 sql 语句来进行
cur.execute("UPDATE Writers SET Name = %s WHERE Id = %s",
("Guy de Maupasant", "4"))
#使用 cur.rowcount 获取影响了多少行
print "Number of rows updated: %d" % cur.rowcount

结果:
Number of rows updated: 1

实例 7、把图片用二进制存入 MYSQL

有人喜欢把图片存入 MYSQL(这种做法貌似很少吧),我看大部分的程序,图片都是存放在服务器上的文件,数据库中存的只是图片的地址而已,不过 MYSQL 是支持把图片存入数据库的,也相应的有一个专门的字段 BLOB (Binary Large Object),即较大的二进制对象字段,请看如下程序,注意测试图片自己随便找一个,地址要正确:
首先,在数据库中创建一个表,用于存放图片:

复制代码代码如下:

CREATE TABLE Images(Id INT PRIMARY KEY AUTO_INCREMENT, Data MEDIUMBLOB);

然后运行如下 PYTHON 代码进行:

import MySQLdb as mdb
import sys

try:
#用读文件模式打开图片
fin = open("../web.jpg")
#将文本读入 img 对象中
img = fin.read()
#关闭文件
fin.close()
except IOError, e:
#如果出错,打印错误信息
print "Error %d: %s" % (e.args[0],e.args[1])
sys.exit(1)
try:
#链接 mysql,获取对象
conn = mdb.connect(host='localhost',user='root',passwd='root',
db='test')
#获取执行 cursor
cursor = conn.cursor()
#直接将数据作为字符串,插入数据库
cursor.execute("INSERT INTO Images SET Data='%s'" %
mdb.escape_string(img))
#提交数据
conn.commit()
#提交之后,再关闭 cursor 和链接
cursor.close()
conn.close()
except mdb.Error, e:
#若出现异常,打印信息
print "Error %d: %s" % (e.args[0],e.args[1])
sys.exit(1)

实例 8、从数据库中把图片读出来

import MySQLdb as mdb
import sys

try:
#连接 mysql,获取连接的对象
conn = mdb.connect('localhost', 'root', 'root', 'test');
cursor = conn.cursor()
#执行查询该图片字段的 SQL
cursor.execute("SELECT Data FROM Images LIMIT 1")
#使用二进制写文件的方法,打开一个图片文件,若不存在则自动创建
fout = open('image.png','wb')
#直接将数据如文件
fout.write(cursor.fetchone()[0])
#关闭写入的文件
fout.close()
#释放查询数据的资源
cursor.close()
conn.close()
except IOError, e:
#捕获 IO 的异常 ,主要是文件写入会发生错误
print "Error %d: %s" % (e.args[0],e.args[1])
sys.exit(1)

实例 9、使用 Transaction 即事务(手动提交,自动回滚)

import MySQLdb as mdb
import sys

try:
#连接 mysql,获取连接的对象
conn = mdb.connect('localhost', 'root', 'root', 'test');
cursor = conn.cursor()
#如果某个数据库支持事务,会自动开启
#这里用的是 MYSQL,所以会自动开启事务(若是 MYISM 引擎则不会)
cursor.execute("UPDATE Writers SET Name = %s WHERE Id = %s",
("Leo Tolstoy", "1"))
cursor.execute("UPDATE Writers SET Name = %s WHERE Id = %s",
("Boris Pasternak", "2"))
cursor.execute("UPDATE Writer SET Name = %s WHERE Id = %s",
("Leonid Leonov", "3"))
#事务的特性 1、原子性的手动提交
conn.commit()
cursor.close()
conn.close()
except mdb.Error, e:
#如果出现了错误,那么可以回滚,就是上面的三条语句要么执行,要么都不执行
conn.rollback()
print "Error %d: %s" % (e.args[0],e.args[1])

结果:
1、因为不存在 writer 表( SQL 第三条语句),所以出现错误:Error 1146: Table ‘test.writer' doesn't exist
2、出现错误,出发异常处理, 3 条语句的前两条会自动变成了没有执行,结果不变
3、如果本代码放到一个 MyISAM 引擎表,前两句会执行,第三句不会;如果是 INNDB 引擎,则都不会执行。

㈨ 谁知道数据库优化设计方案有哪些

本文首先讨论了基于第三范式的数据库表的基本设计,着重论述了建立主键和索引的策略和方案,然后从数据库表的扩展设计和库表对象的放置等角度概述了数据库管理系统的优化方案。
关键词: 优化(Optimizing) 第三范式(3NF) 冗余数据(Rendant Data) 索引(Index) 数据分割(Data Partitioning) 对象放置(Object Placement)
1 引言
数据库优化的目标无非是避免磁盘I/O瓶颈、减少CPU利用率和减少资源竞争。为了便于读者阅读和理解,笔者参阅了Sybase、Informix和Oracle等大型数据库系统参考资料,基于多年的工程实践经验,从基本表设计、扩展设计和数据库表对象放置等角度进行讨论,着重讨论了如何避免磁盘I/O瓶颈和减少资源竞争,相信读者会一目了然。
2 基于第三范式的基本表设计
在基于表驱动的信息管理系统(MIS)中,基本表的设计规范是第三范式(3NF)。第三范式的基本特征是非主键属性只依赖于主键属性。基于第三范式的数据库表设计具有很多优点:一是消除了冗余数据,节省了磁盘存储空间;二是有良好的数据完整性限制,即基于主外键的参照完整限制和基于主键的实体完整性限制,这使得数据容易维护,也容易移植和更新;三是数据的可逆性好,在做连接(Join)查询或者合并表时不遗漏、也不重复;四是因消除了冗余数据(冗余列),在查询(Select)时每个数据页存的数据行就多,这样就有效地减少了逻辑I/O,每个Cash存的页面就多,也减少物理I/O;五是对大多数事务(Transaction)而言,运行性能好;六是物理设计(Physical Design)的机动性较大,能满足日益增长的用户需求。
在基本表设计中,表的主键、外键、索引设计占有非常重要的地位,但系统设计人员往往只注重于满足用户要求,而没有从系统优化的高度来认识和重视它们。实际上,它们与系统的运行性能密切相关。现在从系统数据库优化角度讨论这些基本概念及其重要意义:
(1)主键(Primary Key):主键被用于复杂的SQL语句时,频繁地在数据访问中被用到。一个表只有一个主键。主键应该有固定值(不能为Null或缺省值,要有相对稳定性),不含代码信息,易访问。把常用(众所周知)的列作为主键才有意义。短主键最佳(小于25bytes),主键的长短影响索引的大小,索引的大小影响索引页的大小,从而影响磁盘I/O。主键分为自然主键和人为主键。自然主键由实体的属性构成,自然主键可以是复合性的,在形成复合主键时,主键列不能太多,复合主键使得Join*作复杂化、也增加了外键表的大小。人为主键是,在没有合适的自然属性键、或自然属性复杂或灵敏度高时,人为形成的。人为主键一般是整型值(满足最小化要求),没有实际意义,也略微增加了表的大小;但减少了把它作为外键的表的大小。
(2)外键(Foreign Key):外键的作用是建立关系型数据库中表之间的关系(参照完整性),主键只能从独立的实体迁移到非独立的实体,成为后者的一个属性,被称为外键。
(3)索引(Index):利用索引优化系统性能是显而易见的,对所有常用于查询中的Where子句的列和所有用于排序的列创建索引,可以避免整表扫描或访问,在不改变表的物理结构的情况下,直接访问特定的数据列,这样减少数据存取时间;利用索引可以优化或排除耗时的分类*作;把数据分散到不同的页面上,就分散了插入的数据;主键自动建立了唯一索引,因此唯一索引也能确保数据的唯一性(即实体完整性);索引码越小,定位就越直接;新建的索引效能最好,因此定期更新索引非常必要。索引也有代价:有空间开销,建立它也要花费时间,在进行Insert、Delete和Update*作时,也有维护代价。索引有两种:聚族索引和非聚族索引。一个表只能有一个聚族索引,可有多个非聚族索引。使用聚族索引查询数据要比使用非聚族索引快。在建索引前,应利用数据库系统函数估算索引的大小。
① 聚族索引(Clustered Index):聚族索引的数据页按物理有序储存,占用空间小。选择策略是,被用于Where子句的列:包括范围查询、模糊查询或高度重复的列(连续磁盘扫描);被用于连接Join*作的列;被用于Order by和Group by子句的列。聚族索引不利于插入*作,另外没有必要用主键建聚族索引。
② 非聚族索引(Nonclustered Index):与聚族索引相比,占用空间大,而且效率低。选择策略是,被用于Where子句的列:包括范围查询、模糊查询(在没有聚族索引时)、主键或外键列、点(指针类)或小范围(返回的结果域小于整表数据的20%)查询;被用于连接Join*作的列、主键列(范围查询);被用于Order by和Group by子句的列;需要被覆盖的列。对只读表建多个非聚族索引有利。索引也有其弊端,一是创建索引要耗费时间,二是索引要占有大量磁盘空间,三是增加了维护代价(在修改带索引的数据列时索引会减缓修改速度)。那么,在哪种情况下不建索引呢?对于小表(数据小于5页)、小到中表(不直接访问单行数据或结果集不用排序)、单值域(返回值密集)、索引列值太长(大于20bitys)、容易变化的列、高度重复的列、Null值列,对没有被用于Where子语句和Join查询的列都不能建索引。另外,对主要用于数据录入的,尽可能少建索引。当然,也要防止建立无效索引,当Where语句中多于5个条件时,维护索引的开销大于索引的效益,这时,建立临时表存储有关数据更有效。
批量导入数据时的注意事项:在实际应用中,大批量的计算(如电信话单计费)用C语言程序做,这种基于主外键关系数据计算而得的批量数据(文本文件),可利用系统的自身功能函数(如Sybase的BCP命令)快速批量导入,在导入数据库表时,可先删除相应库表的索引,这有利于加快导入速度,减少导入时间。在导入后再重建索引以便优化查询。
(4)锁:锁是并行处理的重要机制,能保持数据并发的一致性,即按事务进行处理;系统利用锁,保证数据完整性。因此,我们避免不了死锁,但在设计时可以充分考虑如何避免长事务,减少排它锁时间,减少在事务中与用户的交互,杜绝让用户控制事务的长短;要避免批量数据同时执行,尤其是耗时并用到相同的数据表。锁的征用:一个表同时只能有一个排它锁,一个用户用时,其它用户在等待。若用户数增加,则Server的性能下降,出现“假死”现象。如何避免死锁呢?从页级锁到行级锁,减少了锁征用;给小表增加无效记录,从页级锁到行级锁没有影响,若在同一页内竞争有影响,可选择合适的聚族索引把数据分配到不同的页面;创建冗余表;保持事务简短;同一批处理应该没有网络交互。
(5)查询优化规则:在访问数据库表的数据(Access Data)时,要尽可能避免排序(Sort)、连接(Join)和相关子查询*作。经验告诉我们,在优化查询时,必须做到:
① 尽可能少的行;
② 避免排序或为尽可能少的行排序,若要做大量数据排序,最好将相关数据放在临时表中*作;用简单的键(列)排序,如整型或短字符串排序;
③ 避免表内的相关子查询;
④ 避免在Where子句中使用复杂的表达式或非起始的子字符串、用长字符串连接;
⑤ 在Where子句中多使用“与”(And)连接,少使用“或”(Or)连接;
⑥ 利用临时数据库。在查询多表、有多个连接、查询复杂、数据要过滤时,可以建临时表(索引)以减少I/O。但缺点是增加了空间开销。
除非每个列都有索引支持,否则在有连接的查询时分别找出两个动态索引,放在工作表中重新排序。
3 基本表扩展设计
基于第三范式设计的库表虽然有其优越性(见本文第一部分),然而在实际应用中有时不利于系统运行性能的优化:如需要部分数据时而要扫描整表,许多过程同时竞争同一数据,反复用相同行计算相同的结果,过程从多表获取数据时引发大量的连接*作,当数据来源于多表时的连接*作;这都消耗了磁盘I/O和CPU时间。
尤其在遇到下列情形时,我们要对基本表进行扩展设计:许多过程要频繁访问一个表、子集数据访问、重复计算和冗余数据,有时用户要求一些过程优先或低的响应时间。
如何避免这些不利因素呢?根据访问的频繁程度对相关表进行分割处理、存储冗余数据、存储衍生列、合并相关表处理,这些都是克服这些不利因素和优化系统运行的有效途径。
3.1 分割表或储存冗余数据
分割表分为水平分割表和垂直分割表两种。分割表增加了维护数据完整性的代价。
水平分割表:一种是当多个过程频繁访问数据表的不同行时,水平分割表,并消除新表中的冗余数据列;若个别过程要访问整个数据,则要用连接*作,这也无妨分割表;典型案例是电信话单按月分割存放。另一种是当主要过程要重复访问部分行时,最好将被重复访问的这些行单独形成子集表(冗余储存),这在不考虑磁盘空间开销时显得十分重要;但在分割表以后,增加了维护难度,要用触发器立即更新、或存储过程或应用代码批量更新,这也会增加额外的磁盘I/O开销。
垂直分割表(不破坏第三范式),一种是当多个过程频繁访问表的不同列时,可将表垂直分成几个表,减少磁盘I/O(每行的数据列少,每页存的数据行就多,相应占用的页就少),更新时不必考虑锁,没有冗余数据。缺点是要在插入或删除数据时要考虑数据的完整性,用存储过程维护。另一种是当主要过程反复访问部分列时,最好将这部分被频繁访问的列数据单独存为一个子集表(冗余储存),这在不考虑磁盘空间开销时显得十分重要;但这增加了重叠列的维护难度,要用触发器立即更新、或存储过程或应用代码批量更新,这也会增加额外的磁盘I/O开销。垂直分割表可以达到最大化利用Cache的目的。
总之,为主要过程分割表的方法适用于:各个过程需要表的不联结的子集,各个过程需要表的子集,访问频率高的主要过程不需要整表。在主要的、频繁访问的主表需要表的子集而其它主要频繁访问的过程需要整表时则产生冗余子集表。
注意,在分割表以后,要考虑重新建立索引。
3.2 存储衍生数据
对一些要做大量重复性计算的过程而言,若重复计算过程得到的结果相同(源列数据稳定,因此计算结果也不变),或计算牵扯多行数据需额外的磁盘I/O开销,或计算复杂需要大量的CPU时间,就考虑存储计算结果(冗余储存)。现予以分类说明:
若在一行内重复计算,就在表内增加列存储结果。但若参与计算的列被更新时,必须要用触发器更新这个新列。
若对表按类进行重复计算,就增加新表(一般而言,存放类和结果两列就可以了)存储相关结果。但若参与计算的列被更新时,就必须要用触发器立即更新、或存储过程或应用代码批量更新这个新表。
若对多行进行重复性计算(如排名次),就在表内增加列存储结果。但若参与计算的列被更新时,必须要用触发器或存储过程更新这个新列。
总之,存储冗余数据有利于加快访问速度;但违反了第三范式,这会增加维护数据完整性的代价,必须用触发器立即更新、或存储过程或应用代码批量更新,以维护数据的完整性。
3.3 消除昂贵结合
对于频繁同时访问多表的一些主要过程,考虑在主表内存储冗余数据,即存储冗余列或衍生列(它不依赖于主键),但破坏了第三范式,也增加了维护难度。在源表的相关列发生变化时,必须要用触发器或存储过程更新这个冗余列。当主要过程总同时访问两个表时可以合并表,这样可以减少磁盘I/O*作,但破坏了第三范式,也增加了维护难度。对父子表和1:1关系表合并方法不同:合并父子表后,产生冗余表;合并1:1关系表后,在表内产生冗余数据。
4 数据库对象的放置策略
数据库对象的放置策略是均匀地把数据分布在系统的磁盘中,平衡I/O访问,避免I/O瓶颈。
⑴ 访问分散到不同的磁盘,即使用户数据尽可能跨越多个设备,多个I/O运转,避免I/O竞争,克服访问瓶颈;分别放置随机访问和连续访问数据。
⑵ 分离系统数据库I/O和应用数据库I/O。把系统审计表和临时库表放在不忙的磁盘上。
⑶ 把事务日志放在单独的磁盘上,减少磁盘I/O开销,这还有利于在障碍后恢复,提高了系统的安全性。
⑷ 把频繁访问的“活性”表放在不同的磁盘上;把频繁用的表、频繁做Join*作的表分别放在单独的磁盘上,甚至把把频繁访问的表的字段放在不同的磁盘上,把访问分散到不同的磁盘上,避免I/O争夺;
⑸ 利用段分离频繁访问的表及其索引(非聚族的)、分离文本和图像数据。段的目的是平衡I/O,避免瓶颈,增加吞吐量,实现并行扫描,提高并发度,最大化磁盘的吞吐量。利用逻辑段功能,分别放置“活性”表及其非聚族索引以平衡I/O。当然最好利用系统的默认段。另外,利用段可以使备份和恢复数据更加灵活,使系统授权更加灵活。

㈩ 数据库作业,高手解答。。。

第一个表桐世伏: create table goods(goodsId char(8) primary key, goodName varchar2(30), unitprice number(10,2) check(unitprice>0), category varchar2(8), provider varchar2(30)); 第二个表: create table customer(customerId char(2) primary key, name varchar2(50) not null, address varchar2(50), email varchar2(50) unique, sex char(2) default '男局携' check(sex in('男'返卜,'女')), cardId char(18)); 第三个表: create table purchase(customerId char(8) references customer(customerId), goodsId char(8) references goods(goodsId), nums number(5) check(nums between 1 and 30));