Database: MS Sql Server 2016
Ignition: 7.9.6
I have a query which uses a temporary table. If I try to run this query under different transactions repeatedly, I get an error that the object already exists.
Intuitively, I would have thought that temp tables would not be visible between different transactions, but this does not seem to be True.
I must run this same query in multiple clients and threads on each client. How can I do this?
Ex:
import threading
import sys
import time
import java
times = []
def do():
try:
q = 'create table #Results(num varchar(30))'
s=time.time()
t = system.db.beginTransaction(database='NDB',
isolationLevel=system.db.READ_COMMITTED,
timeout=5000
)
times.append(time.time()-s)
_=system.db.runUpdateQuery(query=q, tx=t, database='NDB')
system.db.closeTransaction(t)
except java.lang.Exception, e:
print(e.getCause().getMessage())
threads=[]
for i in range(20):
# do()
t=threading.Thread(target=do)
t.start()
threads.append(t)
for t in threads:
t.join()
Output...
SQL error for "create table #Results(num varchar(30))": There is already an object named '#Results' in the database.
Note that this is inconsistent, hence the for loop. You may have to run a few times before the error pops up.
UPDATE:
After some research, it looks like SQL Server does things the following way: create a Connection, create zero or more Sessions using the Connection, create zero or more Transactions within each Session.
Temp tables are Session-scoped, which means that if Ignition is generating multiple Transactions within one Session and in each Transaction I am using the same temporary table name, I would end up creating the temp table in the first Transaction and then my create temp table statement in the next transaction would conflict with the existing object in the Session.
After a few runs of the code above, the error only seems to crop up in relation to some period of time between runs of the code which seems to correspond to the transaction timeout period. Might be something odd going on here...?
Table variables would be the next option, but they are batch-scoped and because I am using prepared statements with a ~2100 placeholder limit, I frequently have to cut up my queries into multiple batches and send them separately and a table variable would only be scoped for each of those batches.