13. 数据库访问技术

15 篇文章 4 订阅

数据库是一门复杂的技术,其在当前软件开发中得到了广泛 的应用。数据库的出现为数据存储技术带来了新的方向。为了使客户端能够访问服务器中的数据库,可以使用各种数据访问方法或技术,ADO.NET就是这样的一种技术。

1 数据库基础

1.1 数据库简介

数据库是按照数据结构来组织、存储和管理数据的仓库,是存储在一起的相关数据的集合。使用数据库可以减少数据的冗余度,节省数据的存储控件。其具有较高的数据独立性和易扩充性,实现了数据资源的充分共享。计算机系统中只能存储二进制的数据,而数据存在的形式却是多种多样的。数据库可以将多样化的数据转换成二进制形式,使其能够被计算机识别。同时,可以将存储在数据库中的二进制数据以合理的方式转化为人们可以识别的逻辑数据。

随着数据库技术的发展,为了进一步提高数据库存储数据的高效性和安全性,随即产生了关系型数据库。关系型数据库是由许多数据表组成的,数据表又是由多条记录组成的,而记录又是由许多的字段组成的,每个字段对应一个对象。根据实际的要求,设置字段的长度、数据类型、是否必须存储数据库。

数据库的种类有很多,常见的分类有以下几种:
①按照是否支持联网分为单机版数据库和网络版数据库。
②按照存储的容量分为小型数据库、中型数据库、大型数据库和海量数据库。
③按照是否支持关系分为非关系型数据库和关系型数据库。

1.2 SQL语言简介

SQL是一种数据库查询和程序设计语言,用于存储数据以及查询、更新和管理关系型数据库。SQL的含义是结构化查询语句(Structrued Query Language)。目前SQL语言有俩个不同的标准,分别是美国国家标准会(ADSI)和国际标准化组织(ISO)。SQL是一种计算机语言,可以利用它与数据库进行交互。SQL本身不是一个数据库管理系统,也不是一个独立的产品。但SQL是数据库管理系统中不可缺少的组成部分,它是与DMBS通信的一种语言和工具。由于它功能丰富,语言简洁,使用方法灵活,所以备受用户和计算机业界青睐,被众多计算机公司和软件公司采用。经过多年发展,SQL语言已经成为关系型数据库的标准语言。
说明:在编写SQL语句时,要注意SQL语句中的关键字要以空格来分隔。

1.3 数据库的创建及删除

数据库主要用于存储数据及数据库对象(如表、索引等)。下面以Microsoft SQL Server 2019位例介绍如何通过管理器来创建和删除数据库。

  1. 创建数据库
    ①在开始界面中找到SQL Server 2019 的Microsoft SQL Server Management Studio,打开“连接到服务器”界面,在对话框中选择登录的服务器名称和身份证验证方式,然后输入登录用户名和登录密码,点击连接按钮连接到指定的服务。
    在这里插入图片描述
    ②选中“数据库”节点,单击鼠标右键,在弹出的惨淡中选择“新建数据库”
    在这里插入图片描述
    ③打开“新建数据库”对话框,在该对话框中输入新建数据库的名称,选择数据库所有者和存放路径,这里的数据库所有者一般为默认。
    在这里插入图片描述
    ④单击“确定”按钮即可创建一个新的数据库

在这里插入图片描述

  1. 删除数据库

删除数据库的方法很简单,只需要在删除的数据库上单击鼠标右键,在弹出的快捷菜单中选择“删除”命令即可。
如果数据库以后还要被使用,可以将数据库进行分离,在数据库上单击鼠标右键,在弹出的快捷菜单中选择“任务/分离”命令
在这里插入图片描述
在这里插入图片描述

1.4 数据表的创建及删除

数据库创建完毕,接下来要在数据库中创建数据表。下面以上述数据库为例,介绍如何在数据库中创建和删除数据表。

  1. 创建数据表

①单击数据库名左侧加号(+),打开该数据库的子项目,在子项目中的“表”项上单击书标右键,在弹出的快捷菜单中选择“新建表”命令。
在这里插入图片描述

②在新建表中设置新建表的字段名称、字段数据类型、主键、索引值、默认初始值等,保存并且输入表名确定即可

在这里插入图片描述
在这里插入图片描述

  1. 删除数据表

如果要删除数据库中的某个数据表,只需右击数据表,在弹出的快捷菜单中选择“删除”命令即可。

在这里插入图片描述
在这里插入图片描述

1.5 简单的SQL语句的应用

  1. 查询数据

通过使用Select语句查询数据,Select语句是从数据库中检索数据并查询,并将查询结果以表格的形式返回。

语法:

SELECT  select_list
[ INTO new_table ]
FROM table_source
[ WHERE search_condition ]
[ GROUP BY group_by_expression ]
[ HAVING search_condition ]
[ ORDER BY order_expression [ASC] [DESC] ]

