1、数据库
定义:数据库只是一个信息的集合。关系数据库是一个信息的集合,这种数据库中的数据以某种方式和另一个数据关联。
DBMS(商业数据库管理系统):简化了与构建和使用关系数据库关联的任务。
(1)数据库的结构
关系数据库:通常是两个或两个以上数据库表的集合。
数据库表、字段和记录
数据库表:按行和列排列的数据库的结构。
数据库表中的每一行称为一个记录。
数据库表中的每一列称为一个字段。(类似于数据库的属性,每个字段用来存储特定数据项的值)
数据库表可能有0行或多行。如果表有0行,就说这个数据库表是空,不包含有用信息。数据库表一般至少有两个或多个字段。
数据规范化
数据规范化:从数据库中删除重复或者冗余数据的过程。
主键
表中存放独有值的字段称之为主键字段。
如果某个记录的一个字段中有一个独有值,我们就可以说表中每个记录都是独有的(因为有主键字段)。可以在不同的表中用这个主键字段引用另一个表中的信息。(这就是把这样的数据库成为关系数据库的原因:存储在数据库中的数据的表之间存在某种关系。)
数据库的关系:一对一,多对多,一对多等等。
无穷号:数据库表关系的讨论中的术语“多”的标准表示法。
外键
作为表中外键的字段必须和另一个表建立某种关系。
2、使用自己的数据库
商业数据库多种类型:Microsoft:Access,SQL Server。IBM:DB2,MySQL,Oracle。
本文以Access为基础介绍。
ADO.NET
C#与数据库交互方式的重要工具:ADO.NET。
ADO.NET:由两种基本元素构成:数据提供程序元素,数据集元素。
(1)数据提供程序
有几个类共同作为ADO.NET的数据提供程序。
OLE DB:外部数据源与Microsoft交互的桥梁。这种方法是一种双赢的方法。
如果使用其他数据库,可以查找器提供程序信息,绕过OLEDB提供程序,这样可以提供更好的性能。
(2)OLE连接对象
为了与数据库通信,必须先建立与数据库的连接。
要通过OLE DB来使用数据库,所以用OleDbConnection类提供我们需要与数据库通信的连通性。一旦实例化一个OleDbConnection对象,就用该对象通过OleDbConnection对象执行对数据库的命令。(执行大部分数据库操作的启动点)
I.OLE Command对象
OleDbCommand对象用来处理结构化查询语言(SQL)命令。
SQL是使用关系数据库的标准语言。
II.数据定义语言(DDL)
SQL包括一个语言子集,成为数据定义语言(DDL)。初次创建数据库时,使用DDL命令建立第一次创建数据库结构。
(用DDL创建一个数据库,向数据库中添加表,并且向数据库表中添加字段。定义了结构之后,用其他DDL命令在数据库中添加编辑,删除行。其他大部分SQL操作符用来操作已经位于数据库中的数据。)
III.OLE reader 对象
当用OleDbCommand对象从数据库中取得数据后,用一个OleDbReader对象来遍历SQL命令产生的数据,使得reader对象的输出最终产生所要浏览的数据。
(3)数据集
数据集类:提供了操作在数据库中所含数据的方式。数据集对象是泛型,因为他们不随数据库而变化,所以他们的使用不会因为底层数据库的变化而变化。
每个数据集可以与一个有列和行的DataTable对象相关联。从Datatable对象中可以构造一个DataView对象。DataView对象通常表示由SQL命令过滤的数据集。
3、使用SQL
目的:为了将其作为创建、管理和维护关系数据库的通用数据库语言。
(1)SELECT语句
可以用来从数据库中检索数据的特定子集,大多数查询都用SELECT语句进行初始化。
语法为:
SELECT fieldList FROM tablename
fieldList是一个希望从数据库中检索的字段列表。用逗号分隔。
tablename 存放信息的表
例子:
SELECT firstName,lastName FROM Friends
SQL关键字的惯例是大写字母。
SELECT * FROM tablename
该查询返回一个数据集,其中包含Friend表中每一行的所有字段数据……那是问题所在:该数据集包含数据库中的每一个人。
(2)WHERE语句
可以用WHERE谓词来过滤从数据库返回的数据集
SELECT firstName,lastName FROM Friends WHERE Zip=80120
将会返回一个数据集,其中包含住在邮政编码为80120的地区的人的所有姓名。
也可以像WHERE谓词应用基本条件运算符。
SELECT firstName,lastName FROM Friends WHERE Zip>46214 AND Zip<46254
它允许生成拥有某种限制性的数据集。
(3)ORDER BY语句
ORDER BY语句允许将数据集重新组织成升序或降序。
SELECT * FROM Friends WHERE Zip=46214 ORDER BY lastName
将返回按照lastName字段的升序排列的数据集。如果想要按照降序排列的同一个列表。应使用:
SELECT * FROM Friends WHERE Zip=46214 ORDER BY lastName DESC
关键字DESC,变成降序排列。
(4)聚合
有些数据库操作是如此常见,SQL提供了称为聚合的方法来对数据库执行特定的计算。至少大多数数据库都支持如下列出的聚合:
AVG:返回选中字段的数值平均值。
SELECT AVG(Age)FROM Friend
COUNT:返回在选中字段中发现的项数。
SELECT COUNT(lastName) FROM Friend WHERE Status=1
指出表中有多少活动的人。
MIN:查找字段中的最小值。
SELECT MIN(Age) FROM Friend
MAX:查找字段中的最大值。
SELECET MAX(Age) FROM Friend
SUM:返回字段中值的和。
SELECT SUN(Status)FROM Friend
返回表中活动的人数。
(5)示例程序:编写自己的数据库
创建一个MDI程序。创建Access数据库,向该数据库添加表,以及添加、编辑和删除行数据。
OLE DB功能没有提供创建新数据库的能力。这里使用ADOX(标准ADO的一个扩展)来给我们创建新数据库的能力。
Visual Studio——>Project->Add Reference命令,选择COM选项卡,选择Microsoft ADO Ext.2.8 for DDL and Security reference选项。添加引用之后。向clsDB类提供CreateNewDB()方法。
public int CreateNewDB(string name) {
int index;
string newDB;
try
{
if (name.Length == 0 && dbName.Length == 0)
{
return 0;
}
index = name.LastIndexOf(".");
if (index == -1)
{
dbName += ".mdb";
name = dbName;
}
combineName = Path.Combine(pathName, name);
ADOX.CatalogClass myCat = new ADOX.CatalogClass();
newDB = CONNECTSTRING + combineName + ";" + CONNECTSTRINGPART2;
myCat.Create(newDB);
myCat = null;
}
catch(Exception ex)
{
#if DEDBUG
Mssage.Show("Error: "+ex.Message);
#elseif
return 0;
}
return 1;
}
上述代码需要传递到方法中的数据库的新名称。该方法通过一个菜单项从frmMain中调用的
以上代码将路径名与数据库名称结合到一起了。文件路径默认是指可执行程序所位于的路径。
预处理程序触发MessageBox方法的代码。如果没有发生错误,那么选中的目录中就会出现一个扩展名为.mdb的空数据库。
privare void mnuNew_Click(Object sender,EventArgs e)
{
frmCreateDB myNewDB=new frmCreateDB(dbName);
myNewDB.ShowDialog();
}
在子窗体中,输入新数据库名称,点击Create New DB之后,执行
clsDB myDB=new clsDB(txtDBName.Text);
flag=myDB.CreateNewDB(txtDBName.Text);
(6)创建新表
关于ListView控件中删除出错项的一种方式:
private void lstFiledsToAdd_DoubleClick(object sender,EventArgs e)
{
ListView.SelectedIndexCollection indexes=lstFieldsToAdd.SelecteedIndices;
foreach(int index in indexes)
{
lstFieldsToAdd.Items[index].Remove();
}
}
双击listView当中的出错项就可以对出错项进行删除。
Add New Table按钮:
private voidbtnWrite_Click(object sender,EventArgs e)
{
int i,j;
int flag;
string sqlCommand;
string buff;
string temp;
try
{
clsDB myDB=new clsDB(dbName);
sqlCommand="CREATE TABLE "+txtTableName.Text+"(ID COUNTER, ";
for(i=0;i<lstFieldsToAdd.Items.Count;i++)
{
temp=" ";
for(j=0;j<lstFieldsToAdd.Items[i].SubItems.Count;j++)
{
buff=lstFieldToAdd.Items[i].SubItems[j].Text;
switch(j)
{
case 0://field name
sqlCommand+=buff+"";
break;
case 1://The field length
temp=buff;
break;
case 2:
if(buff.Equals("TEXT")==true)
{
sqlCommand+="TEXT("+TEMP+"),";
}
else
{
sqlCommand+=buff+",";
}
break;
}
}
}
i=sqlCommand.LastIndexOf(",");
sqlCommand=sqlCommand.SubString(0,sqlCommand.Length-2);
sqlCommand+=")";
flag=myDB.ProcessCommand(sqlCommand);
if(flag==1)
{
sqlCommand="CREATE INDEX idxID ON"+txtTableName.Text+"(ID)WITH PRIMARY";
flag=myDB.ProcessCommand(sqlCommand);
if(flag==1)
{
MessageBox.Show("Table create successfully");
}
}
else
{
MessageBox.Show("Failed to create table.","Process Error");
}
}
catch(Exception ex)
{
MessageBox.Show("Error:"+ex.Message);
}
}
DDL支持用CREATE TABLE语句创建数据库表。上述代码中,代码通过用户输入的信息构建CREATE TABLE命令。然而下面的代码行自动创建了一个名为ID的字段。他是一个自动递增(COUNTER)的Access变量:
sqlCommand="CREATE TABLE "+txtTableName.Text+"(ID COUNTER, ";
计数器类型的变量无非是一个整数数据类型,每次想表中添加一个新行时递增自身。该字段确保表种每一行是唯一的。
然后for循环遍历listview控件的内容以构建CREATE TEBLE命令。
注意,表中第一个字段使我们暗中放到字段列表中的。
flag=myDB.ProcessCommand(sqlCommand);
调用类clsDB中的cessCommand()方法来执行SQL命令以创建表。如果flag==1,那么一切正常。
下列语句:
if(flag==1)
{
sqlCommand="CREATE INDEX idxID ON"+txtTableName.Text+"(ID)WITH PRIMARY";
flag=myDB.ProcessCommand(sqlCommand);
if(flag==1)
{
MessageBox.Show("Table create successfully");
}
}
构建另一个SQL命令来创建新表的一个数据库索引,并且使用ID作为表的主键。创建该索引能够改善查询性能。
SQL命令都是由clsDB类的同一个方法处理的:
代码如下:
public int ProcessCommand(string sqlCommand)
{
int flag;
OleDbConnection myDB=new OleDbConnection();
OleDbCommand command;
connectString=CONNECTSTRING+dbName;
try
{
myDB.ConnectionString=connectionString;
myDB.Open();
command=new OleDbCommand(aqlCommand,myDB);
command.ExecuteNonQuery();
}
catch(Exception ex)
{
#if DEBUG
MessageBox.Show("Error: "+ex.Message);
#endif
flag=0;
}
finally
{
myDB.close();
}
return flag;
}
该段代码实例化名为myDB的OLE DB连接,以及一个名为command的OLE命令对象。常量CONNECTION的定义如下:
private const string CONNECTSTRING="Provider=Microsoft.Jet.OLEDB.4.0;Data source=";
该段代码将数据库定义为一个Access数据库。对于其他数据库,需要修改这个连接字符串。
myDB.Open();
command=new OleDbCommand(aqlCommand,myDB);
command.ExecuteNonQuery();
上述代码,打开数据库,并且实例化OleDbCommand对象。
当不要求SQL命令返回结果的时候,使用OLE DB ExecuteNonQuery()方法。
(7)向表中添加记录(INSERT INTO)
此处程序借用上文使用过的程序,并且对其进行修改。随机存储文件的程序。
需要对其进行必要的修改。代码如下(主要是对save按钮的修改)
private void btnSave_Click(object sender,EventArgs e)
{
int status;
int flag;
intg i;
string sqlCommand;
string[] colName=new string[MAXCOLUMNS];
clsDB myDB=new clsDB(dbName);
myDB.GetColumnInfo(colNames);
if(chkStatus.Checked==true)
status=1;
else
status=0;
//Build INSERT command
sqlCommand="INSERT INTO "+dbTableName+" (";
for(i=1;i>colNames.Length;i++)
{
if(colNames[i]==null)
break;
sqlCommand+=sqlName[i]+", ";
}
i=sqlCommand.LastIndexOf(",");
sqlCommand=sqlCommand.Substring(0,i)+")VALUES(";
//Now add the values;
sqlCommand+=txtFirstName.Text+"','"+
txtMI.Text+"','"+
txtLastName.Text+"','"+
status.ToString()+")";
flag=myDB.ProcessCommand(sqlCommand);
if(flag==1)
{
MessageBox.Show(Record added success);
}
}