多部分标识符无法绑定


196

我在SO上看到过类似的错误,但是我没有找到解决问题的方法。我有一个SQL查询,如:

SELECT DISTINCT
        a.maxa ,
        b.mahuyen ,
        a.tenxa ,
        b.tenhuyen ,
        ISNULL(dkcd.tong, 0) AS tongdkcd
FROM    phuongxa a ,
        quanhuyen b
        LEFT OUTER JOIN ( SELECT    maxa ,
                                    COUNT(*) AS tong
                          FROM      khaosat
                          WHERE     CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
                                                              AND
                                                              'Sep 5 2011'
                          GROUP BY  maxa
                        ) AS dkcd ON dkcd.maxa = a.maxa
WHERE   a.maxa <> '99'
        AND LEFT(a.maxa, 2) = b.mahuyen
ORDER BY maxa;

当我执行此查询时,错误结果是: 不能绑定多部分标识符“ a.maxa”。为什么?
P / s:如果我将查询分为2个单独的查询,则运行正常。

SELECT DISTINCT
        a.maxa ,
        b.mahuyen ,
        a.tenxa ,
        b.tenhuyen
FROM    phuongxa a ,
        quanhuyen b
WHERE   a.maxa <> '99'
        AND LEFT(a.maxa, 2) = b.mahuyen
ORDER BY maxa;

SELECT  maxa ,
        COUNT(*) AS tong
FROM    khaosat
WHERE   CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
                                        AND     'Sep 5 2011'
GROUP BY maxa;

phuongxa表是否包含一列maxa
Michael Petrotta 2011年

1
如果您在2011
user710502'9

是的,有。如果我将查询指定给2
个子

听起来您在错误的数据库上执行。在查询的开头添加“ USE [数据库名称]”语句,以查看是否仍然收到错误。
brian

1
不,我在上面说过,如果我将查询分为2个单独的查询,它将运行okey。
PhamMinh 2011年

Answers:


226

您正在将隐式联接与显式联接混合在一起。允许这样做,但是您需要知道如何正确执行此操作。

事实是,显式联接(使用JOIN关键字实现的联接)优先于隐式联接(“逗号”联接,在WHERE子句中指定联接条件)。

以下是查询的概述:

SELECT
  
FROM a, b LEFT JOIN dkcd ON 
WHERE 

您可能希望它的行为如下:

SELECT
  
FROM (a, b) LEFT JOIN dkcd ON 
WHERE 

即,表的组合ab接合用表dkcd。实际上,正在发生的是

SELECT
  
FROM a, (b LEFT JOIN dkcd ON …)
WHERE 

也就是说,正如您可能已经了解的那样,仅dkcd针对b和进行联接b,然后将联接的结果a与该WHERE子句组合并进一步过滤。在这种情况下,aON子句中的任何引用均无效,此时a是未知的。这就是为什么您收到错误消息的原因。

如果您是我,我可能会尝试重写此查询,一种可能的解决方案可能是:

SELECT DISTINCT
  a.maxa,
  b.mahuyen,
  a.tenxa,
  b.tenhuyen,
  ISNULL(dkcd.tong, 0) AS tongdkcd
FROM phuongxa a
  INNER JOIN quanhuyen b ON LEFT(a.maxa, 2) = b.mahuyen
  LEFT OUTER JOIN (
    SELECT
      maxa,
      COUNT(*) AS tong
    FROM khaosat
    WHERE CONVERT(datetime, ngaylap, 103) BETWEEN 'Sep 1 2011' AND 'Sep 5 2011'
    GROUP BY maxa
  ) AS dkcd ON dkcd.maxa = a.maxa
WHERE a.maxa <> '99'
ORDER BY a.maxa

在此先将表格ab连接起来,然后将结果连接到dkcd。基本上,这是相同的查询是你的,只是使用不同的语法的连接,这使得有很大的差别之一:参考a.maxadkcd的连接条件是现在绝对有效。

正如@Aaron Bertrand正确指出的那样,您可能应该在子句中maxa使用特定的别名(可能是)进行限定。aORDER BY


ORDER BY maxa仍然是模棱两可的,不是吗?另外,我会谨慎选择“ 2011年9月1日”作为日期,不适用于其他语言/地区设置。
亚伦·贝特朗

@Aaron:同意ORDER BY maxa,谢谢。至于日期,我相信这就是OP选择在其环境中指定日期的方式。
Andriy M

“显式连接...优先于隐式连接” –请您为此提供引用吗?例如,是在SQL标准中定义的还是产品功能?谢谢。
2011年

1
@onedaywhen:恐怕到目前为止,这不过是我这一边的观察而已。我不是首先在这里谈论联接的优先顺序,这让我有些放心,但是除此之外,我很高兴自己找到任何形式的官方确认信息。
Andriy M

1
就我而言,我忘记了在连接字符串以构建sql时要放空格,因此'FROM dbo.table_a a'+'INNER JOIN dbo.table_b b'变为'FROM dbo.table_a aINNER JOIN dbo.table_b b',它感到困惑,并给了我这个错误信息。细节,细节,细节。
Guy Schalnat

40

有时,当您以错误的方式在查询中使用架构(dbo)时,会发生此错误。

例如,如果您编写:

select dbo.prd.name
from dbo.product prd

您将得到错误。

在这种情况下,请将其更改为:

select prd.name
from dbo.product prd

1
这是一件很烦人的事,我花了很长时间才弄清楚。谢谢 最令人讨厌的部分是有时对此事na,但有时却不正常
DanteTheSmith

12

如果您给了alies名称,请将其更改为实际名称