Select语句参数说明:

参数说明
Select_list指定由查询返回的列。它是一个逗号分隔的表达式列表。每个表达式同时定义格式(数据类型和大小)和结果集列的数据来源。每个选择列表表达式通常都是对从中获取数据的源表或视图的列的引用,但也可能是其他表达式,例如常量或T-SQL函数。在选择列表中使用*表达式指定返回源表中所有列。
INTO new_table创建表并将查询行从查询插入新表中。new_table 指定新表名称
table_source指定从其中检索行的表。这些来源可能包括基表、视图和链接表。From子句还可以包含连接接明,说明定义了SQL Server用来在表之间进行导航的特定路径。From子句还可以用在Delete和Update语句中,以定义要修改的表。
WHERE search_conditionWhere子句指定用于限制返回行的搜索条件。Where子句还用在Delete和Update语句中以定义目标中要修改的行
GROUP BY group_by_expressionGroup By子句根据group_by_list列中的值将结果分成组。例如,student表在 性别中you俩个值、Group By ShipVia子句将结果分成俩组,每组对应ShipVia的一个值
HAVING search_conditionHaving子句是指定组或聚合的搜索条件。逻辑上将,Having子句从中间结果集对行进行筛选,这些中间结果集使用Select语句中的From、Where和GroupBY子句创建的。Having子句通常与GroupBY子句一起使用,尽管Having子句前面不是必须有GroupBy子句
ORDER BY order_expression [ASC] [DESC]Order By子句定义结果集中的行排列的顺序。order_list指定组成排序列表的结果集的列。ASC和DESC关键字用于指定行是按照升序还是降序来排序。OrderBy之所以重要,是因为关系理论规定除非已经指定OrderBy,否则不能假设结果集中的行带有任何序列。如果结果集行的顺序对于Select语句来说很重要,那么就必须使用OrderBy语句
  1. 添加数据

在SQL中,使用Insert语句项数据表中添加数据

语法:

INSERT [INTO]
	{table_name WITH(<table_hint_limited>[···n])
|view_name
|rowset_function_limited 
}
{[column_list]
	{VALUES
		({DEFAULT|NULL|expression}[,..])
		|derived_table
		|execute_statement
	}
}
|DEFAULT vALUES

Insert语句参数说明:

参数说明
[INTO]一个可选的关键字,可以将它用在INSERT和目标表之间
tabel_name将要接受数据的表或table变量的名称
view_name视图的名称及可选的别名。通过view_name来引用的视图必须是可更新的
(column_list)要在其中插入数据的一列或多列的列表。必须用圆括号将column_list括起来,并且用逗号进行分隔
VALUES引入要插入的数据值的列表。对于column_list(如果已经指定)中或者表中的每个列,都必须有一个数据值。必须用圆括号将值列表括起来。如果VALUES列表中的值、表中的值与表中列的顺序不相同,或者未包含表中所有列的值,那么必须使用column_list明确的指定存储每个传入值的列
DEFAULT强制SQLServer装载为列定义的默认值。如果对于某列并不存在默认值,并且该列允许为NULL,那么就插入NULL
expression一个常量、变量或表达式。表达式不能包含Select和Execute语句
derived_table任何有效的Select语句,它将返回装载到表中的数据行

注意:
① 插入项的顺序和数据类型必须与表或视图中列的顺序和数据类型相对应
②如果表中某列定义为不允许为NULL,则插入数据时,该列必须存在合法值
③如果某列是字符型或日期型数据类型,则插入的数据应该加上单引号

  1. 更新数据

使用Update语句根新数据,可以修改一个或者几个列的值,但一次只能修改一个表。

语法:

UPDATE
	{table_name WITH(<table_hint_limited>[···n])
	|view_name
	|rowset_function_limited 
	}
	SET
	{column_name={expression|DEFAULT|NULL}
	|@variable=expression
	|@variable=column=expression}[,···n]
	{{[FROM{<table_source>}[,···n]]
	[WHERE
		<search_condition>]}
	|
	[WHERE CURRENT OF
	{{[GLOBAL]cursor_name}|cursor_variable_name}
	]}
	[OPTION(<qyery_hint>[,···n])] 

Update语句参数说明:

