When using temporary tables in SQL Server, all you have to do is prefix the table during creation with a “#” (pound sign) and SQL Server knows to delete the table after the session closes. Example of creating a temporary table in SQL Server:
CREATE TABLE #myTable (
ID int IDENTITY(1,1),
firstName nvarchar(30),
lastName nvarchar(30)
)
Again, if you close your session in SQL Server, the above table will be dropped then and there. This makes temporary tables in SQL Server very useful to SSIS as they clean up after themselves.
Unfortunately, there are many of us who are still having to deal with all those pesky Access 200x databases running around. And, unfortunately, Access does not support temporary tables like SQL Server does. When you create a table in Access, it is there to stay unless you specifically drop it by executing a DROP TABLE statement.
In SSIS, this leads to a bit of a problem. Let’s say your package fails for whatever reason (lost connection to server, power went out, etc.) before it gets to the step where you clean up all those temporary Access tables (i.e. you have an Execute SQL step that has one or more DROP TABLE statements in it). The next time that same package is scheduled to run it’s just going to fail again when it gets to the step where you create your temporary tables in your Access database because those tables already exist.
In order to combat this problem, and provide yourself a sanity check as I’m certain that like me you always forget to delete your temp tables while testing which means you get the “table already exists” error a lot, we can put a step in that checks for temp tables in Access and drops them. Before the step that creates your temp tables, insert a Script Task that runs the following code:
OleDbConnection conn = null; OleDbCommand comm = null; public void Main() { conn = new OleDbConnection(Dts.Connections["Connection Manager"].ConnectionString); comm = new OleDbCommand("", conn); conn.Open(); if (checkForTable("Demographics")) { comm.CommandText = "DROP TABLE Demograhpics"; comm.ExecuteNonQuery(); } if (checkForTable("newBills")) { comm.CommandText = "DROP TABLE newBills"; comm.ExecuteNonQuery(); } if (checkForTable("newTrans")) { comm.CommandText = "DROP TABLE newTrans"; comm.ExecuteNonQuery(); } conn.Close(); conn.Dispose(); Dts.TaskResult = (int)ScriptResults.Success; } private bool checkForTable(string tableName) { string[] restrictions = new string[3]; restrictions[2] = tableName; DataTable dt = conn.GetSchema("Tables", restrictions); if (dt.Rows.Count == 0) { return false; } else { return true; } }
Notice that this code checks for three tables: Demograhpics, newBills, and newTrans. You can, of course, keep adding “if” statements to check for your temporary tables or you can pass in an object variable that you can loop through that checks for a list of tables. This way, if your packages fails for some reason during one run, on the next run any temporary tables in Access will be dropped before the task that creates them executes.
There may be other more elegant ways to handle this problem. If I think of any, I’ll post them. You, of course, are welcome to mention other ways in the comments section.
JamesNT
[…] See my post on handling temporary tables in Access. […]