Access & SQL-Server: Resetting Autonumber field with table wipe - ms-access

I am trying to keep a copy of an activity table synchronized between a SQL Server Express table and the production Access version. In other tables, I am able to wipe the contents of the SQL Server table, and insert the whole mess back in to capture all of the changes. However, when I attempt to do that with this table - I get the information - but the Autonumber field increments from the last unused number from the previous iteration. After a dozen or so 'sync' operations, I am dangerously close to running out of autonumbers for this field.
I have tried issuing the 'DBCC CHECKIDENT' from the Microsoft Access front end application, which throws an error that the statement didn't start with SELECT, DELETE, PROCEDURE, DROP, ALTER or something like that. This command DOES work when issued from the SQL Server management console (a tool I do have access to in the current test environment, but will NOT when the application goes production).
I then tried the 'TRUNCATE TABLE' query using the DoCmd.RunSQL command and it threw the error that the operation isn't supported on linked tables (approximately). This table is linked to the Microsoft Access front-end (the back end table is on SQL Server Express).
So, for a quick summary:
Front End is an Microsoft Access VBA application
Data is stored on SQL Server Express on a remote machine
Data tables are linked in the front end application
I will NOT be able to use SQL Server Management Console commands when this application goes production, it needs to run it's housekeeping on it's own.
DoCmd.RunSQL and CurrentDB.Execute do not seem to allow the use of the TRUNCATE TABLE -or- the 'DBCC CHECKIDENT' command.
Both of the aforementioned functions -DO- work when issued from the SQL Server Management Console - see above as to why this isn't a viable option.
-ALL- other tables behave the way I'd expect them to besides this one, resetting their indentity fields as appropriate.
-- Edited 08/08/2011 # 15:08 --
Alright - I have tried a number of attempts at a VBA-based pass-through query, all resulting in an ODBC -- call failed error. Here is the code for the module I created to handle pass-throughs (borrowed the code from dbforums.com):
Function RunPassThrough(ByVal ConnectionString As String, ByVal SQL As String, Optional ByVal QueryName As String)
Dim dbs As DAO.Database
Dim qdf As DAO.QueryDef
Set dbs = CurrentDb
Set qdf = dbs.CreateQueryDef
With qdf
.Name = QueryName
.Connect = ConnectionString
.SQL = SQL
.ReturnsRecords = (Len(QueryName) > 0)
If .ReturnsRecords = False Then
.Execute
Else
If Not IsNull(dbs.QueryDefs(QueryName).Name) Then dbs.QueryDefs.Delete QueryName
dbs.QueryDefs.Append qdf
End If
.Close
End With
Set qdf = Nothing
Set dbs = Nothing
End Function
As such, I need to specify a connection string to the database; all of the following have failed:
strConnect = "ODBC;DRIVER={SQL Server};SERVER=ENV980-067\ENVIRON_TEST;DATABASE=instkeeper_test;Uid=<my username>;Pwd=<my password>;"
Result: Run-time error ODBC -- call failed (error #3146)
strConnect = "ODBC;DRIVER={SQL Server};SERVER=ENV980-067\ENVIRON_TEST;DATABASE=instkeeper_test;TRUSTED_CONNECTION=YES;"
Result: Run-time error ODBC -- call failed (error #3146)
strConnect = "ODBC;DSN=instkeeper_beta;"
Result: Asks me for the Data Source Name, once specified with the Data Source administration panel, I get Run-time error ODBC -- call failed (error #3146)
strConnect = "ODBC;Server=ENV980-067\ENVIRON_TEST;Database=instkeeper_test;User ID=<my user name>;Password=<my password>;Trusted_Connection=False;"
Result: Run-time error ODBC -- call failed (error #3146)
-- Edited 08/08/2011 # 16:41 --
MORE failures on iterations of the connection strings, I am officially out of ideas on how to make this beast work. After trying the previous - now any pass-throughs made with the interface fail after asking for a DSN. No repair is possible, they have to be restored to call on the linked tables and ran through JET.
strConnect = "ODBC;DATA SOURCE=instkeeper_test;"
Result: Run-time error ODBC -- call failed (error #3146)
strConnect = "ODBC;DRIVER=SQL Server;SERVER=ENV980-067\ENVIRON_TEST;"
Result: Run-time error ODBC -- call failed (error #3146)
strConnect = "ODBC;DRIVER=SQL Server;Server=ENV980-067\ENVIRON_TEST;Database=instkeeper_test;User ID=<my user name>;Password=<my password>;"
Result: Run-time error ODBC -- call failed (error #3146)

In the SQL Server side, you can
Use another DBCC command
DBCC CHECKIDENT ('MyTable', RESEED, 1)
Or use TRUNCATE TABLE...
If the table contains an identity column, the counter for that column is reset to the seed value defined for the column. If no seed was defined, the default value 1 is used.
So you'd run
TRUNCATE TABLE MyTable

I went through all of my code, and checked with a local VBA expert who pointed out that I had made an error in the naming of my tables while attempting to do a pass-through query. I, basically, was referring to the table by the name it possess as a link in my front-end, and not the actual table name it possesses in SQL Server on the back end.
The following connection string, once this was corrected, worked:
strConnect = "ODBC;DRIVER={SQL Server};SERVER=ENV980-067\ENVIRON_TEST;DATABASE=instkeeper_test;TRUSTED_CONNECTION=YES;"
This, then, allowed me to execute the TRUNCATE TABLE command on the remote table, and execute a DoCmd.RunSQL statement to repopulate the table from the production source.
The end result is that when the option is selected to update the Activity, it will purge the contents of the remote table, then read the contents of the production table into the test table for use while resetting the autonumber.

I found out an easy way of doing that trought a SQL query written in Access, at the SQL View!
Check it out at:
http://answers.microsoft.com/en-us/office/forum/office_2003-access/reset-autonumber-in-access-table-automatically/66cbcfed-5cbe-40f6-b939-9aea8bbea2de
Write this:
ALTER TABLE YourTable ALTER COLUMN YourField COUNTER(1,1)

Related

How to execute and query in VBA in MS Access using the ODBC Connector for MySQl?

The following VBA code will allow you to run a sql query in the current access database
I tried this in a MS Access file that is connected to a MySQL database through the ODBC Connector. However this code does not work, presumably because it's not a normal access DB.
How can I query the database using the existing ODBC connection?
EDIT: I always get a "Runtime error 3024 cannot find file"
Try 1
Dim mydb As Database
Dim myrs As DAO.Recordset
Set mydb = CurrentDb
Set myrs = mydb.OpenRecordset("select from blah blah...")
Try 2
Dim dbMine As DAO.Database
Set dbMine = CurrentDb
Dim qr As String
qr = "select count(*) as `result` from floatinp_appdb2.clientes where cliente_email = 'tiagovalente#float-in.pt';"
'debug.print qr
dbMine.Execute qr, dbFailOnError
Requirements are:
Linked table has a PK defined.
So, this should work:
Set myrs = mydb.OpenRecordset("select from blah blah...",dbOpenDynaset, dbSeeChanges)
Also:
any true/false columns (bit fields) should have default value of 0 set. (don't allow nulls for the true/false columns).
You can and should also consider adding a rowversion column, but above should suffice.
Though the error was "runtime error 3024 cannot find file", my mistake was including the database name before the table
e.g. Select * From DB2.Table1

Microsoft Access can't update large Memo (Long Text) fields on a linked SQLite3 ODBC table: sequence error (#-1)

Microsoft Access can't update large Memo Fields (Long Text) on the ODBC linked SQLite table. The limit is somewhere between 2300 and 5152 characters. It can be an Update Query, DAO or ADO rs.Edit or manual copy-paste using Ctrl-C / Ctrl-V + mouse directly into the linked table - it doesn't matter.
Error messages:
Update query or manual copy-paste:
ODBC-update on a linked table 'Adobe_AdditionalMetadata' failed.
sequence error (#-1)
DAO, VBA on the rs.Edit line:
Run-time error '3027':
Cannot update. Database or object is read-only.
ADO, VBA on the rs.Update line:
Run-time error '-2147217887 (80040e21)':
ODBC-update on a linked table 'Adobe_AdditionalMetadata' failed.
Installed driver:
http://www.ch-werner.de/sqliteodbc/ (SQLite3 ODBC Driver)
Access linked field properties: Long Text
the original SQLite field properties: TEXT NOT NULL DEFAULT ''
(Access see almost all fields as Memo)
This is the "xmp" field in the "Adobe_AdditionalMetadata" table of the Adobe Lightroom "Lightroom Catalog.lrcat" file.
Smaller Memo fields can be updated easily.
One possible workaround is to enable the "No WCHAR" option for the ODBC DSN:
(Existing ODBC linked tables in Access may have to be re-created for the change to take effect.)

VBA Code for Transferring ACCESS Table to SQL Server

I was trying to Transfer my Access Table Data over to SQL server but I am getting an error which says
Object Variable or With block variable not set
I've already connected my Access database with SQL server but now facing problem transferring data to SQL server with VBA code.
Can you please help me with it?
Here is my code:
Public Sub ADOtest()
Dim ADOConn As New ADODB.Connection
Dim ADOCom As New ADODB.Command
On Error Resume Next
ADOConn.ConnectionString = "Driver={SQL Server};Server=IT-TEMP2-8470P\SQLEXPRESS2014;Database=Discrepancy;Trusted_Connection=True;"
ADOConn.Open
Debug.Print ADOConn.State
Dim db As Database
Dim Discrepancy As Database
Set db = Discrepancy
Dim ID As Variant
db.Execute "INSERT INTO [ODBC;DRIVER=SQL Server;SERVER=IT-TEMP2-8470P\SQLEXPRESS2014;DATABASE=Discrepancy].SFTransfersDB ( ID, TO ) SELECT ID,TO FROM SFTransfersDB"
End Sub
I am getting error at the 2nd last line:
db.Execute "INSERT INTO [ODBC;DRIVER=SQL Server;SERVER=IT-TEMP2-8470P\SQLEXPRESS2014;DATABASE=Discrepancy].SFTransfersDB ( ID, TO ) SELECT ID,TO FROM SFTransfersDB"
It seems you are attempting an ad hoc distributed query. If server permits it, consider executing this statement after your ADO connection. No need for calling Access objects.
ADOConn.Execute "INSERT INTO dbo.SFTransfersDB ([ID], [TO])" _
" SELECT [ID], [TO] FROM OPENDATASOURCE('Microsoft.ACE.OLEDB.12.0', " _
"'Data Source=""C:\Path\To\Access\Database.accdb""')...SFTransfersDB;"
You declare two Database variables, but don't initialize them (you don't set them to anything):
Dim db As Database
Dim Discrepancy As Database
So this
Set db = Discrepancy
is the same as
Set db = Nothing
and so when you try to use db, you get the error that db is not set, which it isn't.
Thanks for your suggestions.
I got it correct after all.
I used "Set db = CurrentDb" and it worked perfect.

MS Access crashes on error

I wrote a little SQL command to correct a field in a table. Since it was so small (and maybe I got a little arrogant) I didn't run it even once, and just put it into an update package for a different user.
Dim SQL As String
Dim rs As DAO.Recordset
On Error GoTo errhandler
SQL = "UPDATE Table1 SET Name = 'Calender' WHERE Name = 'Clalender'"
CurrentDb.Execute
errhandler:
Exit Sub
That's why I didn't notice it should have been
CurrentDb.Execute (SQL)
When the user started this command, Access said something like "Critical Error" and closed.
How come the error handling didn't catch that error? And why didn't Access tell me there was something missing when I wrote it? Usually it's quite pedantic about that.
The statement
CurrentDb.Execute
will not compile.
Compile error: Argument not optional.
Your victim ;) must have hit the error when they tried to run the code, which triggered an "on-the-fly" compilation. Error trapping in your code would not handle that because your code never got a chance to run (because it wouldn't compile).
In other words, Access would have gotten all pedantic on you if you had tried to run (or at least compile) your code.... :)
Try to compact and repair the database.
If that does not work, create a new empty database and import all the objects from the problematic database. Perhaps, you can import a few objects each time to determine which is the corrupted object (if any. Sometimes Access have this behavior and there isn't any bad object).

How to obtain value of auto_increment field in Access linked to MySQL?

I'm trying to modify and existing Access application to use MySQL as a database via ODBC with the minimal amount of recoding.
The current code will often insert a new record using DAO then obtain the ID by using LastModified. This doesn't work with MySQL. Instead I'm trying to use the approach using
SELECT * FROM tbl_name WHERE auto_col IS NULL
Suggested for Access in the MySQL documentation. However if I set up a sample table consisting of just an id and text data field and execute this
CurrentDb.Execute ("INSERT INTO tbl_scratch (DATA) VALUES ('X')")
Set rst = CurrentDb.OpenRecordset("SELECT id FROM tbl_scratch WHERE id IS NULL")
myid = rst!id
Id is returned as null. However if I execute
INSERT INTO tbl_scratch (DATA) VALUES ('X');
SELECT id FROM tbl_scratch WHERE id IS NULL;
using a direct MySQL editor then id is returned correctly, so my database and approach is fine but my implementation inside Access must be incorrect. Frustratingly the MySQL documentation gives the SQL statement to retrieve the id as an example that works in Access (as it states LAST_INSERT_ID() doesn't) but gives no further details.
How might I fix this?
Solved (and blogged) as below
I've been implementing an upgrade for a set of Access databases to replace the Access file database with MySQL linked by ODBC. Everything seems to be going remarkably smoothly except for the common concept of inserting a record into a table with an auto-increment id column and retrieving the value of the id just created. Of course on PHP or the like one would just use the
SELECT LAST_INSERT_ID()
Function to retrieve the ID. However the MySQL documentation itself says that this doesn't work for certain ODBC applications such as Delphi or Access and suggests using
SELECT * FROM tbl WHERE auto IS NULL;
Unfortunately this simply didn't work for me when called from inside the Access application I was working with, and there seems to be several comments around the web that indeed this is unreliable as Access may drop the data connection and reconnect behind the scenes - thus invalidating the call.
As an alternative I decided to use a MySQL function to add a blank record to the table, returning the id which Access would then use to update the record (which fits well with the code-style of the existing application). Unfortunately this apparently straightforward work-around fails to be simple either as long-standing bugs in MySQL make finding valid code that can both send and return a variable something of a challenge. Several examples on the web will work within the limited domain of using either just IN or OUT variables but fail to work with both.
My final solution, which works on the MySQL 5.1 and Access 2003 combination I am deploying, is as follows
MySQL procedure
DELIMITER $$
CREATE
PROCEDURE `alicedata`.`sp_ins_identity`(IN tablename VARCHAR(50))
BEGIN
SET #result = 0;
SET #sqlproc = CONCAT("INSERT INTO ",tablename," () VALUES ();");
PREPARE s1 FROM #sqlproc;
EXECUTE s1;
DEALLOCATE PREPARE s1;
SELECT LAST_INSERT_ID();
END$$
This procedure is useful in that it will insert a row and return the id for any table where a row contains all null fields or non-null fields with defaults defined. To call this I use the following function:
Public Function InsertMySQLIdentityRow(DSN As String, Tablename As String) As Integer
On Error GoTo Err_InsertMySQLIdentity
Dim cnnSQL As New ADODB.Connection
Dim cmdSQL As ADODB.Command
Dim pid As Integer
Dim rs
Dim strSQL As String
' initialize
pid = 0
' set up ADO connection
Set cnnSQL = New ADODB.Connection
cnnSQL.Open DSN
' execute the procedure - note that assembling by parameter fails to handle IN or OUT correctly
Set cmdSQL = New ADODB.Command
cmdSQL.ActiveConnection = cnnSQL
strSQL = "call sp_ins_identity('" & Tablename & "');"
Set rs = CreateObject("ADODB.Recordset")
Set rs = cnnSQL.Execute(strSQL)
If Not rs.EOF Then
pid = rs(0)
End If
' clean up
Set rs = Nothing
Set cmdSQL = Nothing
cnnSQL.Close
Set cnnSQL = Nothing
Exit_InsertMySQLIdentity:
InsertMySQLIdentityRow = pid
Exit Function
Err_InsertMySQLIdentity:
MsgBox Err.Number & Err.Description
Resume Exit_InsertMySQLIdentity
End Function
This code is somewhat unusual in that normally, on MSSQL, you would use a parametrized procedure call, but due to bugs in the MySQL ODBC (or at least incompatibilities with Access) the above seems to be the only way that allows both data to be passed and returned.