***************SQL2K,D6 C/S 我想这样,当某用户修改数据时,锁定该记录,当另一用户试图修改该记录时,则向试图修改该记录的用

  • 主题发起人 主题发起人 蛐蛐
  • 开始时间 开始时间
十分关注????
 
为什么总是抱着Foxpro编程方法处理问题呢?
你用什么语言,就怎么样处理。对于数据库并行操作,只要是Delphi编程的书都有相应
的解决办法。
你要求的方法,不符合C/S结构的处理要求。
 
悲观锁定法并不常用,以内它让系统性能大为降低,象你所说的,如果一个用户在更改,
那么其他用户得到“正在修改。。。”的信息,那么如果这个用户去干别的了,那么是
否其他人都要一直等下去呢?那么这个记录就一直别锁着!这是相当低级的想法!
 
我觉得用trigger或者StoreProcedure要好些.

另外, 关注.
 
虽然悲观锁对系统性能影响极大,但实际上也有这种需求的。
谁也不想辛苦修改完的数据到了存盘时才发现保存不了。
 
请看如下代码
function Tdm.TranNoProtection(TranNozz:string):boolean;
var
TranNoProtectionquery1:TZMysqlquery;
TranNoName:string;
begin
if TranNozz='' then ReSult:=true;
TranNoName:=TranNozz;
TranNoProtectionQuery1:=TZMysqlQuery.Create(nil);
with TranNoProtectionQuery1 do begin
TranNoProtectionQuery1.Database:=dm.ZMySqlDatabase1;
TranNoProtectionQuery1.Transaction :=dm.ZMySqlTransact1;
SQl.Clear;
SQL.Add('select * from trannoprotection where TranNo=:var1');
ParamByName('Var1').value:=TranNoName;
Active:=True;
end;
if TranNoProtectionQuery1.eof and TranNoProtectionQuery1.bof then
begin
ReSult:=true;
//save date
end
else
begin
if (abs(strtofloat(formatdatetime('hh',now))-strtofloat(formatdatetime('hh',TranNoProtectionQuery1.fieldbyname('date1').asdatetime)))>1 ) then
begin
ReSult:=true
end
else
begin
ReSult:=false
end;
end
end;

procedure Tdm.SaveTranNoProtection( TranNozz:string );
var
TranNoName:string;
begin
if TranNozz='' then Exit;
TranNoName:= TranNozz;
dm.tbTranNoProtection.open;
DM.tbTranNoProtection.append;
dm.tbTranNoProtection.fieldbyname('TranNo').asstring:= TranNoName ;
dm.tbTranNoProtection.fieldbyname('date1').asdatetime:=now;
CommitData(DM.tbTranNoProtection);
end ;

procedure TDM.DeleteTranNoProtection(TranlNozz:string );
var
TranNoProtectionquery100:TZMysqlquery;
TranlNoName:string;
begin
if TranlNozz='' then exit;
TranNoProtectionquery100:=TZMysqlquery.CREATE(NIL) ;
TranlNoName:=TranlNozz;
TranNoProtectionquery100.Database:=dm.ZMySqlDatabase1;
TranNoProtectionquery100.Transaction:=dm.ZMySqlTransact1;
TranNoProtectionquery100.SQL.Add('DELETE FROM trannoprotection WHERE TranNo=:VAR1') ;
TranNoProtectionQUERY100.ParamByName('VAR1').value:=TranlNozz;
TranNoProtectionquery100.ExecSQL ;
TranNoProtectionquery100.Close ;
TranNoProtectionquery100.Free;
end;

在修改时调用的,每张单或都每个记录都有他的关键字,把关键字写进
function Tfrmoutfinished.RecordProtection:boolean;
begin
if DM.TranNoProtection(dbedit2.text) then
begin
DM.SaveTranNoProtection(dbedit2.text);
Result := False;
end
else
begin
MessageDlg(Msg5, mtInformation, [mbYes, mbNo], 0);
Result := True;
end;
end;

在close时
if (KK=False) and (EditorAppend=2) then
dm.deleteTranNoProtection(DBEdit2.text);
kk:boolean;用于记录它是什么状态。


加分!我要加分



 
mark_yjh,如果可以,加你60分。
 
象这种问题dbms早就都考虑到了,它们的手段肯定比我们在这想的要可靠、性能要好的多
那为什么不去看看呢!
 
