ADO 无法识别旧式 SQL 连接。不知道如何在此特定查询中使用新式语法

Posted

技术标签:

【中文标题】ADO 无法识别旧式 SQL 连接。不知道如何在此特定查询中使用新式语法【英文标题】:ADO not recognising old-style SQL joins. Don't know how to use new-style syntax in this particular query 【发布时间】:2020-01-08 14:20:14 【问题描述】:

我正在使用 VBA 进行编码,使用 ADO 来查询与 Access 兼容 (JET) 的数据库。我有以下查询,效果很好:

SELECT
   Answers.UserName AS UserName,
   COUNT(Answers.Correct) AS CorrectAnswers
FROM
   Answers
WHERE
   Answers.QuizID=17
   AND (SELECT COUNT(A.UserName) FROM Answers A WHERE A.QuizID=17 AND A.UserName=Answers.UserName)=30
GROUP BY Answers.UserName

这基本上是一个问答测验,其中每个答案都写入答案表。 Answers 表的一列是“UserName”,其中包含提交答案的用户的登录 ID。

但是,我想显示用户的全名,而不是登录 ID。这已经存储在一个单独的表“用户”中。在“用户”表中有两列:用户名和全名。

当然,显示全名的正确方法是使用如下连接:

SELECT
   Users.FullName AS FullName,
   COUNT(Answers.Correct) AS CorrectAnswers
FROM
   Answers,
   Users
WHERE
   Answers.QuizID=17
   AND (SELECT COUNT(A.UserName) FROM Answers A WHERE A.QuizID=17 AND A.UserName=Answers.UserName)=30
   AND Users.UserName=Answers.UserName
GROUP BY Users.UserName

这也有效...只要用户名存在于用户表中。但是,如果出于某种原因,用户没有在 Users 表中注册,而不是返回 NULL,则不会完全选择记录。

在“旧式”连接语法中,我将通过在上述代码的相关行上添加一个 (+) 符号来解决这个问题,因此它显示为:

AND Users.UserName=Answers.UserName(+)

这将确保返回所有记录,即使用户表中不存在匹配项。然而,当我尝试这个时,ADO 会抛出一个错误:Extra ( in query expression... etc。我推测这是因为 ADO 无法识别 (+) 语法。

所以问题是,是否有办法让 ADO 识别 (+) 连接;或者我应该如何以“新样式”连接语法编写查询以使其执行我想要的操作?

我的尝试:

SELECT
   Users.FullName AS UserName,
   COUNT(Answers.Correct) AS CorrectAnswers
FROM
   Answers,
   RIGHT JOIN Users U on Answers.Username = U.UserName
WHERE
   Answers.QuizID=17
   AND (SELECT COUNT(A.UserName) FROM Answers A WHERE A.QuizID=17 AND A.UserName=Answers.UserName)=30
GROUP BY Users.FullName

但这不起作用。它只是抛出Syntax Error。我也试过Answers后面不加逗号,没用。

有大量在线资源告诉人们如何使用新式联接。但是我没有看到任何东西告诉我如何正确地执行此操作,其中查询包括WHERE 中的其他子句。事实上,我发现所有新型连接示例都相对简单,它演示了如何在两个表上执行单个连接 - 查询没有其他元素。但是,当查询稍微复杂一点时,就不清楚应该如何使用语法了。

【问题讨论】:

去掉 RIGHT 前的逗号。除此之外,语法很好。 @jarlh 我已经尝试过了,如问题中所述。错误变为:No value given for one or more of the required parameters. 这是另一个问题... 【参考方案1】:

您需要的是 AnswersUsersLEFT 连接,基于两个表中的 ONUserName。 这意味着即使Users 中没有匹配项,也会返回Answers 的所有行。 但是还有另一个问题:在SELECT 列表中,您有FullName 列,尽管您没有将其包含在GROUP BY 子句中,这是不允许的。 所以我也将它包含在GROUP BY

SELECT
   a.UserName, u.FullName,
   COUNT(a.Correct) AS CorrectAnswers
FROM Answers a LEFT JOIN Users u
ON u.UserName = a.UserName
WHERE a.QuizID=17
  AND 
 (SELECT COUNT(aa.UserName) FROM Answers aa WHERE aa.QuizID = a.QuizID AND aa.UserName = a.UserName) = 30
GROUP BY a.UserName, u.FullName

虽然我不知道WHERE子句中子查询的原因,但我相信它可以像这样在HAVING子句中移动:

SELECT
   a.UserName, u.FullName,
   COUNT(a.Correct) AS CorrectAnswers
FROM Answers a LEFT JOIN Users u
ON u.UserName = a.UserName
WHERE a.QuizID=17
GROUP BY a.UserName, u.FullName
HAVING COUNT(*) = 30

【讨论】:

谢谢 - 这似乎工作!当然,下一步是在 SELECT 子句中用 UserName 代替 FullName,以防 FullName 为空。 NVL 似乎不起作用(我习惯于在 oracle 中工作)。 IsNull 也无法识别。我知道这是一个不同的问题,但你能建议吗? ;) 如果只需要 1 列,请将 a.UserName, u.FullName 更改为 COALESCE(u.FullName, a.UserName) 使用 COALESCE 会导致错误:Method 'Open' of object '_Recordset' failed。你确定 COALESCE 被 ADO 认可吗? 更新:COALESCE 不起作用,但 IIF(Condition, ValueIfTrue, ValueIfFalse) 起作用!谢谢。 如果您使用的是 MS Access,则 no coalesce() 不起作用。

以上是关于ADO 无法识别旧式 SQL 连接。不知道如何在此特定查询中使用新式语法的主要内容,如果未能解决你的问题,请参考以下文章

如何在此 Access-SQL server-Visual Basic 6 (ADO) 表单中不包含重复元素(主详细信息)

ado.net如何连接 oracle?

delphi怎样在ADO里用ADOproc调用数据库sql server存储过程?,用ADODATASET或者ADOQUERY又怎样调用存储过程?

将 SQL Server 凭据添加到 ADO 连接

如何在 Asp.Net Core Mvc 5.0 中将 sql 数据库与 ado.net 连接?

PHP 无法识别符号 '