关于VB.Net的问题
问题
1.如何实现每日一贴的那中效果,能否给点代码!
2.如何建触发器??
问题点数:100、回复次数:6Top
1 楼rickjelly2004(每逢佳节倍思亲-------------快乐生活)回复于 2004-09-03 12:37:30 得分 25
在VB中使用INI文件实现每日一贴对话框
每当我们打开像金山词霸等一些软件时,会弹出来一个“每日一帖”的对话框,或者显示一条小技巧,或者是对本软件的介绍等等,总之会给人一种亲切的感觉。那么你是不是也想在自己编的程序中实现这种功能呢?OK!Follow me!
首先新建一个工程文件,添加一个模块,两个窗体。窗体分别命名为frmMain和frmTips。在frmMain中添加一个按钮,双击并输入如下代码:
Private Sub cmdOK_Click()
Unload Me
End Sub
在frmTips窗体上添加如下控件:三个按钮,分别命名为:cmdOk、cmdPreTip和cmdNextTip,Caption值依次设为:“确定”,“上一个”和“下一个”(为了使程序更直观,笔者在cmdOk按钮上应用了一张图片,见图1)。、两个复选框,名字(Caption)分别为:chkIfTips(在启动时显示(&S))和chkIfRnd(随机(&S)),再添加一个label,命名为:lblTipText,用来显示提示作息,另外再添加一个picturebox作为背景,一个label作为标题,最终设计好的效果如图所示。
然后再添加一个模块,在其中输入以下代码:
Option Explicit
Public TipFileName As String '提示信息文件
Public INIFileName As String '用户配置文件名
'以下两条API函数的声明,笔者建议从VB自带的API浏览器中复制,要不然,如果有一个字母写错,程序就不能正确运行了!
Public Declare Function GetPrivateProfileString Lib "kernel32" Alias _
"GetPrivateProfileStringA" (ByVal lPAPPlicationName As String, ByVal lPKeyName As Any, ByVal lPDefault As String, ByVal lPReturnedString As String, ByVal nSize As Long, ByVal lPFileName As String) As Long
Public Declare Function WritePrivateProfileString Lib _
"kernel32" Alias "WritePrivateProfileStringA" (ByVal lPAPPlicationName As String, ByVal lPKeyName As Any, ByVal lPString As Any, ByVal lPFileName As String) As Long
Sub GetFile()
Dim AppName As String
AppName = App.Path
If Right(AppName, 1) <> "\" Then
AppName = AppName & "\"
End If
TipFileName = AppName & "TIPOFDAY.txt" '请读者朋友事先新建一个文本文件,并和工程文件放在同目录下(这个文件名仅供参考)
INIFileName = AppName & "TIPOFDAY.INI" '这个文件大家不用管,系统会自动建立的
End Sub
Public Function sGetINI(INIFileName As String, sSection As String, sKey As String, sDefault As String) As String
Dim sTemP As String * 256
Dim nLength As Long
sTemP = Space$(256)
nLength = GetPrivateProfileString(sSection, sKey, sDefault, sTemP, 255, INIFileName)
sGetINI = Left$(sTemP, nLength)
End Function
Public Sub writeINI(INIFileName As String, sSection As String, sKey As String, sValue As String)
Dim n As Long
Dim sTemP As String
sTemP = sValue
'用空格替换回车/换行
For n = 1 To Len(sValue)
If Mid$(sValue, n, 1) = vbCr Or Mid$(sValue, n, 1) = vbLf Then
Mid$(sValue, n) = ""
End If
Next n
n = WritePrivateProfileString(sSection, sKey, sTemP, INIFileName)
End Sub
Sub main()
Dim ifStartTips As String
Dim sNumUPPer As String, sNumOneZhu As String
Call GetFile
Load frmMain
ifStartTips = sGetINI(INIFileName, "Others", "ifStartTips ", "YES")
frmMain.Show
If ifStartTips = "YES" Then
frmTip.Show vbModal, frmMain
frmTip.chkIfTips.Value = vbChecked
End If
End Sub
再在frmTip中添加如下代码:
Option Explicit
' 内存中的提示数据库。
Dim Tips As New Collection
' 提示文件名称
Const Tip_FILE = "TipOFDAY.TXT"
' 当前正在显示的提示集合的索引。
Dim CurrentTip As Long, ifNext As Boolean
Private Sub DoNextTip()
If chkIfRnd.Value = vbChecked Then
'随机选择一条提示。
CurrentTip = Int((Tips.Count * Rnd) + 1)
Else
'或者,您可以按顺序遍历提示
CurrentTip = CurrentTip + 1
If Tips.Count < CurrentTip Then
CurrentTip = 1
End If
End If
'显示它。
Call frmTip.DisPlayCurrentTip
End Sub
Private Sub DoPreTip()
If chkIfRnd.Value = vbChecked Then
'随机选择一条提示。
CurrentTip = Int((Tips.Count * Rnd) + 1)
Else
'或者,您可以按顺序遍历提示
CurrentTip = CurrentTip - 1
If CurrentTip < 1 Then
CurrentTip = Tips.Count
End If
End If
'显示它。
Call frmTip.DisPlayCurrentTip
End Sub
Function LoadTips(sFile As String) As Boolean
Dim NextTip As String ' 从文件中读出的每条提示。
Dim InFile As Long ' 文件的描述符。
' 包含下一个自由文件描述符。
InFile = FreeFile()
' 确定为指定文件。
If sFile = "" Then
LoadTips = False
Exit Function
End If
' 在打开前确保文件存在。
If Dir(sFile) = "" Then
LoadTips = False
Exit Function
End If
' 从文本文件中读取集合。
Open sFile For Input As InFile
While Not EOF(InFile)
Line Input #InFile, NextTip
Tips.Add NextTip
Wend
Close InFile
' 显示一条提示。
DoNextTip
LoadTips = True
End Function
Private Sub chkIfRnd_Click()
Dim ifRndShow As String
' 保存在下次启动时是否随机显示提示信息
ifRndShow = IIf(chkIfRnd.Value = vbChecked, "YES", "NO")
Call writeINI(INIFileName, "Others", "ifRndShow ", ifRndShow)
End Sub
Private Sub chkIfTips_Click()
Dim ifStartTips As String
' 保存在下次启动时是否显示此窗体
ifStartTips = IIf(chkIfTips.Value = 1, "YES", "NO")
Call writeINI(INIFileName, "Others", "ifStartTips ", ifStartTips)
End Sub
Private Sub cmdNextTip_Click()
ifNext = True
Call DoNextTip
End Sub
Private Sub cmdOK_Click()
Unload Me
End Sub
Private Sub cmdPreTip_Click()
ifNext = False
Call DoPreTip
End Sub
Private Sub Form_Load()
Dim ifStartTips As String, ifRndShow As String
' 察看在启动时是否显示提示信息
ifStartTips = sGetINI(INIFileName, "Others", "ifStartTips ", "?")
If ifStartTips = "?" Then
ifStartTips = "YES"
Call writeINI(INIFileName, "Others", "ifStartTips ", ifStartTips)
End If
' 设置复选框
chkIfTips.Value = IIf(ifStartTips = "NO", vbUnchecked, vbChecked)
' 察看在显示时是否随机显示
ifRndShow = sGetINI(INIFileName, "Others", "ifRndShow ", "?")
If ifRndShow = "?" Then
ifRndShow = "YES"
Call writeINI(INIFileName, "Others", "ifRndShow ", ifRndShow)
End If
' 设置复选框
chkIfRnd.Value = IIf(ifRndShow = "NO", vbUnchecked, vbChecked)
' 随机寻找
ifNext = True
Randomize
' 读取提示文件并且随机显示一条提示。
If LoadTips(TipFileName) = False Then
lblTipText.Caption = "文件 " & Tip_FILE & " 没有被找到!"
End If
End Sub
Public Sub DisPlayCurrentTip()
If Tips.Count > 0 Then
If Tips.Item(CurrentTip) = "" Then
If ifNext = True Then
Call DoNextTip
Else
Call DoPreTip
End If
End If
lblTipText.Caption = Tips.Item(CurrentTip)
End If
End Sub
Top
2 楼rickjelly2004(每逢佳节倍思亲-------------快乐生活)回复于 2004-09-03 12:38:16 得分 25
一 触发器介绍
触发器是一种特殊的存储过程,它在插入,删除或修改特定表中
的数据时触发执行,它比数据库本身标准的功能有更精细和更复杂的
数据控制能力。数据库触发器有以下的作用:
* 安全性。可以基于数据库的值使用户具有操作数据库的某种权
利。
# 可以基于时间限制用户的操作,例如不允许下班后和节假日
修改数据库数据。
# 可以基于数据库中的数据限制用户的操作,例如不允许股票
的价格的升幅一次超过10%。
* 审计。可以跟踪用户对数据库的操作。
# 审计用户操作数据库的语句。
# 把用户对数据库的更新写入审计表。
* 实现复杂的数据完整性规则。
# 实现非标准的数据完整性检查和约束。触发器可产生比规则
更为复杂的限制。与规则不同,触发器可以引用列或数据库对
象。例如,触发器可回退任何企图吃进超过自己保证金的期货。
# 提供可变的缺省值。
* 实现复杂的非标准的数据库相关完整性规则。触发器可以对数
据库中相关的表进行连环更新。例如,在auths表author_code列上的
删除触发器可导致相应删除在其它表中的与之匹配的行。
# 在修改或删除时级联修改或删除其它表中的与之匹配的行。
# 在修改或删除时把其它表中的与之匹配的行设成NULL值。
# 在修改或删除时把其它表中的与之匹配的行级联设成缺省值。
# 触发器能够拒绝或回退那些破坏相关完整性的变化,取消试
图进行数据更新的事务。当插入一个与其主健不匹配的外部键
时,这种触发器会起作用。例如,可以在books.author_code
列上生成一个插入触发器,如果新值与auths.author_code列
中的某值不匹配时,插入被回退。
* 同步实时地复制表中的数据。
* 自动计算数据值,如果数据的值达到了一定的要求,则进行特
定的处理。例如,如果公司的帐号上的资金低于5万元则立即给财务人
员发送警告数据。
ORACLE与SYBASE数据库的触发器有一定的区别,下面将分别讲述
这两种数据库触发器的作用和写法。
二 ORACLE 触发器
ORACLE产生数据库触发器的语法为:
create [or replace] trigger 触发器名 触发时间 触发事件
on 表名
[for each row]
pl/sql 语句
其中:
触发器名:触发器对象的名称。由于触发器是数据库自动执行
的,因此该名称只是一个名称,没有实质的用途。
触发时间:指明触发器何时执行,该值可取:
before---表示在数据库动作之前触发器执行;
after---表示在数据库动作之后出发器执行。
触发事件:指明哪些数据库动作会触发此触发器:
insert:数据库插入会触发此触发器;
update:数据库修改会触发此触发器;
delete:数据库删除会触发此触发器。
表 名:数据库触发器所在的表。
for each row:对表的每一行触发器执行一次。如果没有这一
选项,则只对整个表执行一次。
举例:下面的触发器在更新表auths之前触发,目的是不允许在
周末修改表:
create trigger auth_secure
before insert or update or delete //对整表更新前触发
on auths
begin
if(to_char(sysdate,'DY')='SUN'
RAISE_APPLICATION_ERROR(-20600,'不能在周末修改表auths');
end if;
end
三 SYBASE数据库触发器
SYBASE数据库触发器的作用与ORACLE非常类似,仅有较小的差异。
SYBASE产生触发器的语法为:
CREATE TRIGGER 触发器名
ON 表名
FOR INSERT,UPDATE,DELETE
AS
SQL_statement |
FOR INSERT,UPDATE
AS
IF UPDATE(column_name) [AND|OR UPDATE(column_name)]...
SQL_statements
上面FOR子句用来指定在触发器上的哪些数据更新命令可激活该
触发器。IF UPDATE子句检查对指定列的操作类型,在IF UPDATE子句
中可指定多个列。
与ORACLE不同,对于每条SQL语句,触发器只执行一次。触发器
在数据更新语句完成以后立即执行。触发器和启动它的语句被当作一
个事务处理,事务可以在触发器中回退。
下面举例说明SYBASE触发器的写法。
create trigger forinsert_books
on books
for insert
as
if(select count(*) from auths,inserted
where auths.author_code=insert.author_code)!=@@rowcount
begin
rollback transaction
print "books 表中 author_code 列的值在auths 表中不存在。"
end
Top
3 楼rickjelly2004(每逢佳节倍思亲-------------快乐生活)回复于 2004-09-03 12:38:40 得分 25
触发器设计技巧与实例
在数据库设计中,有两种方法可设定自动化的资料处理规则,一种是条件约束,
一种是触发器,一般而言,条件约束比触发器较容易设定及维护,且执行效率较
好,但条件约束只能对资料进行简单的栏位检核,当涉及到多表操作等复杂操
作时,就要用到触发器了.
一个数据库系统中有两个虚拟表用于存储在表中记录改动的信息,分别
是:
虚拟表Inserted 虚拟表Deleted
在表记录新增时 存放新增的记录 不存储记录
修改时 存放用来更新的新记录 存放更新前的记录
删除时 不存储记录 存放被删除的记录
触发器的种类及触发时机
After触发器:触发时机在资料已变动完成后,它将对变动资料进行必要的
善后与处理,若发现有错误,则用事务回滚(Rollback Transaction)
将此次操作所更动的资料全部回复。
Istead of 触发器:触发时机在资料变动前发生,且资料如何变动取决于触发器
现在介绍一下创建触发器的编写格式:
After类型:
Create Trigger 触发器名称
on 表名
after 操作(insert,update)
as
Sql语句
Instead类型
Create Trigger 触发器名称
on 表名
Instead of 操作(update,delete)
as
Sql语句
实例1:
在订单(表orders)中的订购数量(列名为num)有变动时,触发器会先到客户(表Customer)中
取得该用户的信用等级(列名为Level),然后再到信用额度(Creit)中取出该等级
许可的订购数量上下限,最后比较订单中的订购数量是否符合限制。
代码:
Create Trigger num_check
on orders
after insert,update
as
if update(num)
begin
if exists(select a.* from orders a join customer b on a.customerid=b.customerid
join creit c on b.level=c.level
where a.num between c.up and c.down)
begin
rollback transaction
exec master..xp_sendmail 'administrator','客户的订购数量不符合限制'
end
end
实例2:
有工资管理系统中,当公司对某员工甲的月薪进行调整时,通常会先在表员工中修改薪资列,然后在
表员工记录中修改薪资调整时间与薪资
Create trigger compensation
on 员工
after update
as
if @@rowcount=0 return
if update(薪资)
begin
insert 员工记录
select 员工遍号,薪资,getdate()
from inserted
end
Top
4 楼ryx1984ryx(做最好的禽兽)回复于 2004-09-03 12:42:10 得分 0
谢谢了Top
5 楼rickjelly2004(每逢佳节倍思亲-------------快乐生活)回复于 2004-09-03 12:42:24 得分 25
--即时同步两个表的实例:
--测试环境:SQL2000,远程主机名:xz,用户名:sa,密码:无,数据库名:test
--创建测试表,不能用标识列做主键,因为不能进行正常更新
--在本机上创建测试表,远程主机上也要做同样的建表操作,只是不写触发器
if exists (select * from dbo.sysobjects where id = object_id(N'[test]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [test]
create table test(id int not null constraint PK_test primary key
,name varchar(10))
go
--创建同步的触发器
create trigger t_test on test
for insert,update,delete
as
set XACT_ABORT on
--启动远程服务器的MSDTC服务
exec master..xp_cmdshell 'isql /S"xz" /U"sa" /P"" /q"exec master..xp_cmdshell ''net start msdtc'',no_output"',no_output
--启动本机的MSDTC服务
exec master..xp_cmdshell 'net start msdtc',no_output
--进行分布事务处理,如果表用标识列做主键,用下面的方法
BEGIN DISTRIBUTED TRANSACTION
delete from openrowset('sqloledb','xz';'sa';'',test.dbo.test)
where id in(select id from deleted)
insert into openrowset('sqloledb','xz';'sa';'',test.dbo.test)
select * from inserted
commit tran
go
--插入数据测试
insert into test
select 1,'aa'
union all select 2,'bb'
union all select 3,'c'
union all select 4,'dd'
union all select 5,'ab'
union all select 6,'bc'
union all select 7,'ddd'
--删除数据测试
delete from test where id in(1,4,6)
--更新数据测试
update test set name=name+'_123' where id in(3,5)
--显示测试的结果
select * from test a full join
openrowset('sqloledb','xz';'sa';'',test.dbo.test) b on a.id=b.id
Top
6 楼njhyh(小辉)回复于 2004-09-03 12:44:57 得分 0
好贴!收藏!Top




