web-dev-qa-db-fra.com

Comment se débarrasser d'un conflit de classement dans une requête SQL Server?

Je travaille sur une vue dans laquelle j'utilise une jointure interne sur deux tables provenant de deux serveurs différents. Nous utilisons un serveur lié. Lors de l'exécution de la requête, je reçois ce message:

Impossible de résoudre le conflit de classement entre "SQL_Latin1_General_CP1_CI_AS" et "Arabic_CI_AS" dans l'opération égal à.

Je ne sais pas grand chose de la collation. En cherchant sur Internet, je trouve des solutions pour utiliser COLLATE, mais le concept de COLLATE n’est pas clair pour moi. Cela changera-t-il quelque chose pour l'une des bases de données? Je cherche une solution sans rien changer pour les bases de données.

Tout bon matériel d'apprentissage pour ces concepts est le bienvenu.

31
wsDev

Vous pouvez résoudre le problème en forçant le classement utilisé dans une requête à être un classement particulier, par exemple. SQL_Latin1_General_CP1_CI_AS ou DATABASE_DEFAULT. Par exemple:

SELECT MyColumn
FROM FirstTable a
INNER JOIN SecondTable b
ON a.MyID COLLATE SQL_Latin1_General_CP1_CI_AS = 
b.YourID COLLATE SQL_Latin1_General_CP1_CI_AS

Dans la requête ci-dessus, a.MyID et b.YourID seraient des colonnes avec un type de données textuel. Utiliser COLLATE forcera la requête à ignorer le classement par défaut de la base de données et à utiliser le classement fourni, dans ce cas SQL_Latin1_General_CP1_CI_AS.

En gros, chaque base de données possède son propre classement qui "fournit des règles de tri, des propriétés de sensibilité de casse et d'accentuation pour vos données" (from http://technet.Microsoft.com/fr/library /ms143726.aspx ) et s'applique aux colonnes avec des types de données textuelles , par exemple VARCHAR, CHAR, NVARCHAR, etc. Lorsque deux bases de données ont des classements différents, vous ne pouvez pas comparer les colonnes de texte avec un opérateur comme égal à (=) sans résoudre le conflit entre les deux collations disparates.

55
rory.ap

J'ai résolu un problème similaire en encapsulant la requête dans une autre requête ...

La requête initiale était en train de trouver des colonnes de sortie individuelles, certaines provenant de sous-requêtes avec une fonction Max ou Sum, et d'autres avec des substitutions de casse "distinctes" ou autres.

J'ai rencontré l'erreur de classement après avoir tenté de créer un seul champ de sortie avec ...

select
rtrim(field1)+','+rtrim(field2)+','+...

La requête s'exécuterait telle que je l'ai écrite, mais l'erreur se produirait après l'enregistrement et le rechargement de SQL.

Wound Up le réparer avec quelque chose comme ...

select z.field1+','+z.field2+','+... as OUTPUT_REC
from (select rtrim(field1), rtrim(field2), ... ) z

Certains champs sont "max" dans une sous-requête, avec une substitution de casse si null et d'autres sont des champs de date, et certains sont des jointures à gauche (peut-être NULL) ... en d'autres termes, des types de champs mixtes. Je pense que cela est dû au fait que le classement des systèmes d'exploitation et de la base de données est légèrement différent, mais en convertissant tout en chaînes coupées avant la sélection finale, le problème est trié, le tout dans le code SQL.

3
PStuart

J'ai eu des problèmes avec les classements car j'avais la plupart des tables avec Modern_Spanish_CI_AS, Mais quelques-unes, que j'avais héritées ou copiées d'une autre base de données, avaient un classement SQL_Latin1_General_CP1_CI_AS.

Dans mon cas, le moyen le plus simple de résoudre le problème a été le suivant:

  1. J'ai créé une copie des tables qui étaient "Amérique latine", en utilisant la table de script comme ...
  2. Les nouvelles tables ont bien évidemment acquis la collation "Moderne Espagnol" de ma base de données
  3. J'ai copié les données de ma table 'Amérique latine' dans la nouvelle, effacé l'ancienne et renommé la nouvelle.

J'espère que cela aide les autres utilisateurs.

0
Ramon Baiges