mysql vba连接字符串带有“ no_date_overflow”

发布于 2025-01-21 06:13:50 字数 1460 浏览 2 评论 0原文

因此,我在MS Access中使用MySQL链接表有这个问题: 当我手动设置使用“禁用日期溢出错误”的ODBC Unicode连接时,我可以使用MS Access前端删除MySQL链接表中的记录。 mysql odbc设置 但是,当我使用vba中的以下连接字符串连接时,表已连接,但是当我在日期字段中输入日期或尝试删除记录时,我会得到日期溢出错误

''-------------------------------------
strConn = "Driver={" & MysqlDriver & "}" & _
           ";server=" & ServerName & _
           ";Database=" & DatabaseName & _
           ";Trusted_Connection=Yes" & _
           ";NO_DATE_OVERFLOW=1" & _  'This is the part that I think it doesn't work in the code
           ";charset=utf8" & _
           ";user=" & ConnUserName & _
           ";password=" & ConnPassword

Delete_ALL_TABLES   '' Delete All the old tables before the import
Conn.Open strConn
Debug.Print Conn.ConnectionString
Set TablesSchema = Conn.OpenSchema(adSchemaTables)
Debug.Print TablesSchema.RecordCount
Do While Not TablesSchema.EOF
 R = R + 1
 def_str = TablesSchema("TABLE_NAME")
 Debug.Print R, def_str
 Set tdfLink = db.CreateTableDef(def_str)
 tdfLink.SourceTableName = def_str
 tdfLink.Connect = "ODBC;" & strConn
 db.TableDefs.Append tdfLink
 DoEvents
 TablesSchema.MoveNext
Loop
''-------------------------------------

它仅与我手动创建的ODBC一起使用“禁用日期溢出错误”。

您能帮我解决连接字符串的问题吗?

如果我可以将密码保存在连接字符串中,则Bouns会有所帮助,因此当MS Access前端关闭并重新打开时,我不必导入表。

先感谢您 :)

So I have this issue with MySQL linked tables in MS Access:
When I manually set up an ODBC Unicode connection with "Disable Date Overflow error" I'm able to delete records in the MySQL linked table using the MS Access front end.
MySQL ODBC Settings
However, when I connect using the below connection string in VBA the tables are connected but when I enter a date in the date field or try to delete a record I get a Date Overflow error

''-------------------------------------
strConn = "Driver={" & MysqlDriver & "}" & _
           ";server=" & ServerName & _
           ";Database=" & DatabaseName & _
           ";Trusted_Connection=Yes" & _
           ";NO_DATE_OVERFLOW=1" & _  'This is the part that I think it doesn't work in the code
           ";charset=utf8" & _
           ";user=" & ConnUserName & _
           ";password=" & ConnPassword

Delete_ALL_TABLES   '' Delete All the old tables before the import
Conn.Open strConn
Debug.Print Conn.ConnectionString
Set TablesSchema = Conn.OpenSchema(adSchemaTables)
Debug.Print TablesSchema.RecordCount
Do While Not TablesSchema.EOF
 R = R + 1
 def_str = TablesSchema("TABLE_NAME")
 Debug.Print R, def_str
 Set tdfLink = db.CreateTableDef(def_str)
 tdfLink.SourceTableName = def_str
 tdfLink.Connect = "ODBC;" & strConn
 db.TableDefs.Append tdfLink
 DoEvents
 TablesSchema.MoveNext
Loop
''-------------------------------------

MS Access Date Overflow Error

I'm using MySQL ODBC Unicode 8.0 driver and tested the connection with MS Access 32-bit and 64-bit versions.

it only works with the ODBC I manually create with "Disable Date Overflow error" checked.

Would you please help me fix the issue with the connection string?

Bouns help if I can save the password within the connection string so I don't have to import the tables when the MS Access Front end is closed and reopened.

Thank you in Advance :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

厌味 2025-01-28 06:13:50