例如

SELECT  
    A.name,A.date
  FROM [LoginInfo].[dbo].[TableA] as A
   join 
  [LoginInfo].[dbo].[TableA] as B 
  on  [LoginInfo].[dbo].[TableA].name=[LoginInfo].[dbo].[TableB].name;

更改为

SELECT  
    A.name,A.date
  FROM [LoginInfo].[dbo].[TableA] as A
   join 
  [LoginInfo].[dbo].[TableA] as B 
  on  A.name=B.name;

1
另外,如果要构建sql字符串,请注意在行尾缺少尾随空格。当它加入下面的下一个INNER JOIN行时,它将我的别名M转换为MINNER。SQL事件探查器显示执行的字符串有助于解决我的问题。(在此评论,因为它与别名v实际名称问题有关)
西蒙(Simon

哇@Simon谢谢,我什至没有想到这一点,并把头撞在墙上试图弄清楚为什么我的查询不起作用,我在一个回车符的末尾缺少空格!
buradd

9

我在SQL SERVER中遇到相同的错误消息,因为我有多个联接,所以更改联接的顺序可以为我解决。



2

我在JDBC中遇到了相同的错误。检查一切,我的查询很好。原来,在where子句中我有一个参数:

where s.some_column = ?

我传入的参数的值为null。这同样会产生误导性的错误,因为当您搜索Internet时,您最终会发现查询结构出了点问题,但我的情况并非如此。只是以为有人可能会遇到同样的问题


2

对我有用的是将WHERE子句更改为SELECT子查询

从:

    DELETE FROM CommentTag WHERE [dbo].CommentTag.NoteId = [dbo].FetchedTagTransferData.IssueId

至:

    DELETE FROM CommentTag WHERE [dbo].CommentTag.NoteId = (SELECT NoteId FROM FetchedTagTransferData)

1

我是SQL的新手,但是在我参加的课程中遇到了这个问题,发现将查询分配给项目特别有助于消除多部分错误。例如,我创建的项目是CTU SQL Project,因此我确保以USE [CTU SQL Project]作为第一行来启动脚本,如下所示。

USE [CTU SQL Project]
SELECT Advisors.First_Name, Advisors.Last_Name...and so on.

1
当您说“项目”时,我假设您的意思是数据库而不是投影。use语句只是将您要确定查询范围的数据库更改为
Charleh

是的,Charleh项目和我正在使用的数据库一样。我不确定我的数据库在做什么错,但是指出“使用”和特定的数据库范围可以消除我的错误。
Bogartz '16

1

如果出现此错误UPDATE,请JOIN使用导致该错误的列/字段再次检查表格上的。

在我的情况下,这是由于缺少JOIN自身,由于字段未知而产生了相同的错误(如Andriy所指出的)。



1
SELECT DISTINCT
        phuongxa.maxa ,
        quanhuyen.mahuyen ,
        phuongxa.tenxa ,
        quanhuyen.tenhuyen ,
        ISNULL(dkcd.tong, 0) AS tongdkcd
FROM    phuongxa ,
        quanhuyen
        LEFT OUTER JOIN ( SELECT    khaosat.maxa ,
                                    COUNT(*) AS tong
                          FROM      khaosat
                          WHERE     CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
                                                              AND
                                                              'Sep 5 2011'
                          GROUP BY  khaosat.maxa
                        ) AS dkcd ON dkcd.maxa = maxa
WHERE   phuongxa.maxa <> '99'
        AND LEFT(phuongxa.maxa, 2) = quanhuyen.mahuyen
ORDER BY maxa;

如果出现多部分绑定问题,请使用表名称本身而不是使用别名。
SVaidya

1

我的错误是使用表中不存在的字段。

table1.field1 =>不存在

table2.field1 =>是正确的

更正您的表名称。

我的错误是因为使用WITH

WITH RCTE AS (
   SELECT...
)
SELECT RCTE.Name, ...
FROM 
  RCTE INNER JOIN Customer
  ON RCTE.CustomerID = Customer.ID 

当与其他表结合使用时...


1

你忘了参加一些餐桌吗?如果不是,那么您可能需要使用一些别名。


1

我也在这个错误中苦苦挣扎,最终得到了与答案相同的策略。我加入我的答案只是为了确认这是一个应该起作用的策略。

这是一个示例,在该示例中,我首先在两个我知道有数据的表之间进行一个内部联接,然后在可能具有对应行可以为空的表上进行两个左外部联接。您可以混合使用内部联接和外部联接来获得整个表中数据的结果,而不是在表之间执行默认的逗号分隔语法,从而错过所需联接中的行。

use somedatabase
go 

select o.operationid, o.operatingdate, p.pasid, p.name as patientname, o.operationalunitid, f.name as operasjonsprogram,  o.theaterid as stueid, t.name as stuenavn, o.status as operasjonsstatus from operation o 
inner join patient p on o.operationid = p.operationid 
left outer join freshorganizationalunit f on f.freshorganizationalunitid = o.operationalunitid
left outer join theater t on t.theaterid = o.theaterid
where (p.Name like '%Male[0-9]%' or p.Name like '%KFemale [0-9]%')

第一:在您希望数据匹配的表之间进行内部联接。第二部分:继续进行外部联接以尝试检索其他表中的数据,但是如果表外部联接没有得到相应的数据或与您在on谓词/条件中设置的条件相匹配,这将不会过滤出您的结果集。


0

,在SELECT语句中的列名称之间缺少逗号也可能导致此错误。

例如:

SELECT MyCol1, MyCol2 MyCol3 FROM SomeTable;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.