# Bulk insert of tag valueChange events

**URL:** <https://forum.inductiveautomation.com/t/bulk-insert-of-tag-valuechange-events/112678>\
**Category:** Ignition\
**Tags:** ignition81, database, scripting\
**Created:** [December 8, 2025, 9:48am UTC](https://forum.inductiveautomation.com/t/bulk-insert-of-tag-valuechange-events/112678 "2025-12-08T09:48:53Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![jonathan.axelsson](https://avatars.discourse-cdn.com/v4/letter/j/51bf81/32.png) [@jonathan.axelsson](https://forum.inductiveautomation.com/u/jonathan.axelsson)\
**Post date:** [December 8, 2025, 9:48am UTC](https://forum.inductiveautomation.com/t/bulk-insert-of-tag-valuechange-events/112678/1 "2025-12-08T09:48:53Z")

</div>

We have have about 25 000 tags that we want log into an MSSQL database using tag eventChange scripts. One requirement is that every value is to be saved into a custom structure with a unique key for each machine and machine cycle. So we can not use tag historian since you cant make those kinds of relationships.

Since there are a lot of tags that fire querys at a very high rate we wanted to create some kind of buffer so that we could bulk insert lets say 100 rows at a time instead of doing them one by one.

We tried using system.util.getGlobals were we created a global list which held all the args for an insert query so that we could once every second bulk insert whatever was there (gatewayEvent script, 1000ms fixed delay) We limited it to 200 rows pers second as we fond a limitation of 2100 args per query.

It worked perfectly in small scale but as soon as we implemented it on all of the tags the script started to fire “empty rows” and no values were inserted.

Does anyone know why this could happen or have done something similar?

the gatewayEvent looked like this:

```python
buffer = system.util.getGlobals()['history_buffer']
row_count=len(buffer)
if row_count>200:
       max_rows=200
else:
max_rows=row_count

tag_rows=buffer[:max_rows]

SMASH_logging.logging.log_group_data(tag_rows)

del buffer[:max_rows]

```

Script:

```python
def log_group_data(tag_rows):
dbCon='SMASH'
values_sql = ",".join("(?,?,?,?,?,?,?,?)" for _ in tag_rows)

query = """
INSERT INTO tbl_history
(cycle_key, int_value, real_value, bool_value, timestamp_value, tag_id, string_value, timestamp)
VALUES {}
""".format(values_sql)

# Flatten parameters
args = [item for row in tag_rows for item in row]

system.db.runPrepUpdate(query, args, dbCon)

```

Error code like this:

```python

 
com.inductiveautomation.ignition.common.script.JythonExecException: Traceback (most recent call last): File "", line 10, in File "", line 94, in log_group_data INSERT INTO tbl_history (cycle_key, int_value, real_value, bool_value, timestamp_value, tag_id, string_value, timestamp) VALUES , 
, SMASH, , false, false) at com.inductiveautomation.ignition.common.script.builtin.AbstractDBUtilities.error(AbstractDBUtilities.java:392) at com.inductiveautomation.ignition.common.script.builtin.AbstractDBUtilities.runPrepUpdate(AbstractDBUtilities.java:268) at jdk.internal.reflect.GeneratedMethodAccessor51.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source) java.lang.Exception: java.lang.Exception: Error executing system.db.runPrepUpdate( INSERT INTO tbl_history (cycle_key, int_value, real_value, bool_value, timestamp_value, tag_id, string_value, timestamp) VALUES , 
, SMASH, , false, false)

at org.python.core.Py.JavaError(Py.java:545)

at com.inductiveautomation.ignition.common.script.builtin.AbstractDBUtilities.error(AbstractDBUtilities.java:392)

at com.inductiveautomation.ignition.common.script.builtin.AbstractDBUtilities.runPrepUpdate(AbstractDBUtilities.java:268)

at jdk.internal.reflect.GeneratedMethodAccessor51.invoke(Unknown Source)

at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

at java.base/java.lang.reflect.Method.invoke(Unknown Source)

at org.python.core.PyReflectedFunction.call(PyReflectedFunction.java:190)

at com.inductiveautomation.ignition.common.script.ScriptManager$ReflectedInstanceFunction.call(ScriptManager.java:553)

at org.python.core.PyObject.call(PyObject.java:494)

at org.python.core.PyObject.call(PyObject.java:498)

at org.python.pycode._pyx2431085.log_group_data$4(:94)

at org.python.pycode._pyx2431085.call_function()

at org.python.core.PyTableCode.call(PyTableCode.java:173)

at org.python.core.PyBaseCode.call(PyBaseCode.java:134)

at org.python.core.PyFunction.call(PyFunction.java:416)

at org.python.pycode._pyx2431084.f$0(:12)

at org.python.pycode._pyx2431084.call_function()

at org.python.core.PyTableCode.call(PyTableCode.java:173)

at org.python.core.PyCode.call(PyCode.java:18)

at org.python.core.Py.runCode(Py.java:1703)

at com.inductiveautomation.ignition.common.script.ScriptManager.runCode(ScriptManager.java:804)

at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$TrackingProjectScriptManager.runCode(ProjectScriptLifecycle.java:859)

at com.inductiveautomation.ignition.common.script.ScriptManager.runCode(ScriptManager.java:752)

at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$TrackingProjectScriptManager.runCode(ProjectScriptLifecycle.java:840)

at com.inductiveautomation.ignition.common.script.TimerScriptTask.run(TimerScriptTask.java:92)

at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)

at java.base/java.util.concurrent.FutureTask.runAndReset(Unknown Source)

at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)

at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at java.base/java.lang.Thread.run(Unknown Source)

Caused by: org.python.core.PyException: java.lang.Exception: java.lang.Exception: Error executing system.db.runPrepUpdate( INSERT INTO tbl_history (cycle_key, int_value, real_value, bool_value, timestamp_value, tag_id, string_value, timestamp) VALUES , 
, SMASH, , false, false)

... 31 common frames omitted

Caused by: java.lang.Exception: Error executing system.db.runPrepUpdate( INSERT INTO tbl_history (cycle_key, int_value, real_value, bool_value, timestamp_value, tag_id, string_value, timestamp) VALUES , 
, SMASH, , false, false)

... 30 common frames omitted

Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near 'VALUES'.

at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:265)

at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1662)

at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:615)

at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:537)

at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7417)

at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:3488)

at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:262)

at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:237)

at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeUpdate(SQLServerPreparedStatement.java:483)

at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:136)

at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:136)

at com.inductiveautomation.ignition.gateway.datasource.SRConnectionWrapper$SRPreparedStatement.executeUpdate(SRConnectionWrapper.java:981)

at com.inductiveautomation.ignition.gateway.datasource.SRConnectionWrapper.runPrepUpdate(SRConnectionWrapper.java:181)

at com.inductiveautomation.ignition.gateway.script.GatewayDBUtilities._runPrepStmt(GatewayDBUtilities.java:203)

at com.inductiveautomation.ignition.common.script.builtin.AbstractDBUtilities.runPrepUpdate(AbstractDBUtilities.java:261)

```

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [December 8, 2025, 12:40pm UTC](https://forum.inductiveautomation.com/t/bulk-insert-of-tag-valuechange-events/112678/2 "2025-12-08T12:40:46Z")

</div>

I'm assuming the indentation error you have in the script after the `else:` is a copy paste error as you are obviously running the script.

There error says that it is a syntax error. I don't see anything imediately in the script that I would think would result in a syntax error.

I would suggest logging the actual query prior to it being run, to try and determine what the syntax error is.

---

<div class="post-metadata">

**Author:** ![jonathan.axelsson](https://avatars.discourse-cdn.com/v4/letter/j/51bf81/32.png) [@jonathan.axelsson](https://forum.inductiveautomation.com/u/jonathan.axelsson)\
**Post date:** [December 8, 2025, 12:53pm UTC](https://forum.inductiveautomation.com/t/bulk-insert-of-tag-valuechange-events/112678/3 "2025-12-08T12:53:51Z")

</div>

it seems the entire errror was not included in the copy paste eather… I think this is the key line:

Caused by: org.python.core.PyException: java.lang.Exception: java.lang.Exception: Error executing system.db.runPrepUpdate( INSERT INTO tbl\_history (cycle\_key, int\_value, real\_value, bool\_value, timestamp\_value, tag\_id, string\_value, timestamp) VALUES , , SMASH, , false, false). It looks like the args list is empty, but i cant figure out why.

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [December 8, 2025, 1:24pm UTC](https://forum.inductiveautomation.com/t/bulk-insert-of-tag-valuechange-events/112678/4 "2025-12-08T13:24:04Z")

</div>

The only explanation is, that `tag_rows` is empty, which would indicate that the buffer is empty.

Possible issues:

1. The gatewayEvent is being called prior to globals being populated.
2. You are populating globals with a different key than you are attempting to access it with.
3. You are not properly populating globals.

I'm not super familiar with using `getGlobals()`, I am sure that Phil will provide a pertinent answer if he has one.

Phil, could this be related to the script initilization race?

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [December 8, 2025, 1:34pm UTC](https://forum.inductiveautomation.com/t/bulk-insert-of-tag-valuechange-events/112678/5 "2025-12-08T13:34:33Z")

</div>

> [@lrose](#):
>
> Possible issues:

(1) almost certainly.

I don't use `system.util.getGlobals()`. It has problems that I solved with `system.util.globalVarMap(...)` in my Integration Toolkit.

I recommend using my Integration Toolkit's [Bulk Script Action](https://www.automation-pros.com/toolkit/doc/actors.html#bulk-script-action), with a suitable script (or multiple) in the global scripting project.
