Qu'est-ce qu'un «identifiant en plusieurs parties» et pourquoi ne peut-il pas être lié?

137

J'obtiens continuellement ces erreurs lorsque j'essaye de mettre à jour des tables basées sur une autre table. Je finis par réécrire la requête, changez l'ordre des jointures, changez certains groupements, puis cela fonctionne finalement, mais je ne comprends tout simplement pas.

Qu'est-ce qu'un «identifiant en plusieurs parties»?
Quand un «identifiant en plusieurs parties» ne peut-il pas être lié?
À quoi est-il lié de toute façon?
Dans quels cas cette erreur se produira-t-elle?
Quels sont les meilleurs moyens de l'empêcher?

L'erreur spécifique de SQL Server 2005 est:

L'identificateur en plusieurs parties "..." n'a pas pu être lié.

Voici un exemple:

UPDATE  [test].[dbo].[CompanyDetail]

SET Mnemonic = [dbBWKMigration].[dbo].[Company].[MNEMONIC], 
               [Company Code] = [dbBWKMigration].[dbo].[Company].[COMPANYCODE]

WHERE [Company Name] = **[dbBWKMigration].[dbo].[Company].[COMPANYNAME]**

L'erreur réelle:

Msg 4104, niveau 16, état 1, ligne 3 L'identificateur en plusieurs parties "dbBWKMigration.dbo.Company.COMPANYNAME" n'a pas pu être lié.

Même Mien
la source

Réponses:

101

Un identifiant en plusieurs parties est toute description d'un champ ou d'une table qui contient plusieurs parties - par exemple MyTable.SomeRow - s'il ne peut pas être lié, cela signifie qu'il y a un problème - soit vous avez une simple faute de frappe, soit une confusion entre table et colonne. Cela peut également être causé par l'utilisation de mots réservés dans vos noms de table ou de champ et en ne les entourant pas de []. Cela peut également être dû au fait que toutes les colonnes requises ne sont pas incluses dans la table cible.

Quelque chose comme l' invite redgate sql est génial pour éviter d'avoir à les taper manuellement (il complète même automatiquement les jointures basées sur des clés étrangères), mais n'est pas gratuit. SQL Server 2008 prend en charge intellisense hors de la boîte, bien qu'il ne soit pas aussi complet que la version redgate.

Fouet
la source
6
Toujours d'actualité: votre indice de faute de frappe m'a sauvé la journée.
Stefan
Commentaire Day Saver pour les nouveaux arrivants: il suffit de vérifier votre faute de frappe, parfois cela se produit lorsqu'il vous manque un petit morceau. Dans mon numéro, c'était OBJECT_ID (Schema.Table) sans guillemets dans une requête de plus de 50 lignes.
Abdullah Ilgaz
57

En fait, parfois, lorsque vous mettez à jour une table à partir des données d'une autre table, je pense que l'un des problèmes courants à l'origine de cette erreur est lorsque vous utilisez les abréviations de votre table de manière incorrecte ou lorsqu'elles ne sont pas nécessaires . La déclaration correcte est ci-dessous:

Update Table1
Set SomeField = t2.SomeFieldValue 
From Table1 t1 
Inner Join Table2 as t2
    On t1.ID = t2.ID

Notez que la SomeFieldcolonne de Table1 n'a pas le t1qualificatif comme t1.SomeFieldmais est juste SomeField.

Si l'on essaie de le mettre à jour en spécifiant t1.SomeFieldl'instruction renverra l'erreur en plusieurs parties que vous avez remarquée.

amadelle
la source
3
L'ajout d'alias de table dans le champ Set avant pose ce problème dans mon cas.
Malhaar Punjabi
1
C'était aussi mon problème. J'avais SET ABBREVIATION.My_Field, quand j'avais juste besoin SET.My_Field;
VSO
J'ai couru sur cette erreur en utilisant OPENJSON. `FROM cust c OUTER APPLY OPENJSON (cust.Addresses)` a jeté l'erreur. `FROM cust c OUTER APPLY OPENJSON (c.Addresses)` a rendu les résultats
Shaakir
Vous pouvez trouver l'explication de sqlservertutorial.net/sql-server-basics/sql-server-update-join utile:
CAtoOH
17

