views:

247

answers:

4

Hi, I have a simple SQL insert statement of the form:

insert into MyTable (...) values (...)

It is used repeatedly to insert rows and usually works as expected. It inserts exactly 1 row to MyTable, which is also the value returned by the Delphi statement AffectedRows:= myInsertADOQuery.ExecSQL.

After some time there was a temporary network connectivity problem. As a result, other threads of the same application perceived EOleExceptions (Connection failure, -2147467259 = unspecified error). Later, the network connection was reestablished, these threads reconnected and were fine.

The thread responsible for executing the insert statement described above, however, did not perceive the connectivity problems (No exceptions) - probably it was simply not executed while the network was down. But after the network connectivity problems myInsertADOQuery.ExecSQL always returned 0 and no rows were inserted to MyTable anymore. After a restart of the application the insert statement worked again as expected.

For SQL Server, is there any defined case where an insert statment like the one above would not insert a row and return 0 as the number of affected rows? Primary key is an autogenerated GUID. There are no unique or check constraints (which should result in an exception anyway rather than not inserting a row).

Are there any known ADO bugs (Provider=SQLOLEDB.1)?

Any other explanations for this behaviour?

Thanks, Nang.

+1  A: 

If the values you're trying to insert are violating

  • a CHECK constraint
  • a FOREIGN KEY relationship
  • a NOT NULL constraint
  • a UNIQUE constraint

or any other constraints, then the row(s) will not be inserted.

marc_s
Thanks! True. But then I would expect an exception, rather than silently not inserting a row. But besides that, there are no such constraints.
nang
+1  A: 

Do you use transactions? Maybe your application has no autocommit? Some drivers do not commit data if there was error in transaction.

Michał Niklas
Thanks. No explicit transactions used, but autocommit. If I used transactions, ExecSQL should return 1 for the number of affected rows anyway, shouldn't it?
nang
+1  A: 

If you does not have any exceptions, then:

  1. When a table has triggers without SET NOCOUNT ON, then actually the operation (INSERT / UPDATE / DELETE) may be finished successfully, but a number of affected records may be returned as 0.
  2. Depending on a transaction activity in current session, other sessions may not see changes made by current session. But current session will see own changes and a number of affected records will be (may be) not 0.

So, the exact answer may depend on your table DDL (+ triggers if any) and on how you are checking the inserted rows.

da-soft
Thanks. 1. No triggers used. 2. Neither the current session observes inserted rows, nor external sessions. I check the number of inserted rows by the return value of MyQuery.ExecSQL. Further, I checked the table for new rows via the SQL Management Studio - no new rows. Besides, in normal circumstances everything works fine. So I guess there is something strange happening at ADO / provider level, rather than actually at SQL / SQL Server level.
nang
Are you able to reproduce your issue ?
da-soft
In the beginning everything worked fine. Then the problem occurred for the first time. From then on, it was permanent until I restarted my application. Since then I am not able to reproduce it.
nang
Michał Niklas
The result of this scenario is an exception.
nang
+2  A: 

Looks like your Insert thread lost silently the connection and is not checking on it to do an auto reconnect if needed but keeps queuing the inserts without actually sending them.
I would isolate this code in a small standalone app to debug it and see how it behaves when you voluntarily disconnect the network then reconnect it.
I would not be surprised if you either found a "swallowed" exception, or some code omitting to check for success/failure.
Hope it helps...

François
Sounds reasonable. What I haven't described yet: When I closed the application, some memory leaks were reported, including ~45 TADOCommand and ~45 TADOQuery instances. I just wonder where the exception could have been swallowed, definitely not in my user code. In normal circumstances as soon as the connection gets broken all subsequent attemts to perform a query result in an exception.
nang