让我们从奖金开始。 MS Access有一个无证件连接池。如果创建连接,然后尝试访问同一服务器&使用相同的ODBC驱动程序主版本的数据库,即使您试图使用不同的凭据。
也将重复使用该连接。
副作用:如果您在链接表中的服务器和数据库中创建DAO连接,则它们将在不提示用户和密码的情况下工作。

同样,从安全的角度来看,可以将链接的表从ACCDE文件导入到可编辑的ACCDB中,因此最好保存没有用户&密码,并在启动时提示用户获得凭据。一个不太安全的变化是将连接字符串隐藏在VBA函数中时,然后分发ACCDE文件。因此,攻击者必须拆卸ACCDE文件才能获取密码。可以做到,但它停止了大多数非专业人士。

因此,我的建议是创建一个启动功能,Wich试图使用列表中的所有ODBC驱动程序创建连接,直到找到一个驱动程序,而不是relinks tables&仅当驾驶员已更改时,Passstrough查询。

我正在使用它来重新链接表:(与no_date_overflow一起使用)

Private Sub dsnless_table2(Name As String, strconn As String, Optional srcname As String = "", Optional myflags As Long = 0)
'
On Error GoTo myerr
ERT = "dsnless_table2"
ert2 = ert2 & " ->" & ERT
ert3 = ""

   Dim tdef As New TableDef, sourcename As String, mysource As String, db As DAO.Database, eflag As Boolean, oldcon As String
   Set db = CurrentDb
   
eflag = False
On Error Resume Next
   If IsObject(db.TableDefs(Name)) = True Then eflag = True
   If err.Number <> 0 Then eflag = False
err.Clear
On Error GoTo myerr

If eflag = True Then
   sourcename = db.TableDefs(Name).SourceTableName
   oldcon = db.TableDefs(Name).Connect
   
   If compdiff(oldcon, strconn) = False And compdiff(sourcename, srcname) = False Then GoTo skip ' .Connect, .Name and .SourcetableName is equal to new value..
   ' else: recreate table; .Connect is write protected(?) after tabledefs.append
   DoCmd.DeleteObject acTable, Name
   db.TableDefs.Refresh
Else
   sourcename = ""
End If
      
   If Len(srcname) = 0 Then
      If Len(sourcename) > 0 Then
         mysource = sourcename
      Else
         mysource = Name
      End If
   Else
      mysource = srcname
   End If
   
   Set tdef = db.CreateTableDef(Name, 0, mysource, strconn)  
   db.TableDefs.Append tdef  

' db.TableDefs.Append stores actual connection string instead of the specified one. 
   If tdef.Connect <> strconn Then
      tdef.Connect = strconn
      tdef.RefreshLink
   End If
   
skip:
On Error Resume Next
db.TableDefs(Trim(Name)).Properties("Attributes").Value = myflags ' dbHiddenObject ' 536870913  ' dbsystemobject = -2147483646
err.Clear
On Error GoTo myerr
   
   'db.TableDefs.Refresh
   
Exit Sub
'Resume Next
myerr:
    Call show_ert(err.Number, erl)
   
End Sub




Public Function compdiff(inA As Variant, inB As Variant) As Boolean
' returns true if values doesn't match, Including Null <>2 etc.. ' Null,Null --> False.  Null, 1 --> True. 1,1 --> False. A,B --> True.
'input: anything if "=" has a meaning for that datatype.
On Error GoTo myerr

Dim OneNullflag As Boolean, Compflag As Boolean
OneNullflag = IsNull(inA) Xor IsNull(inB) 'csak az egyik Null?
Compflag = Not (IsNull(inA) Or IsNull(inB)) 'egyik sem Null?

If OneNullflag = True Then
   compdiff = True ' Null <> 2
Else
   If Compflag = True Then
      ' No Nulls
      If inA = inB Then
         compdiff = False ' 1=1 ; (1<>1) = False
      Else
         compdiff = True ' 1<>2
      End If
   Else
      compdiff = False ' Null = Null
   End If
End If