C'est probablement une faute de frappe. Recherchez les endroits dans votre code où vous appelez [schema]. [TableName] (essentiellement partout où vous faites référence à un champ) et assurez-vous que tout est correctement orthographié.

Personnellement, j'essaye d'éviter cela en utilisant des alias pour toutes mes tables. Cela aide énormément lorsque vous pouvez raccourcir un long nom de table en un acronyme de sa description (c'est-à-dire WorkOrderParts -> WOP), et rend également votre requête plus lisible.

Modifier: en prime, vous économiserez des tonnes de frappes lorsque tout ce que vous avez à taper est un alias à trois ou quatre lettres par rapport aux noms de schéma, de table et de champ tous ensemble.

Lieutenant Frost
la source
6

Liaison = votre représentation textuelle d'une colonne spécifique est mappée à une colonne physique dans une table, dans une base de données, sur un serveur.

L'identifiant en plusieurs parties peut être: MyDatabase.dbo.MyTable. Si l'un de ces identifiants est erroné, vous avez un identifiant en plusieurs parties qui ne peut pas être mappé.

La meilleure façon de l'éviter est d'écrire correctement la requête du premier coup, ou d'utiliser un plugin pour studio de gestion qui fournit intellisense et donc vous aide en évitant les fautes de frappe.

Mark S. Rasmussen
la source
5

Vous avez probablement une faute de frappe. Par exemple, si vous avez une table nommée Customer dans une base de données nommée Sales, vous pouvez la désigner comme Sales..Customer (bien qu'il soit préférable de s'y référer en incluant le nom du propriétaire (dbo est le propriétaire par défaut) comme Sales.dbo .Client.

Si vous avez tapé Ventes ... Client, vous avez peut-être reçu le message que vous avez reçu.

HLGEM
la source
4

Si vous êtes sûr qu'il ne s'agit pas d'une faute d'orthographe, c'est peut-être une faute de frappe.

Quelle collation utilisez-vous? Vérifie ça.

DBA de Pittsburgh
la source
4

Lors de la mise à jour des tables, assurez-vous de ne pas référencer le champ de votre mise à jour via l'alias.

Je viens d'avoir l'erreur avec le code suivant

update [page] 
set p.pagestatusid = 1
from [page] p
join seed s on s.seedid = p.seedid
where s.providercode = 'agd'
and p.pagestatusid = 0

J'ai dû supprimer la référence d'alias dans l'instruction set pour qu'elle se lit comme suit

update [page] 
set pagestatusid = 1
from [page] p
join seed s on s.seedid = p.seedid
where s.providercode = 'agd'
and p.pagestatusid = 0
Upio
la source
4

J'ai trouvé que j'en reçois beaucoup lorsque j'essaie d'abréger, comme:

Table1 t1, Table2 t2 
where t1.ID = t2.ID

Changer pour:

Table1, Table2 
where Table1.ID = Table2.ID

Fait fonctionner la requête et ne renvoie pas l'erreur.

jo-mso
la source
3

Code d'erreur

FROM                
    dbo.Category C LEFT OUTER JOIN           
    dbo.SubCategory SC ON C.categoryID = SC.CategoryID AND C.IsActive = 'True' LEFT OUTER JOIN          
    dbo.Module M ON SC.subCategoryID = M.subCategoryID AND SC.IsActive = 'True' LEFT OUTER JOIN          
    dbo.SubModule SM ON M.ModuleID = SM.ModuleID AND M.IsActive = 'True' AND SM.IsActive = 'True' LEFT OUTER JOIN 
    dbo.trainer ON dbo.trainer.TopicID =dbo.SubModule.subModuleID 

Code de la solution

 FROM                
    dbo.Category C LEFT OUTER JOIN           
    dbo.SubCategory SC ON C.categoryID = SC.CategoryID AND C.IsActive = 'True' LEFT OUTER JOIN          
    dbo.Module M ON SC.subCategoryID = M.subCategoryID AND SC.IsActive = 'True' LEFT OUTER JOIN          
    dbo.SubModule SM ON M.ModuleID = SM.ModuleID AND M.IsActive = 'True' AND SM.IsActive = 'True' LEFT OUTER JOIN 
    dbo.trainer ON dbo.trainer.TopicID = SM.subModuleID 

comme vous pouvez le voir, dans le code d'erreur, dbo.SubModuleest déjà défini comme SM, mais j'utilise dbo.SubModuledans la ligne suivante, il y a donc eu une erreur. utilisez le nom déclaré au lieu du nom réel. Problème résolu.

Onkar Vidhate
la source
2

J'ai eu ce problème et il s'est avéré être un alias de table incorrect. La correction de cela a résolu le problème.

Matt Setter
la source
2

Le mien mettait le schéma sur la table Alias ​​par erreur:

SELECT * FROM schema.CustomerOrders co
WHERE schema.co.ID = 1  -- oops!
inconnu
la source
2

L'ajout d'alias de table dans le champ Set avant pose ce problème dans mon cas.

Droit de mise à jour Table1 Set SomeField = t2.SomeFieldValue de table1 t1 INNER JOIN Table2 comme t2 t1.ID = t2.ID

Mauvaise mise à jour de la table1 Définir t1.SomeField = t2.SomeFieldValue à partir de la table1 t1 Table de jointure interne t1 comme t2 sur t1.ID = t2.ID

Malhaar Punjabi
la source
1

J'ai eu P.PayeeName AS 'Payer' --, et les deux lignes de commentaire ont jeté cette erreur

Andrew Day
la source
1

J'ai en fait oublié de joindre la table aux autres, c'est pourquoi j'ai eu l'erreur

Censé être de cette façon:

  CREATE VIEW reserved_passangers AS
  SELECT dbo.Passenger.PassName, dbo.Passenger.Address1, dbo.Passenger.Phone
  FROM dbo.Passenger, dbo.Reservation, dbo.Flight
  WHERE (dbo.Passenger.PassNum = dbo.Reservation.PassNum) and
  (dbo.Reservation.Flightdate = 'January 15 2004' and Flight.FlightNum =562)

Et pas de cette façon:

  CREATE VIEW reserved_passangers AS
  SELECT dbo.Passenger.PassName, dbo.Passenger.Address1, dbo.Passenger.Phone
  FROM dbo.Passenger, dbo.Reservation
  WHERE (dbo.Passenger.PassNum = dbo.Reservation.PassNum) and
  (dbo.Reservation.Flightdate = 'January 15 2004' and Flight.FlightNum = 562)
MT_Shikomba
la source
1

Mon meilleur conseil en cas d'erreur est d'utiliser [] braquets pour contourner les noms de table, l'abréviation des tables provoque parfois des erreurs, (parfois les abréviations de table fonctionnent très bien ... bizarre)

ramnz
la source
1

J'obtenais cette erreur et je ne pouvais tout simplement pas voir où était le problème. J'ai vérifié tous mes alias et ma syntaxe et rien ne semblait déplacé. La requête était similaire à celles que j'écris tout le temps.

J'ai décidé de simplement réécrire la requête (je l'avais initialement copiée à partir d'un fichier .rdl de rapport) ci-dessous, à nouveau, et tout s'est bien passé. En regardant les requêtes maintenant, elles me ressemblent, mais ma réécriture fonctionne.

Je voulais juste dire que cela pourrait valoir la peine si rien d'autre ne fonctionne.

clamum
la source
1

Lorsque vous tapez la table FROM, ces erreurs disparaissent. Tapez FROM ci-dessous ce que votre saisie puis Intellisense fonctionnera et l'identifiant en plusieurs parties fonctionnera.

David Morrow
la source
0

J'ai rencontré ce problème et je l'ai résolu, mais il y a une différence entre votre code et le mien. Malgré cela, je pense que vous pouvez comprendre ce qu'est "l'identifiant en plusieurs parties ne peut pas être lié"

Quand j'ai utilisé ce code

 select * from tbTest where email = sakira@gmail.com

J'ai rencontré un problème d'identifiant en plusieurs parties

mais lorsque j'utilise un devis unique pour l'adresse e-mail, cela a été résolu

 select * from tbTest where email = '[email protected]'
Neloy Sarothi
la source