记得我曾经建议你用Context_info,为何不用,它是SQL 2000 专门用来在应用程序会话间
共享信息用的。
当要锁定某一功能时,首先查询是否有 特定的Context_info(将用户信息编码进去),
如没有,则设置它,执行完清0。
如果设置特定Context_info的用户非法非法退出,则该会话自动退出,不用手工解锁。

以下是SQL2000相关帮助信息:

会话上下文信息
Microsoft? SQL Server? 2000 引入了编程能力,可将最多 128 字节的二进制信息与当前会话或连接关联起来。会话上下文信息使应用程序得以设置二进制值,以便在同一会话或连接上运行的多个批处理、存储过程、触发器或用户定义函数中加以引用。可使用新的 SET CONTEXT_INFO 语句设置会话上下文,然后从 master.dbo.sysprocesses 表的新 context_info 列中检索上下文字符串。

会话上下文信息不同于 Transact-SQL 变量,后者的作用域局限于当前的批处理、存储过程、触发器或函数。而会话上下文信息可用于存储每个用户或应用程序当前状态所特有的信息,这些信息随后可用于控制 Transact-SQL 语句中的逻辑。

SET CONTEXT_INFO 语句支持:

最多 128 字节的常量,可以是二进制或是可隐性转换为二进制的数据类型。


varbinary(128) 或 binary(128) 变量的名称。
不能在用户定义函数中指定 SET CONTEXT_INFO。因为用来存储信息的 sysprocesses 表不允许空值,所以不能给 SET CONTEXT_INFO 提供空值。

若要获得当前连接的当前会话上下文,请从 SQL Server 进程 ID (SPID) 与连接 SPID 相等的 master.dbo.sysprocesses 行中选择 context_info 列。当前连接的 SPID 由 @@SPID 函数返回:

SELECT context_info
FROM master.dbo.sysprocesses
WHERE spid = @@SPID

如果还没有对当前连接执行 SET CONTEXT_INFO,则 context_info 列中的值将初始化为 128 字节的二进制零。如果已执行 SET CONTEXT_INFO,context_info 列将包含由当前连接最后执行的 SET CONTEXT_INFO 设置的值。context_info 列是 varbinary(128) 列。

以下是使用会话上下文信息的示例:

-- Set context information at start.
SET CONTEXT_INFO 0x1256698456
GO
-- Perform several non-related batches.
sp_who
GO
USE Northwind
GO
SELECT CustomerID
FROM Customers
WHERE City = 'London'
GO
-- Select context information set several batches earlier.
SELECT context_info
FROM master.dbo.sysprocesses
WHERE spid = @@spid
GO

SET CONTEXT_INFO 不支持引用常量或变量名以外的表达式,如函数。如果需要将上下文信息设置为函数调用结果,必须先在 binary 或 varbinary 变量中放置函数调用结果:

DECLARE @BinVar varbinary(128)
SET @BinVar = CAST( REPLICATE( 0x20, 128 ) AS varbinary(128) )
SET CONTEXT_INFO @BinVar


请参见

SET CONTEXT_INFO

sysprocesses

 
大系统通常都是批量更新的,在用户编辑的时候,并没有提交给数据库,数据库中
不会有更新锁,甚至不会保持共享锁,因为用户正在编辑的数据是用SELECT读出来的。
这时候是有必要在程序中自己处理这个情况,给试图编辑该记录的用户一个通知。以免在提交
的时候发生问题。这与数据库内置记录锁定是两回事。
从人性化的角度来说,毕竟“谁也不想辛苦修改完的数据到了存盘时才发现保存不了”
 
to softdog
在delphi 与sql 连接中怎样设置,进行‘脏读’
 
to zhengyue:
select id from LockInfo where LockTable=@LockTable and LockRecID=@LockRecID with nolock
~~~~~~~~~~~
加with nolock关键字就是脏读了
 
看了许多人的解决办法,我是这样做的,

用edit 替换掉dbedit, 这样做把系统的锁定时间最小,
只在提交的那一刻用事务控制提交。 不是一进窗体就 adoconnection.beginstran
是在button里做的。
try
adoconnection.beginstran;
adoquery1.append;
...
adoquery1.post;
adoconnection.comm...;
except
adoconnection.rollback;
showmessage('error';
end;

其次就是用临时表解决这个问题,
或许我用的是笨方法,但可以解决问题,
把要修改的数据修改前存入临时表,修改后和临时表对比,如果此时和临时表对比不相等
就提示其它有户已经修改过, 如果没有则开启事务,提交数据,完成提交
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部