这个错误信息是什么意思? 300分(300分)

  • 主题发起人 主题发起人 cAkk
  • 开始时间 开始时间
C

cAkk

Unregistered / Unconfirmed
GUEST, unregistred user!
Project dce.exe raised exception class EODBCError with message
'ODBC32 error ODBC32 error HY000: [Microsoft][ODBC SQL Server
Driver]Connection is busy with results for another hstmt
: [Microsoft][ODBC SQL Server Driver]Connection is busy with
results for another hstmt
'. Process stopped. Use Step or Run to continue.

使用ODBC98连接Sql Server 7.0数据库,执行以下操作时发生上面的错误:
tqen:=todbcquery.Create(nil);
tqen.database:=ODBC1;
tqen.sql.clear;
tqen.SQL.add('UPDATE dce_account SET aname=:an WHERE ano=:ao');
tqen.Prepare;

tqe0:=todbcquery.Create(nil);
tqe0.database:=odbc1;
tqe0.sql.clear;
tqe0.SQL.add('INSERT INTO dce_account (ano,aname) VALUES (:ao,:an)');
tqe0.Prepare;

tqe1:=todbcquery.Create(nil);
tqe1.database:=odbc1;
tqe1.sql.clear;
tqe1.SQL.add('SELECT ano,aname FROM dce_account WHERE ano=:ao');
tqe1.Prepare; //开始出错

多谢!!
 
我认为是tqen与tqe1在Prepare时,MsSQL锁定冲突造成的....
 
怎么解决?
 
首先说明:我是猜测,不一定对。

先update,再Commit释放锁。再Select.
 
为什么tqen,tqen0在Prepare之后不ExecSQL或Open?
我以前用的BDE也会出现类似错误,将tqe1之前用到的Query,StoredProcedure都
UnPrepare试试看,我就是这么解决的
 
在 tqe1:=todbcquery.Create(nil); 前加句

odbc1.Connected:=false;
 
to 沈前卫,xwolf: 我的这些sql语句在后面将会在一个循环里面重复多次使用,
所以不能先ExecSQL,或者UnPrepare

to gxg8816: 我明天到公司试一试. 能说说为什么这样做吗?
 
to gxg8816:
你这样并不好,odbc1.Connected:=false后; 那cAkk在这个代码前的所有努力都
白费了。HeHe.....如果是在循环中就更不能odbc1.Connected:=false,否则效率
特低,
 
我倒觉得要放一个 odbc1.Connected:= TRUE 去最前面
 
我想知道"为什么这样做"或"为什么不这样做"?
 
如果按gxg8816那样,每次你Active Query时,odbc1.Connected:= TRUE 都回执行
一次,放在循环中更是浪费机时。并且你的Prepare丝毫没有起作用。
 
这样:把所有的Prepare放在最后,并且tqe1 要先Prepare;

tqe1.Prepare;
tqen.Prepare;
tqe0.Prepare;
 
这个错误信息里面的"hstmt"到底是个什么东西? 他在ODBC里面充当什么角色?

因为我发现在ODBC Express控件里面专门有一个hstmt控件,不知道有什么用?
 
错误号: HY000 Connection is busy with results for another hstmt.
描述: The SQL Server ODBC driver allows only one active hstmt.
hstmt是语句句柄.
当使用默认的结果集时:
SQL Server ODBC driver 只允许一个活动的hstmt,

Default result sets can be used for any SQL statement supported by
SQL Server, and are the most efficient method of transferring an
entire result set to the client.

Default result sets do not support multiple active statements on the
same connection. After an SQL statement is executed on a connection,
the server does not accept commands (except a request to cancel the
rest of the result set) from the client on that connection until all
the rows in the result set have been processed. To cancel the
remainder of a partially processed result set, call SQLCloseCursor or
SQLFreeStmt with the fOption parameter set to SQL_CLOSE. To finish a
partially processed result set and test for the presence of another
result set, call SQLMoreResults. If an ODBC application attempts a
command on a connection handle before a default result set has been
completely processed, the call generates SQL_ERROR

上面是SQL手册中的一段话.

我的试验结果如下:
三个 select 没问题.
先 select 再 insert 没问题.
两个insert不行,
先 insert 再 select 不行.
看来是insert占用了结果集.

还有一个解决方法是:
建立多个connection,就是多建几个 odbcdatabase




 
SQLPrepare 函数原型:
SQLRETURN SQLPrepare(
SQLHSTMT StatementHandle,
SQLCHAR* StatementText,
SQLINTEGER TextLength
)
StatementHandle 为有效语句句柄,就是上面提示信息中的 hstmt
 
我的第一个方法不行,虽然运行通过,但
断开连接时,ODBC Driver调用 SQLDisconnect 函数,这个函数会释放该连接的所有
语句句柄.
odbcquery 的 execSql调用下面的函数:

SQLRETURN SQLexecute(
SQLHSTMT StatementHandle
)
或者
SQLRETURN SQLExecdirect(
SQLHSTMT StatementHandle,
SQLCHAR* StatementText,
SQLINTEGER TextLength
)
句柄释放后,prepare就没用了.



 
那么到底怎样解决呀!急死了!
 
解决方法不是已经说了吗?
1: insert 语句最后 prepare

tqe1.Prepare;
tqen.Prepare;
tqe0.Prepare;

2: 建立新的连接 odbcdatabase2,
tqe1.database:=odbcdatabase2;

3: 最好的办法
既然这三个查询要反复调用,把他们写成 存储过程,放在服务器上,效率最高.
其实,再SQL6.5时, prepare 的过程就是建立临时存储过程.
 
to gxg8816:
1. 没试过。
2。用两个odbcdatabase2会不会造成程序死锁?
3。用存储过程,Delphi参与的能力降低。

我认为:
tqe1.SQL.add('SELECT ano,aname FROM dce_account WHERE ano=:ao');
不要Prepare,当UPdate,Insert完成后用commit 或Rollbak释放锁后再select.
select使用完毕后将tqe1.Active:=False;再处理update,insert。如此循环。
这样,只有Select没有prepare而效率稍有降低。Update与Insert效率不变。
 
后退
顶部