SQLCommand
这个类用于执行SQL命令。
属性:
提示:如果使用外部数据源, 请记得设置数据源名称
方法:
ExecuteScalar
用于执行返回单个值的命令,例如:
Dim
val
As Integer
Dim cmd
As New
SQLCommand
cmd.ConnectionName
= "数据源名称"
cmd.CommandText = "Select
Sum(数量) From {订单} Where 日期 > #2012/2/21#"
val = cmd.ExecuteScalar()
上面的代码统计2012年2月21日之后的销售总量,并保存在变量val中。
再例如:
Dim ld As Date
Dim cmd As New SQLCommand
cmd.ConnectionName
= "数据源名称"
cmd.CommandText = "Select Max(日期) From {订单} Where 产品 = 'PD01'"
ld = cmd.ExecuteScalar()
上面的代码得到最后一次有人订购PD01的日期,并保存在变量ld中。
再例如:
Dim
ld
As Date
Dim cmd
As New
SQLCommand
cmd.ConnectionName
= "数据源名称"
cmd.CommandText = "Select top
1 日期 From {订单} Where 产品 = 'PD01' Order by 日期 Desc"
ld = cmd.ExecuteScalar()
上面的代码得到最后一次有人订购PD01的日期,并保存在变量ld中 ,和前一段代码功能一样,但是方法不同,希望大家体会。
ExecuteScalar经常用来判断是否存在指定条件的数据,例如:
Dim
cmd
As New
SQLCommand
Dim nm
As String
= "贺辉"
cmd.ConnectionName
= "User"
cmd.CommandText ="Select
Count(*) From {Users} Where Name = '"
& nm & "'"
If cmd.ExecuteScalar
> 0
Then
Messagebox.Show("已经存在同名用户","提示",MessageBoxButtons.OK,MessageBoxIcon.Information)
End If
ExecuteValues
用于执行一次返回多个值的命令,例如:
Dim
cmd As
new SQLCommand
cmd.CommandText
= "Select
部门,职务
from {员工}
Where 姓名
= '王伟'"
cmd.ConnectionName
= "数据源名称"
Dim
Values = cmd.ExecuteValues
If
Values.Count >
0 Then
Output.show(Values("部门"))
Output.show(Values("职务"))
End
If
再例如:
Dim
cmd As
new SQLCommand
cmd.CommandText
= "Select Sum(数量)
As 数量,
Sum(数量
* 单价)
As 金额
from {订单}
Where 产品
= 'PD01'"
cmd.ConnectionName
= "数据源名称"
Dim
Values = cmd.ExecuteValues
If
Values.Count >
0 Then
Output.show(Values("数量"))
Output.show(Values("金额"))
End
If
ExecuteNonQuery
用于执行不返回任何值的SQL命令,例如DELETE和UPDATE命令。
该方法会返回一个整数,表示受影响的行数。
示例一
Dim
cmd As New SQLCommand以上代码会删除产品PD01的所有订单,执行速度很快。
但是执行完成后,你会发现订单表中产品PD01订单并没有被删除,这是因为DELETE是直接从后台删除的。
所以我们还需要用Remove方法移除已经删除的行:
Dim cmd As New SQLCommand
cmd.ConnectionName
= "数据源名称"
Dim Count As Integer
cmd.CommandText = "DELETE FROM {订单} WHERE 产品 = 'PD01'"
Count= cmd.ExecuteNonQuery()
DataTables("订单").RemoveFor("产品 = 'PD01'")
Messagebox.Show( "总共删除"
& Count & "行!")
也可以用Load方法重新加载表:
Dim cmd As New SQLCommand
cmd.ConnectionName
= "数据源名称"
cmd.CommandText = "DELETE FROM {订单} WHERE 产品 = 'PD02'"
cmd.ExecuteNonQuery()
DataTables("订单").Load()
用Remove的效率更高,但用Load可以同时刷新数据,可根据需要选择。
当然如果删除的数据之前并没有被加载,那么就不需要在删除后执行Remove或Load方法。
示例二
Dim
cmd As New SQLCommand上述代码将订购数量超过500的订单的折扣设为0.2,同样在代码的最后调用了Load方法来显示最新数据。
如果要更新的行之前并没有被加载,那么就不需要在更新后调用Load方法。
UPDATE本身的执行速度很快,而且无需保存即刻生效,但是同样需要重新加载表,才能看到更新后的数据。
所以只有在需要更新大量的行,或者要更新没有加载的数据,才可以考虑用UPDATE命令
ExecuteReader
ExecuteReader用于从后台提取数据生成一个临时的DataTable,而这个DataTable只存在于代码的运行过程中,不会以表的形式呈现给用户。
示例一
同样,假定窗口中有一个组合框(ComboBox),希望这个窗口能够列出订单表所有的客户名称,如果订单表采用动态加载,或者根本没有加载,那么显然无法从订单表中获得所有客户名称,只能利用ExecuteReader直接从后台提取:
Dim
cmd As New SQLCommand上述代码可以设置在窗口的AfterLoad事件中。
示例二
同样有了ExecuteReader,就可以直接利用后台数据给列生成下拉目录树:
'生成数据表
示例三
同样利用ExecuteReader,可以直接从后台提取数据合并到某个表中:
Dim
cmd As New SQLCommand示例四
前面提到ExecuteReader生成的DataTable会在代码运行结束后自动销毁。
如果希望DataTable在代码结束后能够继续存在,可以使用Public变量引用这个DataTable。
例如首先在全局代码中定义一个DataTable类型的Public变量:
Public
dt As DataTable然后在项目事件AfterOpenProject中设置代码,将生成的DataTable赋值给此变量:
Dim
cmd As New SQLCommand这样就可以在任何位置的代码引用此变量:
Dim cmb As WinForm.ComboBox
cmb = e.Form.Controls("ComboBox1")
cmb.ComboList= dt.GetComboListString("客户")
示例五
ExecuteReader有一个可选参数,如果设置为True,那么生成的DataTable不仅可以增加、删除和修改数据,还可以保存。
新建一个文件,在命令窗口测试下面的代码,会在A的第一行的第一列写入123,并删除第二行:
Dim
cmd As
new
SQLCommand
cmd.ConnectionName
= "数据源名称"
Dim
dt As
DataTable
cmd.CommandText
= "Select * From {表A}"
dt =
cmd.ExecuteReader(True)
'记得将参数设置为True
dt.DataRows(0)("第一列")
= 123
dt.DataRows(1).Delete()
dt.Save()
DataTables("表A").Load()
'重新加载表A,看看值是否已经变化
有了这个特性,很多时候,我们不再需要合成Update语句来更新没有加载的后台数据了。
例如要将订购数量超过100的订单的折扣,统一设置为0.05,代码为:
Dim
cmd As
new
SQLCommand
cmd.ConnectionName
= "数据源名称"
Dim
dt As
DataTable
cmd.CommandText =
"Select
[_Identify],折扣
From {订单}
Where
数量
>= 500"
dt =
cmd.ExecuteReader(True)
'记得将参数设置为True
For Each
dr
As
DataRow
In
dt.DataRows
dr("折扣")
=
0.05
Next
dt.Save()
提示:
1、Select语句只加载需要的列,这样可以提高运行速度。
2、如果只选择部分列,那么必须包括主键列,否则保存的时候会出错!
示例六
通过ExecuteReader生成的表也可以增加数据并保存。
如果生成的表仅用于增加数据,那么就没有必要加载数据,生成一个空表即可,例如:
Dim
cmd As
new
SQLCommand
cmd.ConnectionName
= "数据源名称"
Dim
dt As
DataTable
cmd.CommandText
= "Select * From {表A} Where [_Identify] Is null"
'生成空表
dt =
cmd.ExecuteReader(True)
'记得将参数设置为True
Dim
dr As
DataRow = dt.AddNew()
dr("第一列")
= "Foxtable"
dt.Save()
DataTables("表A").Load()
'重新加载表A,看看值是否已经变化
假定出库表和出库明细表通过出库单编号建立关联,下面的代码演示了如何不用SQL语句直接在后台增加一个出库单及对应的两条出库明细:
Dim
cmd As
new
SQLCommand
cmd.ConnectionName
= "数据源名称"
Dim
ckd As
DataTable
Dim
ckmx As
DataTable
cmd.CommandText
= "Select * From {出库} Where [_Identify] Is null"
'生成一个空出库表
ckd =
cmd.ExecuteReader(True)
'记得将参数设置为True
Dim
dr As
DataRow = ckd.AddNew()
'增加出库单
dr("出库日期")
= Date.today
dr("出库单编号")
= "2020-0517-101"
cmd.CommandText
= "Select * From {出库明细} Where [_Identify] Is null"
'生成空出库明细表
ckmx =
cmd.ExecuteReader(True)
'记得将参数设置为True
dr =
ckmx.AddNew()
'增加一个出库明细
dr("出库单编号")
= "2020-0517-101"
dr("商品代码")
= "HC00101"
dr("数量")
= 50
dr =
ckmx.AddNew()
'再增加一个出库明细
dr("出库单编号")
= "2020-0517-101"
dr("商品代码")
= "HC00102"
dr("数量")
= 100
ckd.Save()
ckmx.Save()
示例七
假定出库表的主键是出库单号列,而且是自动增量型,那么上述代码是无法正常运行的,因为作为自动增量列,出库单编号是由系统自动生成的,而且是在保存之后生成。
所以我们在保存出库单之后,必须想办法获取自动生成的出库单编号,并赋值给随后新增的出库单明细的出库单编号列,否则二者之间将失去关联。
Foxtable处理这种问题非常简单,因为每次保存新增行之后,Foxtable都会自动访问后台数据库,获取新增行的主键值并写入到主键列中。
修改后的代码如下,留意加粗显示的代码:
Dim
cmd As
new SQLCommand
cmd.ConnectionName
= "orders"
Dim
ckd As
DataTable
Dim
ckmx As
DataTable
cmd.CommandText
= "Select * From {出库}
Where [出库单编号]
Is null"
'生成一个空出库表
ckd =
cmd.ExecuteReader(True)
'记得将参数设置为True
Dim
cr As
DataRow = ckd.AddNew()
'增加出库单
cr("出库日期")
= Date.today
cr("库管员")
= "张三"
ckd.Save()
'必须提前保存出库单,以获取自动生成的出库单编号.
cmd.CommandText
= "Select * From {出库明细} Where [出库单编号] Is null"
'生成空出库明细表
ckmx =
cmd.ExecuteReader(True)
'记得将参数设置为True
Dim
mr As
DataRow = ckmx.AddNew()
'增加一个出库明细
mr("出库单编号")
= cr("出库单编号")
'将自动生成的出库单编号赋值后新增的出库明细.
mr("商品代码")
= "HC00101"
mr("数量")
= 50
mr =
ckmx.AddNew()
'再增加一个出库明细
mr("出库单编号")
= cr("出库单编号")
'将自动生成的出库单编号赋值后新增的出库明细.
mr("商品代码")
= "HC00102"
mr("数量")
= 100
ckd.Save()
ckmx.Save()