参数说明
table_name需要更新的表的名称。如果该表不再当前服务器或数据库中,或不为当前用户所有,那么这个名称可用链接服务器、数据库和所有者名称来限定
WITH(<table_hint_limited>[···n])指定目标表所允许的一个或多个表提示。需要有WITH关键字和圆括号。不允许有READPAST、NOLOCK和READUNCOMMITTED
view_name更新的视图的名称通过view_name来引用的视图必须是可更新的。用Update语句进行的修改,至多只能影响视图的FROM子句所引用的基表中的一个
rowset_function_limitedOPENQUERYhuoOPENROWSET函数,视提供程序功能而定
SET指定要更新的列或变量名称的列表
column_name含有要更改数据的列的名称。column_name必须驻留于UPDATE子句中所指定的表或视图中。标识列不能进行更新
expression变量、字面值、表达式或加上括弧的返回单个值的subSelect语句。expression返回的值将替换column_name或@variable中的现有值
DEFAULT指定使用对列定义的默认值替换列中的现有值。如果该列没有默认值并且定义允许为空值,也可以用来将列更改外NULL
@variable已声明的变量,该变量将设置为expression所返回的值
FROM<table_source>指定用表来为更新操作提供准则
WHERE指定条件来限定所更新的行
<search_condition>为要更新行指定需要满足的条件。搜索条件也可以是联接所基于的条件。对搜索条件中可以包含的谓词数量没有限制
CURRENT OF指定跟新在指定游标的当前位置进行
GLOBAL指定cursor_name是全局游标
cursor_name要从中进行提取的开放游标的名称。如果同时存在名为cursor_name的全局游标和局部游标,则在指定了GLOBAL时,cursor_name指的是全局游标,如果未指定GLOBAL,则cursor_name指局部游标。游标允许被更新
cursor_variable_name游标变量的名称。cursor_variable_name必须引用可以允许更新的游标
OPTION(<qyery_hint>[,···n])指定优化程序提示用于自定义SQLServer的语句处理

说明:
Update语句将记入日志。如果要替换或修改大块的text、ntext或image数据,请使用WriteText或UpdateText语句而不要使用Update语句。

  1. 删除数据

使用Delete语句删除数据,可以使用一个单一的Delete语句删除一行或多行。当表中没有行满足Where子句中指定的条件时,就没有行会被删除,也没有错误产生。

语法:

DELETE
	[ FROM ]
		{ table_name WITH ( < table_hint_limited > [ ,...n] )
		|view_name
		|rowset_function_limited
		}
		[ FROM { <  table_source> } [ ,...n] ]
	[ WHERE
		{ < search_condition >
		| { [ CURSOR OF
			{ { [ GLOBAL ] cursor_name }
				| cursor_variable_name
			}
		] }	
]
[ OPTION ( < query_hint > [ ,...n ] ) ]

Delete语句参数说明:

参数说明
table_name需要更新的表的名称。如果该表不再当前服务器或数据库中,或不为当前用户所有,那么这个名称可用链接服务器、数据库和所有者名称来限定
WITH(<table_hint_limited>[···n])指定目标表所允许的一个或多个表提示。需要有WITH关键字和圆括号。不允许有READPAST、NOLOCK和READUNCOMMITTED
view_name要更新的视图的名称。通过view_name来引用的视图必须是可更新的。用Update语句进行的修改,至多只能影响视图的FROM子句所引用的基表中的一个
rowset_function_limitedOPENQUERYhuoOPENROWSET函数,视提供程序功能而定
FROM<table_source>指定用表来更新操作提供准则
WHERE指定条件来限定所更新的行
<search_condition>为要更新行指定需要满足的条件。搜索条件也可以是联接所基于的条件。对搜索条件中可以包含的谓词数量没有限制
CURRENT OF指定跟新在指定游标的当前位置进行
GLOBAL指定cursor_name是全局游标
cursor_name要从中进行提取的开放游标的名称。如果同时存在名为cursor_name的全局游标和局部游标,则在指定了GLOBAL时,cursor_name指的是全局游标,如果未指定GLOBAL,则cursor_name指局部游标。游标允许被更新
cursor_variable_name游标变量的名称。cursor_variable_name必须引用可以允许更新的游标
OPTION(<qyery_hint>[,···n])指定优化程序提示用于自定义SQLServer的语句处理

2. ADO.NET简介

ADO.NET是一组.向NET程序员公开数据访问服务的类。ADO.NET为创建分布式数据共享应用程序提供了一组丰富的组件。它提供了一系列的方法,用于支持对Microsoft SQL Server 和 XML 等数据源进行访问,还提供了通过OLEDB和XML公开的数据源提供一致访问的方法。数据客户端应用程序可以使用ADO.NET来连接到这些数据源,并查询、添加、删除和更新所包含的数据。

ADO.NET支持俩种访问数据的模型:无连接模型和链接模型。
无连接模型将数据下载到客机上,并在客户机上将数据封存到内存中,可以向访问本地关系型数据库一样访问内存中的数据(如DateSet)。
链接模型依赖于逐记录的访问,这种访问要求打开并保持与数据库的连接。

这里可以用趣味形象化的方式理解ADO.NET对象模型的各个部分,参照下图用比对的方法来形象的理解ADO.NET中每个对象的作用。
如下图:
在这里插入图片描述

①数据库好比水源
②Connection对象好比伸入水中的进水龙头,保持与水的接触,只有它与水进行了连接,其他对象才可以抽到水
③Command对象则项抽水机,为抽水提供动力和执行方法,通过水龙头,然后把水返给上面的水管
④DateAdapter、DateReader对象就像输水管,担任着水的传输任务,并起着桥梁的作用。DateAdapter对象像一根输水管,通过发动机,把水从水源送到水库进行保存。而DateReader对象也是一种水管,和DataAdapter对象不同的是,他不把水送到水库里面,而是单项地直接把水送到需要谁的用户那里,所以要比在水库中转一下的速度快。
⑤DataSet对象则是一个大水库,把抽上来的水按一定关系的池子进行存放。即使撤掉抽水装置(断开连接、离线状态),也可以保持水的存在。这正是ADO.NET的核心。
⑥DataTable对象则向水库中的每个独立的水池子,分别存放不同种类的水。一个大水库由一个或多个这样的水池子组成。

3 连接数据库:Connection对象

3.1 Connection对象概述

Connection对象是一个连接对象,主要功能是建立与物理数据库的连接。其主要包括4种访问数据库的对象类,也可称为数据提供程序。
① SQL Server数据提供程序,位于System.Data.SqlClient命名空间
② ODBC数据提供程序,位于System.Data.Odbc命名空间
③ OLEDB数据提供程序,位于System.Data.OleDb命名空间
④ Oracle数据提供程序,位于System.Data.OracleClient命名空间
根据使用数据库的不同,引入不同的命名空间,然后通过命名空间中的Connection对象连接数据库。

3.2 连接数据库

以SQL Server数据库为例,如果要连接SQL Server数据库,必须使用System.Data.SqlClient命名空间下的
SqlConnection类。所以首先通过using System.Data.SqlClient命令引用 SQL Server数据提供程序,然后才能调用空间下的SqlConnection类连接数据库。调用SqlConnection对象的Open方法打开数据库,在通过SqlConnection对象的State属性判断数据库的连接状态。
语法:

public override ConnectionState State { get; }
//属性值:ConnectionState 枚举

ConnectionState枚举的值及说明:

枚举值说明
Broken与数据源的连接中断。只有在连接打开之后才能发生这种情况。可以关闭处于这种状态的连接,然后重新打开。
Closed连接处于关闭状态
Connecting连接对象正在与数据源进行链接
Executing连接对象正在执行命令
Fetching连接对象正在检索数据
Open链接处于打开状态

实例:

private void button1_Click(object sender, EventArgs e)
{
    if (textBox1.Text == "")
    {
        MessageBox.Show("请输入要连接的数据库名称!");
    }
    else
    {
        try
        {
            //用户名和密码验证的方式去连接到数据库服务器
            //string ConStr = "server=.;database=" + textBox1.Text.Trim() + ";uid=TJHIS;pwd=";
            //Windows验证的方式去连接到数据库服务器
            string ConStr = "Data Source=.;Initial Catalog=" + textBox1.Text.Trim() + ";Integrated Security=True";
            SqlConnection conn = new SqlConnection(ConStr);
            conn.Open();
            if (conn.State==System.Data.ConnectionState.Open)
            {
                label2.Text = "数据库" + textBox1.Text + "已经打开连接";
            }
        }
        catch 
        {
            MessageBox.Show("连接数据库失败!");
        }
    }
}

效果:
在这里插入图片描述

3.3 关闭连接

当数据库操作完毕后,要关闭与数据库的连接。通过调用SqlConnection对象的Close方法或Dispose方法关闭与数据库的连接,这俩种方式的主要区别是:Close方法用于关闭一个连接,而Dispose方法不仅关闭一个连接,而且还清理连接所占用的资源。当使用Close方法关闭连接后,可以再调用Open方法打开连接,不会产生任何错误。而如果使用Dispose方法关闭连接,就不可以再次直接使用Open方法打开连接,必须再次重新初始化连接再打开。

实例:

SqlConnection conn;
private void button1_Click(object sender, EventArgs e)
{
    if (textBox1.Text == "")
    {
        MessageBox.Show("请输入要连接的数据库名称!");
    }
    else
    {
        try
        {
            //string ConStr = "server=.;database=" + textBox1.Text.Trim() + ";uid=TJHIS;pwd=";
            string ConStr = "Data Source=.;Initial Catalog=" + textBox1.Text.Trim() + ";Integrated Security=True";
            conn = new SqlConnection(ConStr);
            conn.Open();
            if (conn.State==System.Data.ConnectionState.Open)
            {
                MessageBox.Show("连接成功!"); 
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            textBox1.Text = "";
        }
    }

}
private void button2_Click(object sender, EventArgs e)
{
    try
    {
        string str = "";
        conn.Close();
        conn.Open();
        if (conn.State == System.Data.ConnectionState.Open)
        {
            str = "数据库已经成功打开 \n";
            richTextBox1.Text = str;
        }
        
    }
    catch (Exception ex)
    {

        richTextBox1.Text = ex.Message;
    }
}
private void button3_Click(object sender, EventArgs e)
{
    try
    {
        conn.Dispose();
        conn.Open();
    }
    catch (Exception ex)
    {
        richTextBox1.Text = ex.Message;
    }
}

效果:
在这里插入图片描述

在这里插入图片描述

说明:
在编写应用程序时,对数据库操作完成后,要及时关闭数据库的连接,以防止在对数据库进行其他操作时,数据库被占用。

4 执行SQL语句:Command对象

4.1 Command对象概述

Command对象是一个数据命令对象,主要功能是向数据库发送查询、更新、删除、修改操作的SQL语句。
Command对象主要有以下几种方式:
① SqlCommand:用于向SQL Server数据库发送语句,位于System.Data.SqlClient命名空间
② OleDbCommand:用于向使用OLEDB公开的数据库发送SQL语句,位于System.Data.OleDb命名空间。例如,Access数据库和MySql数据库都是OLEDB公开的数据库
③ OdbcCommand:用于向ODBC公开的数据库发送SQL语句,位于System.Data.Odbc命名空间。有些数据库没有提供相应的连接程序,则可以配置好ODBC连接后,使用OdbcCommand。
④ OracleCommand:用于向Oracle数据库发送SQL语句,位于System.Data.OracleClient命名空间
说明:
在使用OracleCommand向Oracle数据库发送SQL语句时,要引入System.Data.OracleClient命名空间。但是默认情况下没有此命名空间,此时需要将System.Data.OracleClient一如到项目中。引入程序集的方法时在项目名称上单击鼠标右键,在弹出的快捷菜单中选择添加引用命令,打开添加引用对话框。在该对话框中选择System.Data.OracleClient程序集,将其添加到项目中。

4.2 设置数据源类型

Command对象有三个重要的属性,分别是Connection属性、CommandText属性和CommandType属性。
①Connection属性用于设置SqlCommand使用的SqlConnection。
②CommandText属性用于设置要对数据源执行的SQL语句或存储过程。
③CommandType属性用于指定CommandText的类型。
CommandType属性的值是CommandType枚举值。
StoredProcedure:存储过程名称
TableDirect:表的名称
Text:SQL文本命令
如果要设置数据源的类型,便可以通过CommandType属性来实现。

实例:

SqlConnection conn;
private void Form1_Load(object sender, EventArgs e)
{
    string ConStr = "Data Source=.;Initial Catalog=TJHIS;Integrated Security=True";
    conn = new SqlConnection(ConStr);
    conn.Open();
}
private void button1_Click(object sender, EventArgs e)
{
    try
    {
        if (textBox1.Text !="" || conn.State == System.Data.ConnectionState.Open )
        {
            SqlCommand cmd = new SqlCommand();
            //设置Connection属性
            cmd.Connection = conn;
            //设置CommandText属性,设置SQL语句
            cmd.CommandText = "select count(*) from " + textBox1.Text.Trim();
            //设置CommandType属性为Text,使其只执行SQL语句文本形式
            cmd.CommandType = System.Data.CommandType.Text;
            //使用ExecuteScalar 方法获取指定数据表中的数据数量
            int i = Convert.ToInt32(cmd.ExecuteScalar());
            label2.Text = "数据表中共有:"+ i.ToString() +"条数据";
        }

    }
    catch (Exception)
    {

        throw;
    }
}

效果:
在这里插入图片描述

在这里插入图片描述

4.3 执行SQL语句

Command对象需要取得将要执行的SQL语句,通过调用该类提供的多种方法,向数据库提交SQL语句。

  1. ExecuteNonQuery方法

执行SQL语句,并返回受影响的行数,在使用SqlCommand向数据库发送增、删、该命令时,通常使用ExecuteNonQuery方法执行发送的SQL语句。

语法:

piblic override int ExecuteNonQuery()
//返回值:受影响的行数

实例:

SqlConnection conn;
private void Form1_Load(object sender, EventArgs e)
{
    string ConStr = "Data Source=.;Initial Catalog=TJHIS;Integrated Security=True";
    conn = new SqlConnection(ConStr);
    conn.Open();
}
private void button1_Click(object sender, EventArgs e)
{
    try
    {
        if (textBox1.Text !="" || textBox2.Text != ""  || conn.State == System.Data.ConnectionState.Open )
        {
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = string.Format("update student set name ='{0}' where id = '{1}'", textBox2.Text.ToString(), textBox1.Text.ToString());
            //cmd.CommandText =  ;
            cmd.CommandType = System.Data.CommandType.Text;
            int i = Convert.ToInt32(cmd.ExecuteNonQuery());
            label2.Text = "数据表中共有:"+ i.ToString() +"条数据被更新";
        }
        else
        {
            MessageBox.Show("请输入学号、新名字!");
        }

    }
    catch (Exception)
    {

        throw;
    }
}

效果:

在这里插入图片描述

在这里插入图片描述
说明:
如果想要执行存储过程,应将CommandType属性设置为StoredProcedure,将CommandText属性设置为存储过程的名称。

  1. ExecuteReader方法

执行SQL语句,并生成一个包含数据的SqlDataReader对象的实例。
语法:

public SQLDataReader ExecuterReader()
//返回值:一个SqlDataReader对象

实例:

SqlConnection conn;
private void Form1_Load(object sender, EventArgs e)
{
    string ConStr = "Data Source=.;Initial Catalog=TJHIS;Integrated Security=True";
    conn = new SqlConnection(ConStr);
    conn.Open();
}
private void button1_Click(object sender, EventArgs e)
{
    try
    {
        SqlCommand cmd = new SqlCommand();
        cmd.Connection = conn;
        cmd.CommandText = string.Format("select * from student");
        cmd.CommandType = System.Data.CommandType.Text;
        SqlDataReader sdr = cmd.ExecuteReader();
        while (sdr.Read())
        {
            listView1.Items.Add(sdr[1].ToString());
        }
        conn.Dispose();
        button1.Enabled = false;

    }
    catch (Exception)
    {

        throw;
    }
}

效果:
在这里插入图片描述

  1. ExecuteScalar方法

执行SQL语句,返回结果集中的第一行第一列
语法:

public override Object ExecuteScalar()
返回值:结果集中的第一行第一列或空引用(如果结果集为空)

ExecuteScalar方法通常与聚合函数一起使用,常见的聚合函数如下表:

聚合函数函数说明
AVG(expr)求平均值,该列只能包含数字数据
Count(expr)、COUNT(*)列值的计数(如果将列名置定为expr)、表或分组中所有行的计数(如果指定*)忽略空值,但COUNT(*)在计数中包含空值
MAX(expr)列中最大值(文本数据类型中按字母顺序排在最后得值),忽略空值
MIN(expr)列中最小值文本数据类型中按字母顺序排在最前得值),忽略空值
SUM(expr)列值的合计,该列只能包含数字数据

5 读取数据:DataReader对象

5.1 DataReader对象概述

DataReader对象是数据读取器对象,提供只读向前的游标,如果应用程序需要每次从数据库中取出最新的数据,或者只是需要快速读取数据,并不修改数据,那么就可以使用DataReader对象进行读取。对于不同的连接,有不同的DataReader对象类型。

①SqlDataReader类,System.Data.SqlClient命名空间下
②OleDbDataReader类,System.Data.OleDb命名空间下
③OdbcDataReader类,System.Data.Odbc命名空间下
④OracleDataReader类,System.Data.Oracle命名空间下

说明:
在创建DataRelation时,它首先验证是否可以建立关系。在创建DataRelation和将其添加到DataRelationCollection(DataSet的DataRelation对象等集合)之间的这段时间,可以对父行或子行进行其他更改。

SqlDataReader sdr = cmd.ExecuteReader();

5.2 判断查询结果中是否有值

可以通过SqlDataReader对象的HasRows属性获取一个值,该值指示SqlDataReader对象是否包含一行或多行,即判断查询结果中是否有值。

语法:

public override  bool HasRows {get; }
属性值:如果SqlDataReader包含一行或多行,则为true

实例:

private void Form1_Load(object sender, EventArgs e)
{
    string ConStr = "Data Source=.;Initial Catalog=TJHIS;Integrated Security=True";
    conn = new SqlConnection(ConStr);
    conn.Open();
}
private void button1_Click(object sender, EventArgs e)
{
    try
    {
        if (textBox1.Text != ""  || conn.State == System.Data.ConnectionState.Open)
        {
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = string.Format("select * from  {0}", textBox1.Text.ToString());
            cmd.CommandType = System.Data.CommandType.Text;
            SqlDataReader sdr = cmd.ExecuteReader();
            sdr.Read();
            if (sdr.HasRows)
            {
                MessageBox.Show("数据表中有值");
            }
            else
            {
                MessageBox.Show("数据表中无值");
            }
        }
        else
        {
            MessageBox.Show("请输入表名");
        }
    }
    catch (Exception)
    {

        throw;
    }
}

效果:
在这里插入图片描述

5.3 读取数据

如果要读取数据表中的数据,通过ExecuteReader方法,根据SQL语句创建一个SqlDataReader对象后,再调用SqlDataReader对象的Read方法读取数据。Read方法使SqlDataReader前进到下一条记录,SqlDataReader的默认位置在第一条记录前面。因此,必须调用Read方法访问数据。对于每个关联的SQLConnection,一次只能打开一个SQLDataReader,在一个关闭之前,打开另一个的任何尝试都将失败。
语法:

public override bool Read()
//返回值:如果存在多个行,则为true,否则为false
//在使用完SQLDataReader对象后,要使用Close方法关闭SQLDataReader对象
public override bool Close()

实例:

conn = new SqlConnection("Data Source=.;Initial Catalog=TJHIS;Integrated Security=True");
conn.Open();
SqlCommand cmd = new SqlCommand("select * from student", conn);
SqlDataReader sdr = cmd.ExecuteReader();
sdr.Close();

注意:
在使用SqlDataReader 对象之间,必须打开数据库连接。如果针对一个SqlConnection,创建多个SqlDataReader对象,则创建下一个SqlDataReader 对象之前,要通过Close方法关闭上一个SqlDataReader对象。

6 数据适配器:DataAdapter对象

6.1 DataAdapter对象概述

DataAdapter对象是一个数据适配器对象,是DataSet与数据源之间的桥梁。DataAdapter对象提供了4个实行,用于实现与数据源之间的互通。
SelectCommand属性:向数据库发送查询SQL语句。
DeleteCommand属性:向数据库发送删除SQL语句。
InsertCommand属性:向数据库发送插入SQL语句。
UpdateCommand属性:向数据库发送更新SQL语句。

对数据库进行操作时,只要将这四个属性设置成相应的SQL语句即可。DataAdapter对象中有几个主要的方法具体如下:

①.Fill方法用数据填充DataSet
语法:

public int Fill(DataSet dataSet,string strTable)
//dataSet:用于记录和架构(如果必要)填充的DataSet
//strTable:用于表映射的源表的名称
//返回值:已经在DataSet中成功添加或刷新的行数,这不包括受不返回行的语句的影响

说明:
当创建DataAdapter的实例时,将其读/写属性设置为初始值
MissingMappingAction属性设置为MissingMappingAction.Passthrough
MissingSchemaAction属性设置为MissingSchemaAction.Add

② Update方法更新数据库时,DataAdapter将调用DeleteCommand、InsertCommand以及UpdateCommand属性

语法:

public int Update (DataTable datatable)
datatable:用于更新数据源的DataTable 
返回值:DataSet中成功更新的行数

例如:如果使用DataAdapter对象的Fill方法从数据源中提取数据并填充到DataSet时,就会用到SelectCommand属性中设置的命令对象。

6.2 填充DataSet数据集

通过DataAdapter对象的Fill方法填充DataSet数据集,Fill方法使用Select语句从数据源中检索数据。与Select命令关联的Connection对象必须有效,但不需将其打开。

注意:
DataSet对象和DataTable对象从MarshalByValueComponent(实现IComponent并提供可远程控制的组件的基实现)继承而来,并支持用于远程处理ISerializable接口。

实例:

private void button1_Click(object sender, EventArgs e)
{
    string ConStr = "Data Source=.;Initial Catalog=TJHIS;Integrated Security=True";
    SqlConnection  conn = new SqlConnection(ConStr);
    conn.Open();
    try
    {
        if (conn.State == ConnectionState.Open)
        {
            SqlCommand cmd = new SqlCommand("select * from  student ",conn);
            SqlDataAdapter sdr = new SqlDataAdapter();
            sdr.SelectCommand = cmd;
            DataSet ds = new DataSet();
            sdr.Fill(ds,"cs");
            dataGridView1.DataSource = ds.Tables[0];
        }
    }
    catch (Exception)
    {

        throw;
    }
}

效果:
在这里插入图片描述

6.3 更新数据源使用

DataAdapter对象的Update方法,可以将DataSet中修改过的数据及时更新到数据库中。在调用Update方法之前,要实例化一个CommandBuilder类,它能自动根据DataAdapter的SelectCommand的SQL语句判断其他的InsertCommand、UpadteCommand和DeleteCommand。这样就不用设置DataAdapter对象的InsertCommand、UpadteCommand和DeleteCommand属性,直接使用DataAdapter的Update方法来更新DataSet、DataTable或DataRos数据即可。

实例:

DataSet ds = new DataSet();
SqlDataAdapter sdr = new SqlDataAdapter();
private void Form1_Load(object sender, EventArgs e)
{
    string ConStr = "Data Source=.;Initial Catalog=TJHIS;Integrated Security=True";
    SqlConnection conn = new SqlConnection(ConStr);
    conn.Open();
    try
    {
        if (conn.State == ConnectionState.Open)
        {
            SqlCommand cmd = new SqlCommand("select * from  student ", conn);
            sdr.SelectCommand = cmd;
            sdr.Fill(ds, "cs");
            dataGridView1.DataSource = ds.Tables[0];
        }
    }
    catch (Exception)
    {

        throw;
    }
}
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
    textBox1.Text = dataGridView1.SelectedCells[0].Value.ToString();
    textBox2.Text = dataGridView1.SelectedCells[1].Value.ToString();
    textBox1.Enabled = false;
}
private void button1_Click_1(object sender, EventArgs e)
{
    DataTable dt = ds.Tables[0];
    sdr.FillSchema(dt, SchemaType.Mapped);
    DataRow dr = dt.Rows.Find(textBox1.Text);
    dr["name"] = textBox2.Text.Trim();
    SqlCommandBuilder scbd = new SqlCommandBuilder(sdr);
    sdr.Update(dt);
}

