delphi 中对 ms ado 的封装 SQL 的几点疑问

[复制链接]
查看11 | 回复8 | 2005-7-16 18:49:11 | 显示全部楼层 |阅读模式
[php]
环境如下:
window2000 professional
oracle 9.2.0.1
delphi 6
-- 建表
create table t1
( f1 varchar2(100)
);
insert into t1 (f1) values ('0');
commit;

procedure TForm1.Button1Click(Sender: TObject);
var
sSQL: string;
begin
// 1 不成功
// ORA-00911: invalid character
and is unable to recognize the comment.
sSQL :=
' update t1 set f1 = ''1 delphi''; ';
try
prExecSQL(sSQL);
except
MessageDlg('Error', mtError, [mbOK], 0);
end;
// 2 成功
sSQL :=
' update t1 set f1 = ''2 delphi'' ';
try
prExecSQL(sSQL);
except
MessageDlg('Error', mtError, [mbOK], 0);
end;
// 3 成功
sSQL :=
' begin ' +
' update t1 set f1 = ''3 delphi''; ' +
' commit; ' +
' end; ';
try
prExecSQL(sSQL);
except
MessageDlg('Error', mtError, [mbOK], 0);
end;
// 4 成功
sSQL :=
' update t1 set f1 = ''4 delphi'' ';
if not ADOConnection1.InTransaction then ADOConnection1.BeginTrans;
try
prExecSQL(sSQL);
ADOConnection1.CommitTrans;
except
ADOConnection1.RollbackTrans;
MessageDlg('Error', mtError, [mbOK], 0);
end;
end;
procedure TForm1.prExecSQL(aSQL: string);
begin
with ADOQuery1 do
begin
Close;
SQL.Clear;
SQL.Add(aSQL);
ExecSQL;
end;
end;
[/php]

疑问 1
为什么第一组语句多了一个分号就不能执行呢?
而在 sqlplus 中执行是可以的?

疑问 2

如果在 sqlplus 中
进程 1:
update t1 set f1 = 'test 1';
commit;
update t1 set f1 = 'test 2';
进程 2:
select * from t1;
如果第一个进程最后的语句不 commit,进程 2 读取是 'test 1'
第 2 组的语句并没有调用提交,但是此时在 sqlplus 读取出来的是 '2 delphi' 了

如果是这样的话,一定通过某种方式调用了 commit,这个是如何调用的呢?
通过什么方法能知道,这个语句由 ado 封装后,到了 oracle 中是什么样子的?
如果可以知道的话,我想分析一下语句2、3、4在oracle里都干了什么
回复

使用道具 举报

千问 | 2005-7-16 18:49:11 | 显示全部楼层
SQLPLUS中的分号是语句的终结符,
不要还不行,在ADODATASET中,却没有这个习惯的。
回复

使用道具 举报

千问 | 2005-7-16 18:49:11 | 显示全部楼层
最初由 xzh2000 发布
[B]SQLPLUS中的分号是语句的终结符,
不要还不行,在ADODATASET中,却没有这个习惯的。 [/B]


但是加了begin end后,如上边的第3组语句,没有分号反而不行。真是莫名其妙。
回复

使用道具 举报

千问 | 2005-7-16 18:49:11 | 显示全部楼层
对 oracle 不是很熟悉,发表一点看法,如果有错误,敬请谅解

疑问 2

如果在 sqlplus 中
进程 1:
update t1 set f1 = 'test 1';
commit;
update t1 set f1 = 'test 2';
进程 2:
select * from t1;
如果第一个进程最后的语句不 commit,进程 2 读取是 'test 1'
第 2 组的语句并没有调用提交,但是此时在 sqlplus 读取出来的是 '2 delphi' 了
====================================================
如果是同一个进程,读取的应该是修改后的数据,而没有提交时,其他进程读的应该是 rollback segment 中的数据before image
====================================================
如果是这样的话,一定通过某种方式调用了 commit,这个是如何调用的呢?
====================================================
按照以上的解释 这里应该是没有commit 的
====================================================
这个跟 ADO 的关系应该不是很大,是oracle 的机制问题
这跟 mssql 不一样



但是加了begin end后,如上边的第3组语句,没有分号反而不行。真是莫名其妙。
=======================================
加 begin end 以后,该程序变成 plsql 的匿名存储过程,
这样数据库那边的执行引擎就变成 plsql 引擎
而不是 sql 引擎了
========================================
回复

使用道具 举报

千问 | 2005-7-16 18:49:11 | 显示全部楼层
最初由 花好月不圆 发布
[B]加 begin end 以后,该程序变成 plsql 的匿名存储过程,
这样数据库那边的执行引擎就变成 plsql 引擎
而不是 sql 引擎了
[/B]

原来是这样啊。
回复

使用道具 举报

千问 | 2005-7-16 18:49:11 | 显示全部楼层
如果在 sqlplus 中
进程 1:
update t1 set f1 = 'test 1';
commit;
update t1 set f1 = 'test 2';
进程 2:
select * from t1;
如果第一个进程最后的语句不 commit,进程 2 读取是 'test 1'

这一点可以用这个解释:如果是同一个进程,读取的应该是修改后的数据,而没有提交时,其他进程读的应该是 rollback segment 中的数据before image

但是如果装将进程1由 sqlplus 换成 delphi,进程2 还是 sqlplus
在 delphi 中执行
// 2 成功
sSQL :=
' update t1 set f1 = ''2 delphi'' ';
try
prExecSQL(sSQL);
except
MessageDlg('Error', mtError, [mbOK], 0);
end;
依照上边的理伦,由于 delphi 中执行的语句没有调用 commit。sqlplus 进程2 读取的应该是before image。数值应该是 '1 delphi'。而实际中读取的却是 '2 delphi'
回复

使用道具 举报

千问 | 2005-7-16 18:49:11 | 显示全部楼层
chuun 好象很熟悉啊?
是不是头像不见了
回复

使用道具 举报

千问 | 2005-7-16 18:49:11 | 显示全部楼层
这是 因为 delphi 可能将事务模式设置为 autocommit
在 sqlplus 中也可以设置,如果在 sqlplus 中设置 自动提交
那么你不写commit 结果会立即改变的


回复

使用道具 举报

千问 | 2005-7-16 18:49:11 | 显示全部楼层
花兄,以前你回答了我好多 sybase 的问题。
比如:怎么清空 sybase 11.5 sa 的口令,及一些 bcp 的相关问题。
等找到一个有个性的图片再用logo。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行