I have problem with part of excel VBA macro that should load data from csv file, to MariaDB tables. SQL command, which works in HeidiSQL, return error when used in VBA. The error message is:
[ma-3.0.3][10.2.13-MariaDB]This command is not supported in the prepared statement protocol yet.
Here is the VBA code.
DBConn = "DSN=Fundusze;UID=login;PWD=pass;"
Command = "Load data low_priority local infile '" + Replace(Plik, "\", "/") + "' replace into table _kurs_" + ID + " fields terminated by ';' lines terminated by '\r\n' ignore 0 lines (`Data`, `Notowanie`);"
Call ZapisDB(Command, DBConn)
Sub ZapisDB(SQL_Com As String, Connection As String)
Dim DBConn As ADODB.Connection
Set DBConn = New ADODB.Connection
DBConn.ConnectionString = Connection
DBConn.Open
DBConn.Execute (SQL_Com)
DBConn.Close
Set DBConn = Nothing
End Sub
I am aware that this is rather db server side problem, but what can I do if I need to load lot of data into lot od tables ? Why SQL command which is fine and works in HeidiSQL cannot be send via ODBC ?
EDIT - problem solved by making workaround
I have made a workaround to not use 'load data infile' as it seems that it is not supported by DB engine accessed via ODBC. I'm using 'insert into' query preparing string of values from csv which should be inserted.
I might be going out on a limb here and bet that you will find the problem(s) by adding this line at the very top of this module:
Option Explicit
(and in the future, always adding that to every module.)
This "forces" you to properly declare and refer to variables, objects, properties, etc.
I thinks it's better to use ExecuteNonQuery() as it's for Insert/Delete/Update :
Dim con As MySqlConnection = New MySqlConnection("DataSource=dev;Database=mydb;User ID=myUser;Password=mypass;")
Try
con.Open()
Dim sql As MySqlCommand = New MySqlCommand(Command, con)
sql.ExecuteNonQuery()
Catch ex As Exception
con.Close()
MsgBox("Record is not Inserted" + ex.Message)
End Try
One other thing you need to verify are the / you may have to transform in \
Related
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.
Im doing some MySQL operations in vbscript and currently Im doing (not true vbscript code as I dont know the syntax off the top of my head):
Dim whereclause=textboxtext
$DBExecute("connectionstring","delete from table where column='"+query+"'")
Obviously this is VERY unsafe and almost destructive. Is there a MySQL function I can pass in that query to make it safer?
There is no magic fairydust function to automatically make your statements harmless. A user that has permission to delete records will always be able to delete records.
If you're concerned about the way you build the statement (using string concatenation), now that's a whole other story. SQL injection can be mitigated via prepared statements (or parameterized queries, as Microsoft calls them):
value = "..."
connectionString = "..."
Set conn = CreateObject("ADODB.Connection")
conn.Open connectionString
Set cmd = CreateObject("ADODB.Command")
Set cmd.ActiveConnection = conn
cmd.CommandText = "DELETE FROM table WHERE column=?"
Set p = cmd.CreateParameter("#p", 200, 1, 255, value)
cmd.Parameters.Append p
cmd.Execute
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)
I have some data stored in SQL Server that contains apostrophes. Within the SQL Server table to apostrophe is escaped. For example the phrase "Roberts's thesis" is stored as "Robert''s Thesis". I use Access 2003 as a font end for the application and I use ADO to access the data stored in SQL Server using Stored Procedures.
The issue I am having is how to "un-escape" the double apostrophe when the data is retrieved using a recordset and then bound to a control. Here is some sample code.
Dim cnn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cnn = New ADODB.Connection
cnn.ConnectionString = myConnectionString
cnn.Open
Set rs = New ADODB.Recordset
Set rs.ActiveConnection = cnn
rs.Source = "EXEC uspMyStoredProcedureName"
rs.LockType = adLockOptimistic
rs.CursorType = adOpenStatic
rs.CursorLocation = adUseClient
rs.Open
Set ListControl.Recordset = rs
Set rs = Nothing
Set cnn = Nothing
Do I have to "loop" through the recordset manually and un-escape the apostrophe? Thank you.
You don't have to unescape anything. The doubled-apostrophe form is only used for string literals inside SQL statements. The actual value inserted in the database by INSERT... 'Robert''s Thesis'; is Robert's Thesis, and that is the value you'll get out when you read it from a recordset grabbed from a SELECT.
If whatever's inside uspMyStoredProcedureName is doing something weird to cause doubled apostrophes to get returned then it's broken and needs fixing; if you have Robert''s Thesis as an actual value in the database, then you've inserted broken data and you should be looking at fixing the code that's done that, and cleaning up the data.
If you have no possibility to change uspMyStoredProcedureName, then You will have to loop through the resultset.
Otherwise, changing the select statement in the stored procedure from col to Replace(col, '''''', '''') would do the trick.
Yes, there are six single quotes in the second argument and four in the third: Two enclose a string, and within that, each quote is doubled to escape it.
BTW: Why are the data stored with doubled quotes at all?
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.