效果:
在这里插入图片描述

说明:
在DataTable对象上可以多次使用Fill方法。如果主键存在,则传入行会与已有的匹配行合并。如果主键不存在,则传入行会追加到DataTable中。

7 数据集:DataSet对象

7.1 DataSet对象概述

DataSet对象就像存放于内存中的一个小型数据库。它可以包含数据表、数据列、数据行、视图、约束以及关系。通常,DataSet的数据来源于数据库或者XML,为了从数据库中获取数据,需要使用数据适配器(DataAdapter)从数据库中查询数据。

conn = new SqlConnection("Data Source=.;Initial Catalog=TJHIS;Integrated Security=True");
DataSet ds = new DataSet();
SqlDataAdapter sda = new SqlDataAdapter("select * from  student ", conn);
sda.Fill(ds);

7.2 合并DataSet内容

可以使用DataSet的Merge方法将DataSet、DataTable或DataRow数组的内容并入现有的DataSet中。Merge方法将指定的DataSet及其架构与当前DataSet合并。在此过程中,将根据给定的参数保留或放弃在当前DataSet中的更改并处理不兼容的架构。当DataSet对象为null时,无法进行合并。
语法:

public void Merge(DataSet dataSet,bool preserveChanges,MissingSchemaAction missionSchemaAction)
//dataSet:其数据和架构将被合并到DataSet中
//preserveChanges:要保留当前DataSet中的更改则为true,否则为false
//missionSchemaAction:MissionSchemaAction枚举值之一

