使用 VBA 的 DAO 直通查询:"Error 3131 Syntax error in from clause"
DAO passthrough query using VBA: "Error 3131 Syntax error in from clause"
我复制了一个在 Stack Overflow 中找到的解决方案,并根据我的需要对其进行了调整。
Public Function getAssortmentTypes(Optional personId As Variant) As DAO.Recordset 'personId is integer
Dim strQuery As String
Dim qdf As DAO.QueryDef
Dim rst As DAO.Recordset
If IsMissing(personId) Then
strQuery = "SELECT assortment_type.type_id, assortment_type.type_name AS qryTest FROM assortment_type"
Else
strQuery = "SELECT * FROM get_non_deleted_assortment_types_by_user(" & personId & ")"
End If
Set qdf = CurrentDb.CreateQueryDef("")
With qdf
.SQL = strQuery
.Connect = getDBConnectionString
.ReturnsRecords = True
End With
Set rst = qdf.OpenRecordset
Debug.Print rst!qryTest
Set getAssortmentTypes = rst
End Function
在我的 postgresql 数据库中,我确实有一个工作函数和适当的表。我用 DBEaver 测试了 sql 个查询,它们有效。
当我调用不带参数的函数时,我只收到一行(应该是大约 30 行)。
使用参数我希望过滤结果集但收到
"Error 3131 Syntax error in from clause".
始终在 设置 SQL 之前 设置连接字符串。
当您设置 SQL 时,DAO 不知道这将在以后成为直通查询,因此它尝试将其解析为 Access SQL,但显然失败了,因为它是无效访问 SQL.
只需更改顺序:
With qdf
.Connect = getDBConnectionString
.ReturnsRecords = True
.SQL = strQuery
End With
请注意,您应该 ,并且通常在使用外部数据源时使用 ADO 而不是 DAO。 DAO 非常适合 Access,但提供的外部数据源功能较少。例如,ADO 不会在实际需要之前尝试解析 SQL 字符串。
放弃对 DAO 和 QueryDefs 的需要,使用带有命令参数化的 ADO,然后可以将其绑定到记录集:
' SET REFERENCE TO Microsoft ActiveX Data Object #.# Library
Public Function getAssortmentTypes(Optional personId As Variant) As ADODB.Recordset
Dim conn As ADODB.Connection
Dim rst As ADODB.Recordset
Dim cmd As ADODB.Command
Set conn As New ADODB.Connection
conn.Open getDBConnectionString
' PREPARED STATEMENT WITH QMARKS ?
If IsMissing(personId) Then
strQuery = "SELECT assortment_type.type_id, assortment_type.type_name AS qryTest FROM assortment_type"
Else
strQuery = "SELECT * FROM get_non_deleted_assortment_types_by_user(?)"
End If
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = conn
.CommandText = strQuery
.CommandType = adCmdText
' BIND PARAMETER
.Parameters.Append .CreateParameter("user_param", adInteger, adParamInput, , personId)
' EXECUTE QUERY AND BIND INTO RECORDSET
Set rst = .Execute
End With
Set cmd = Nothing
Set getAssortmentTypes = rst
End Function
尝试省略“DAO”。在您的 Recordset 和维度语句中添加前缀。更高版本的 Access 了解您的需求。
不推荐引入ADO
问题似乎是您的第一个 SQL 查询将(并且确实)作为 linked table 工作,因此可以工作,因为它不是传递查询.
第二个 sql 失败,因为它仍然尝试使用“访问”sql,而不是 postgresSQL 语法。
我建议您创建一个 PT 查询(使用 Access UI)。在设计器中,确保你 select pass-though:
因此,就像 linked tables - 将连接字符串放入该 PT 查询中。
不要在代码中放置或试图放置连接字符串。因此,您的 re-link 例程还可以包括 re-link PT 查询。
您现在可以使用此代码:
Public Function getAssortmentTypes(Optional personId As Variant) As DAO.Recordset 'personId is integer
Dim rst As DAO.Recordset
Dim strQuery As String
If IsMissing(personId) Then
strQuery = "SELECT assortment_type.type_id, assortment_type.type_name AS qryTest FROM assortment_type"
Else
strQuery = "SELECT * FROM get_non_deleted_assortment_types_by_user(" & personId & ")"
End If
With CurrentDb.QueryDefs("qryPT")
.SQL = strQuery
Set rst = .OpenRecordset
End With
Debug.Print rst!qryTest
Set getAssortmentTypes = rst
End Function
因此,创建一个名为(对于此示例)qryPT
的 PT 查询
我复制了一个在 Stack Overflow 中找到的解决方案,并根据我的需要对其进行了调整。
Public Function getAssortmentTypes(Optional personId As Variant) As DAO.Recordset 'personId is integer
Dim strQuery As String
Dim qdf As DAO.QueryDef
Dim rst As DAO.Recordset
If IsMissing(personId) Then
strQuery = "SELECT assortment_type.type_id, assortment_type.type_name AS qryTest FROM assortment_type"
Else
strQuery = "SELECT * FROM get_non_deleted_assortment_types_by_user(" & personId & ")"
End If
Set qdf = CurrentDb.CreateQueryDef("")
With qdf
.SQL = strQuery
.Connect = getDBConnectionString
.ReturnsRecords = True
End With
Set rst = qdf.OpenRecordset
Debug.Print rst!qryTest
Set getAssortmentTypes = rst
End Function
在我的 postgresql 数据库中,我确实有一个工作函数和适当的表。我用 DBEaver 测试了 sql 个查询,它们有效。
当我调用不带参数的函数时,我只收到一行(应该是大约 30 行)。
使用参数我希望过滤结果集但收到
"Error 3131 Syntax error in from clause".
始终在 设置 SQL 之前 设置连接字符串。
当您设置 SQL 时,DAO 不知道这将在以后成为直通查询,因此它尝试将其解析为 Access SQL,但显然失败了,因为它是无效访问 SQL.
只需更改顺序:
With qdf
.Connect = getDBConnectionString
.ReturnsRecords = True
.SQL = strQuery
End With
请注意,您应该
放弃对 DAO 和 QueryDefs 的需要,使用带有命令参数化的 ADO,然后可以将其绑定到记录集:
' SET REFERENCE TO Microsoft ActiveX Data Object #.# Library
Public Function getAssortmentTypes(Optional personId As Variant) As ADODB.Recordset
Dim conn As ADODB.Connection
Dim rst As ADODB.Recordset
Dim cmd As ADODB.Command
Set conn As New ADODB.Connection
conn.Open getDBConnectionString
' PREPARED STATEMENT WITH QMARKS ?
If IsMissing(personId) Then
strQuery = "SELECT assortment_type.type_id, assortment_type.type_name AS qryTest FROM assortment_type"
Else
strQuery = "SELECT * FROM get_non_deleted_assortment_types_by_user(?)"
End If
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = conn
.CommandText = strQuery
.CommandType = adCmdText
' BIND PARAMETER
.Parameters.Append .CreateParameter("user_param", adInteger, adParamInput, , personId)
' EXECUTE QUERY AND BIND INTO RECORDSET
Set rst = .Execute
End With
Set cmd = Nothing
Set getAssortmentTypes = rst
End Function
尝试省略“DAO”。在您的 Recordset 和维度语句中添加前缀。更高版本的 Access 了解您的需求。
不推荐引入ADO
问题似乎是您的第一个 SQL 查询将(并且确实)作为 linked table 工作,因此可以工作,因为它不是传递查询.
第二个 sql 失败,因为它仍然尝试使用“访问”sql,而不是 postgresSQL 语法。
我建议您创建一个 PT 查询(使用 Access UI)。在设计器中,确保你 select pass-though:
因此,就像 linked tables - 将连接字符串放入该 PT 查询中。
不要在代码中放置或试图放置连接字符串。因此,您的 re-link 例程还可以包括 re-link PT 查询。
您现在可以使用此代码:
Public Function getAssortmentTypes(Optional personId As Variant) As DAO.Recordset 'personId is integer
Dim rst As DAO.Recordset
Dim strQuery As String
If IsMissing(personId) Then
strQuery = "SELECT assortment_type.type_id, assortment_type.type_name AS qryTest FROM assortment_type"
Else
strQuery = "SELECT * FROM get_non_deleted_assortment_types_by_user(" & personId & ")"
End If
With CurrentDb.QueryDefs("qryPT")
.SQL = strQuery
Set rst = .OpenRecordset
End With
Debug.Print rst!qryTest
Set getAssortmentTypes = rst
End Function
因此,创建一个名为(对于此示例)qryPT
的 PT 查询