Exit Function
myerr:
   ERT = "compdiff()"
   ert2 = ert2 & " ->" & ERT
   ert3 = ""
   Call show_ert(err.Number, erl)
End Function  

,这是创建连接的函数:

Private Function dsntest(strCnn1 As Variant) As Boolean
' used by cnn_startup()
On Error GoTo myerr

   dsntest = False
   If IsNull(strCnn1) Then Exit Function
   If Len(CStr(strCnn1)) < 2 Then Exit Function

Dim dbs As DAO.Database, qdf As DAO.QueryDef, rn As Long

   Set dbs = CurrentDb()
   Set qdf = dbs.CreateQueryDef("")
   
   qdf.ReturnsRecords = False
   qdf.Connect = strCnn1
   'Any VALID SQL statement that runs on server will work below.
   qdf.SQL = "Select 0;" '"SET @icon = 1;" ' doesn't run on Oracle server --> sqlstr parameter
   
   On Error Resume Next
     qdf.Execute
     rn = err.Number
   On Error GoTo myerr
   
   If rn = 0 Then dsntest = True

cleanup:
   Set qdf = Nothing
   Set dbs = Nothing
   
   Exit Function
   
myerr:
   dsntest = False
   ERT = "dsntest"
   ert2 = ert2 & " ->" & ERT
   ert3 = ""
   Call show_ert(err.Number, erl)
   GoTo cleanup
End Function

我们基本上创建一个passstrough Query WICH可以打开连接,而不是我们将其丢弃,因此不会与任何保存的查询有关密码。

奖励信息:我建议使用ODBC驱动程序版本8.0.26。 8.0.29可能与no_date_overflow一起使用= 1。有关更多详细信息,请参阅此信息: https://bugs.mysql.com/bug.php.php.php? id = 107235 。 0.27和0.28具有其他与访问相关的错误。

奖励信息2:MS Access VBA有一个记录的ERL对象的中途。我有一个在发布过程中运行的行编号功能。如果在编号的VBA线上发生错误,则将其存储在ERL中,直到您离开子/功能或清除错误。 Show_ert()将一些遥测数据(包括ERL)发送到服务器,因此我可以监视客户端错误。

Let's start with the bonus. MS Access has an undocumented connection pool. If you create a connection, and later you try to access the same server & database using the same odbc driver main version, then it will reuse that connection, even if you are trying to use different credentials.
Side effect: if you create a DAO connection to the server and database where you have linked tables, they will work without prompting for user and password.

Also, from a security point of view, linked tables can be imported from an accde file into an editable accdb, so it is better to save the tables without user & password, and prompt the user for credentials once at startup. A less secure variation is when you hide the connection string in a VBA function, and you distribute an accde file. So an attacker has to disassemble the accde file to get the password. It can be done, but it stops most non-professionals.

So my proposal is to create a startup function, wich tries to create connections using all the odbc drivers on a list until it finds one, and than relinks tables & passtrough queries only if the driver has been changed.

I'm using this to relink tables: (works with NO_DATE_OVERFLOW)

Private Sub dsnless_table2(Name As String, strconn As String, Optional srcname As String = "", Optional myflags As Long = 0)
'
On Error GoTo myerr
ERT = "dsnless_table2"
ert2 = ert2 & " ->" & ERT
ert3 = ""

   Dim tdef As New TableDef, sourcename As String, mysource As String, db As DAO.Database, eflag As Boolean, oldcon As String
   Set db = CurrentDb
   
eflag = False
On Error Resume Next
   If IsObject(db.TableDefs(Name)) = True Then eflag = True
   If err.Number <> 0 Then eflag = False
err.Clear
On Error GoTo myerr

If eflag = True Then
   sourcename = db.TableDefs(Name).SourceTableName
   oldcon = db.TableDefs(Name).Connect
   
   If compdiff(oldcon, strconn) = False And compdiff(sourcename, srcname) = False Then GoTo skip ' .Connect, .Name and .SourcetableName is equal to new value..
   ' else: recreate table; .Connect is write protected(?) after tabledefs.append
   DoCmd.DeleteObject acTable, Name
   db.TableDefs.Refresh