MissionSchemaAction枚举成员及说明:

枚举成员说明
Add添加必需的列以完成架构
AddWithKey添加必需的列和主键信以完成架构,用户可以在每个DataTable上显示设置主键约束。这将确保对现有记录匹配的传入记录进行更新,而不是追加
Error如果缺少指定的列映射,则生成InvalidOperationException
Ignore忽略额外列

实例:

private void Form1_Load(object sender, EventArgs e)
{
    string ConStr = "Data Source=.;Initial Catalog=TJHIS;Integrated Security=True";
    SqlConnection conn = new SqlConnection(ConStr);
    conn.Open();
    try
    {
        if (conn.State == ConnectionState.Open)
        {
            DataSet ds1 = new DataSet();
            DataSet ds2 = new DataSet();
            SqlDataAdapter sda1 = new SqlDataAdapter("select * from  student ", conn);
            SqlDataAdapter sda2 = new SqlDataAdapter("select * from  scoure2 ", conn);
            SqlCommandBuilder sb1 = new SqlCommandBuilder(sda1);
            sda1.Fill(ds1);
            sda2.Fill(ds2);
            ds1.Merge(ds2,true, MissingSchemaAction.AddWithKey);
            dataGridView1.DataSource = ds1.Tables[0];
        }
    }
    catch (Exception)
    {

        throw;
    }
}

