我有一个名为 FietsAantDagen 的表单,一个名为 QueryFietsAantDagen 的查询和一个名为 Txtinput 的文本框。我正在尝试对SQL Server使用传递查询,并在我的查询中使用文本格式的输入作为输入。
查询:
SELECT
Fiets_id,
Fiets_Type,
SUM(DATEDIFF(DAY, Huurovereenkomst_Begin_datum, Huurovereenkomst_Eind_datum)) AS AantalDagen
FROM
Fiets
INNER JOIN
HuurovereenkomstFiets
ON HuurovereenkomstFiets_Fiets_id = Fiets_id
INNER JOIN
Huurovereenkomst
ON Huurovereenkomst_id = HuurovereenkomstFiets_Huurovereenkomst_id
WHERE
YEAR(Huurovereenkomst_Begin_datum) = [Forms]![FietsAantDagen]![Txtinput]
AND YEAR(Huurovereenkomst_Eind_datum) = [Forms]![FietsAantDagen]![Txtinput]
GROUP BY
Fiets_id,
Fiets_Type
在将此查询作为传递查询运行时,我收到以下错误:
ODBC:运行时错误[Microsoft] [SQL Server Native Client 11.0] [SQL 服务器]关键字' WHERE' /(#156)
附近的语法不正确
问题是我在传递查询中使用Access文本表单值,如果是,我该怎么做才能解决它?
我在读取你需要添加()的另一个Overflow问题,我做了,现在我得到了错误:
不支持JOIN表达式。
我疯了......
答案 0 :(得分:1)
如果您没有直接使用SQL服务器,那么最好通过查询创建两个pass。
查询#1 - 这是您的原始SQL 例如:
SELECT
Fiets_id,
Fiets_Type,
SUM(DATEDIFF(DAY, Huurovereenkomst_Begin_datum,
Huurovereenkomst_Eind_datum)) AS AantalDagen
FROM
Fiets
INNER JOIN
HuurovereenkomstFiets
ON HuurovereenkomstFiets_Fiets_id = Fiets_id
INNER JOIN
Huurovereenkomst
ON Huurovereenkomst_id = HuurovereenkomstFiets_Huurovereenkomst_id
WHERE
YEAR(Huurovereenkomst_Begin_datum) = [StartYear]
AND YEAR(Huurovereenkomst_Eind_datum) = [EndYear]
GROUP BY
Fiets_id,
Fiets_Type
查询#2 - 这是一个应用程序范围的查询,您可以反复使用任何原始t-SQL(SQL服务器通过)。然后你在代码中这样:
Dim rst As DAO.Recordset
Dim strSQL As String
strSQL = CurrentDb.QueryDefs("MyQ1").SQL
srtSQL = Replace(strSQL, "[YearStart]", [Forms]![FietsAantDagen]![Txtinput])
strSQL = Replace(strSQL, "[YearEnd]", [Forms]![FietsAantDagen]![Txtinput])
With CurrentDb.QueryDefs("qryPassR")
.SQL = strSQL
.ReturnsRecords = True
Set rst = .OpenRecordset
End With
但是,如果你有能力使用SQL服务器,并创建一个proc,那么我建议你创建这样的存储过程:
CREATE PROCEDURE SelectDates
@StartYear int,
@EndYear int
AS
BEGIN
SET NOCOUNT ON;
SELECT
Fiets_id,
Fiets_Type,
SUM(DATEDIFF(DAY, Huurovereenkomst_Begin_datum, Huurovereenkomst_Eind_datum)) AS AantalDagen
FROM
Fiets
INNER JOIN
HuurovereenkomstFiets
ON HuurovereenkomstFiets_Fiets_id = Fiets_id
INNER JOIN
Huurovereenkomst
ON Huurovereenkomst_id = HuurovereenkomstFiets_Huurovereenkomst_id
WHERE
YEAR(Huurovereenkomst_Begin_datum) = @StartYear
AND YEAR(Huurovereenkomst_Eind_datum) = @EndYear
GROUP BY
Fiets_id,
Fiets_Type
END
然后在访问中,您使用此:
Dim rst As DAO.Recordset
With CurrentDb.QueryDefs("qryPassR")
.SQL = "exec SelectDates " & [Forms]![FietsAantDagen]![Txtinput] & "," & _
[Forms]![FietsAantDagen]![Txtinput]
.ReturnsRecords = True
Set rst = .OpenRecordset
End With
因此,通过传递参数可以减少与SQL注入有关的大多数问题。 当然,如果你不能创建存储过程,或者没有权限,那么你必须采用上面的第一个想法。您当然也可以在第一个建议中将原始SQL插入到代码编辑器中,但我发现使用额外的查询来“只”保存原始SQL,然后将SQL修改为第二个直通查询消除了需要对于VBA代码编辑器中的混乱SQL。
答案 1 :(得分:0)
当您运行Pass-Through查询时,其SQL文本将按原样发送到数据库服务器,不会对任何内容进行评估。因此,在Pass-Through查询中包含[Forms]![FietsAantDagen]![Txtinput]
将永远不会有效。
您正在使用
走上正轨SELECT * FROM fnFietsAantDagenPerJaar([Forms]![FietsAantDagen]![Txtinput])
但你需要自己提供参数,因为(见上文)。
所以你需要构建Pass-Through SQL,例如使用此VBA程序:
Private Sub txtInput_AfterUpdate()
Dim QD As DAO.QueryDef
Dim lYear As Long
' Make sure we pass a number to the SQL Server function
lYear = Val(Me!txtInput)
If lYear > 0 Then
Set QD = CurrentDb.QueryDefs("QueryFietsAantDagen")
QD.SQL = "SELECT * FROM fnFietsAantDagenPerJaar(" & lYear & ")"
Set QD = Nothing
' After changing the query SQL, requery the form
' This assumes that your form is bound to Pass-Through query QueryFietsAantDagen
Me.Requery
End If
End Sub
答案 2 :(得分:0)
传递查询仅在连接的外部数据库引擎(此处为SQL Server)上运行,并且在MS Access中看不到任何内容,只显示该外部环境中的所有内容。
考虑调整传递查询以避免任何MS Access评估,并添加年分组以聚合查询。然后使用表单值在本地Access查询过滤中查询此结果集以查找所需的年条件。下面为了清晰起见添加了表别名(如果不正确则调整)。
传递 (无WHERE
子句,但已展开SELECT
和GROUP BY
)
SELECT
f.Fiets_id,
f.Fiets_Type,
YEAR(h.Huurovereenkomst_Begin_datum) As BeginYear,
YEAR(h.Huurovereenkomst_Eind_datum) As EndYear,
SUM(DATEDIFF('d', h.Huurovereenkomst_Begin_datum,
h.Huurovereenkomst_Eind_datum)) AS AantalDagen
FROM
HuurovereenkomstFiets_LinkTable hf
INNER JOIN
Fiets_LinkTable f
ON hf.HuurovereenkomstFiets_Fiets_id = f.Fiets_id
INNER JOIN
Huurovereenkomst_LinkTable h
ON h.Huurovereenkomst_id = hf.HuurovereenkomstFiets_Huurovereenkomst_id
GROUP BY
f.Fiets_id,
f.Fiets_Type,
YEAR(h.Huurovereenkomst_Begin_datum),
YEAR(h.Huurovereenkomst_Eind_datum)
本地查询
SELECT
t.Fiets_id,
t.Fiets_Type,
t.AantalDagen
FROM
myPassThroughQuery t
WHERE t.BeginYear = [Forms]![FietsAantDagen]![Txtinput]
AND t.EndYear = [Forms]![FietsAantDagen]![Txtinput]
或者,考虑使用SQL Server中的链接表(具有与传递相同的ODBC连接),其中Access可将它们视为本地表。因此,您可以使用表单日期值运行查询。请注意,您必须将语法转换为遵守Access' SQL方言,如DATEDIFF
和JOIN
括号。性能可能因引擎改变而有所不同,但是测试。
链接表本地查询
SELECT
f.Fiets_id,
f.Fiets_Type,
SUM(DATEDIFF('d', h.Huurovereenkomst_Begin_datum,
h.Huurovereenkomst_Eind_datum)) AS AantalDagen
FROM
(HuurovereenkomstFiets_LinkTable hf
INNER JOIN
Fiets_LinkTable f
ON hf.HuurovereenkomstFiets_Fiets_id = f.Fiets_id)
INNER JOIN
Huurovereenkomst_LinkTable h
ON h.Huurovereenkomst_id = hf.HuurovereenkomstFiets_Huurovereenkomst_id
WHERE YEAR(h.Huurovereenkomst_Begin_datum) = [Forms]![FietsAantDagen]![Txtinput]
AND YEAR(h.Huurovereenkomst_Eind_datum) = [Forms]![FietsAantDagen]![Txtinput]
GROUP BY
f.Fiets_id,
f.Fiets_Type
要自动创建链接表,请使用DoCmd.TransferDatabase。否则,请使用功能区上的External Data / ODBC Database图标并完成设置向导。
DoCmd.TransferDatabase acLink, "ODBC Database", _
"ODBC;DRIVER={SQL Server};Server=<ServerAddress>;Database=<DBname>;Trusted_Connection=Yes;", _
acTable, "HuurovereenkomstFiets", "HuurovereenkomstFiets_LinkedTable"