Else
   sourcename = ""
End If
      
   If Len(srcname) = 0 Then
      If Len(sourcename) > 0 Then
         mysource = sourcename
      Else
         mysource = Name
      End If
   Else
      mysource = srcname
   End If
   
   Set tdef = db.CreateTableDef(Name, 0, mysource, strconn)  
   db.TableDefs.Append tdef  

' db.TableDefs.Append stores actual connection string instead of the specified one. 
   If tdef.Connect <> strconn Then
      tdef.Connect = strconn
      tdef.RefreshLink
   End If
   
skip:
On Error Resume Next
db.TableDefs(Trim(Name)).Properties("Attributes").Value = myflags ' dbHiddenObject ' 536870913  ' dbsystemobject = -2147483646
err.Clear
On Error GoTo myerr
   
   'db.TableDefs.Refresh
   
Exit Sub
'Resume Next
myerr:
    Call show_ert(err.Number, erl)
   
End Sub




Public Function compdiff(inA As Variant, inB As Variant) As Boolean
' returns true if values doesn't match, Including Null <>2 etc.. ' Null,Null --> False.  Null, 1 --> True. 1,1 --> False. A,B --> True.
'input: anything if "=" has a meaning for that datatype.
On Error GoTo myerr

Dim OneNullflag As Boolean, Compflag As Boolean
OneNullflag = IsNull(inA) Xor IsNull(inB) 'csak az egyik Null?
Compflag = Not (IsNull(inA) Or IsNull(inB)) 'egyik sem Null?

If OneNullflag = True Then
   compdiff = True ' Null <> 2
Else
   If Compflag = True Then
      ' No Nulls
      If inA = inB Then
         compdiff = False ' 1=1 ; (1<>1) = False
      Else
         compdiff = True ' 1<>2
      End If
   Else
      compdiff = False ' Null = Null
   End If
End If

Exit Function
myerr:
   ERT = "compdiff()"
   ert2 = ert2 & " ->" & ERT
   ert3 = ""
   Call show_ert(err.Number, erl)
End Function  

And this is the function to create the connection:

Private Function dsntest(strCnn1 As Variant) As Boolean
' used by cnn_startup()
On Error GoTo myerr

   dsntest = False
   If IsNull(strCnn1) Then Exit Function
   If Len(CStr(strCnn1)) < 2 Then Exit Function

Dim dbs As DAO.Database, qdf As DAO.QueryDef, rn As Long

   Set dbs = CurrentDb()
   Set qdf = dbs.CreateQueryDef("")
   
   qdf.ReturnsRecords = False
   qdf.Connect = strCnn1
   'Any VALID SQL statement that runs on server will work below.
   qdf.SQL = "Select 0;" '"SET @icon = 1;" ' doesn't run on Oracle server --> sqlstr parameter
   
   On Error Resume Next
     qdf.Execute
     rn = err.Number
   On Error GoTo myerr
   
   If rn = 0 Then dsntest = True

cleanup:
   Set qdf = Nothing
   Set dbs = Nothing
   
   Exit Function
   
myerr:
   dsntest = False
   ERT = "dsntest"
   ert2 = ert2 & " ->" & ERT
   ert3 = ""
   Call show_ert(err.Number, erl)
   GoTo cleanup
End Function

We basically create a passtrough query wich opens the connection, than we throw it away, so there will not be any saved queries with the password.

Bonus info: I recommend to use odbc driver version 8.0.26. 8.0.29 might work with NO_DATE_OVERFLOW=1. See this for further details: https://bugs.mysql.com/bug.php?id=107235. 0.27 and 0.28 have other Access related bugs.

Bonus info 2: MS Access VBA has a half way documented erl object. I have a line numbering function that I run during the release process. If an error occurs on a numbered VBA line, it will be stored in the erl until you leave the sub/function or you clear the error. Show_ert() sends some telemetry data including erl to the server, so I can monitor client side errors.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文