效果:
在这里插入图片描述

7.3 复制DataSet内容

为了在不影响原始数据的情况下使用数据,或者使用DataSet中数据的子集,可以创建DataSet副本。当复制DataSet时,可以:
①创建DataSet的原样副本,其中包含架构、数据、行状态和行版本
②创建包含现有DataSet的架构但仅包含已修改行的DataSet。可以返回已修改的所有行或者指定特定的DataRowState。有关行状态的更多信息,可参见行状态与行版本。
③仅复制DataSet的架构(即关系结构),而不复制任何行。可以使用ImportRow将行导入现有的DataTable。

可以使用DataSet对象的Copy方法创建包含架构和数据的DataSet的原样副本。Copy方法的功能是复制指定DataSet的结构和数据。
语法:

public DataSet Copy()
返回值:新的DataSet,具有与该DataSet 相同的结构(表架构、关系和约束)和数据

实例:

DataSet ds = new DataSet();
private void Form1_Load(object sender, EventArgs e)
{
    string ConStr = "Data Source=.;Initial Catalog=TJHIS;Integrated Security=True";
    SqlConnection conn = new SqlConnection(ConStr);
    conn.Open();
    try
    {
        if (conn.State == ConnectionState.Open)
        {
            SqlDataAdapter sda = new SqlDataAdapter("select * from  student ", conn);
            sda.Fill(ds);
            dataGridView1.DataSource = ds.Tables[0];
        }
    }
    catch (Exception)
    {

        throw;
    }
}
private void button1_Click(object sender, EventArgs e)
{
    DataSet ds1 = ds.Copy();
    dataGridView2.DataSource = ds1.Tables[0];
}

效果:
在这里插入图片描述

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值