Je viens de recevoir le code source et la base de données d'une application de mon client (il a été développé par une autre société, d'un pays différent) et l'application lève quelques exceptions liées au classement des objets:
Impossible de résoudre le conflit de classement entre "SQL_Latin1_General_CP1_CI_AS" et "Latin1_General_CI_AS" dans l'opération égale à.
J'ai vu que dans mon cas, cela se produit lorsqu'une procédure stockée crée une table #temp et que #temp
table est utilisée dans une comparaison avec les tables de l'application (la base de données d'application utilise SQL_Latin1_General_CP1_CI_AS
et tempdb
utilise Latin1_General_CI_AS
).
J'ajoute COLLATE SQL_Latin1_General_CP1_CI_AS
à la CREATE TABLE #TEMPTABLE
, mais cette base de données contient de nombreuses procédures stockées qui peuvent utiliser #temp
les tables.
Comment puis-je résoudre ce problème plus rapidement sans casser les autres bases de données/applications?
Cette base de données doit-elle se trouver sur cette instance? Sinon, comme @Max Vernon l'a suggéré dans un commentaire sur la question, vous pouvez l'installer sur une instance créée avec un classement par défaut de SQL_Latin1_General_CP1_CI_AS
. Peut-être pourriez-vous même vous en sortir avec SQL Server Express Edition, si la base de données est <10 Go et ne nécessite aucune fonctionnalité Enterprise Edition.
Mais si ce n'est pas une option, alors ce que vous faites déjà,
ajout de COLLATE SQL_Latin1_General_CP1_CI_AS à l'instruction CREATE TABLE #TEMPTABLE
est à peu près la seule chose fiable que vous pouvez faire.
Comme vous ne voulez pas nuire au fonctionnement de l'application fournie par votre client, vous ne pouvez pas modifier le classement de la nouvelle base de données. Et en fait, changer le classement par défaut de la base de données ne résoudrait pas votre problème actuel car il ne mettrait pas à jour le classement de la colonne dans les tables de cette base de données. Cela n'affecterait que le classement des littéraux et des variables de chaîne, et vous ne remarqueriez une différence que lorsque ces deux choses sont les seules choses à comparer (puisque le classement d'une colonne remplacerait le classement implicite des littéraux et des variables de chaîne).
Étant donné que vous ne voulez pas nuire à vos bases de données existantes sur votre serveur SQL, il ne serait pas logique de passer le problème de changer le classement de l'instance actuelle en SQL_Latin1_General_CP1_CI_AS
.
Étant donné que la nouvelle base de données et le code associé ont été développés (et, espérons-le, testés!) Sur une instance qui avait SQL_Latin1_General_CP1_CI_AS
comme classement par défaut, vous devez vraiment faire en sorte que les requêtes dans la nouvelle base de données se comportent comme elles le faisaient dans l'environnement dans lequel elles ont été créées. Vous ne pouvez le faire qu'en forçant le classement des colonnes de chaînes dans les tables temporaires en ajoutant la clause COLLATE
(comme vous le faites). Eh bien, techniquement, vous pouvez changer les tables temporaires en variables de table car leur classement par défaut sera tiré de la base de données actuelle, mais c'est un changement plus intrusif car l'Optimiseur de requête ne gère pas les variables de table dans de la même manière que les tables temporaires (et il existe d'autres différences notables).
Dans la clause COLLATE
, vous pouvez utiliser soit DATABASE_DEFAULT
ou continuer à utiliser SQL_Latin1_General_CP1_CI_AS
. Les deux sont équivalents ici car il est peu probable que le classement de la nouvelle base de données change un jour (et si c'est le cas, cela signifie que vous aurez une nouvelle base de données du client qui n'inclut pas vos modifications de toute façon ;-).
FYI: Il n'y a pas beaucoup de différences entre SQL_Latin1_General_CP1_CI_AS
et Latin1_General_CI_AS
. Ils utilisent tous les deux les mêmes paramètres régionaux - 1033 - et la même page de codes - 1252. Les principales différences sont les suivantes:
SQL_
Les classements sont obsolètes depuis longtemps et doivent être évités si possibleSQL_
Les classements permettent certaines extensions/normalisation offertes par Unicode qui associeront plus de caractères que le SQL_
Collations.Cela dépend, par exemple, de la connexion à une base de données ou à des bases de données provenant d'un autre pays où le classement de leurs variantes est l'emplacement standard dans leur région.
Si tel est le cas, il y a une raison pour laquelle vous devez avoir deux classements (ou plus) tels que la jonction avec une base de données (ou une table) qui a une variante de classements.
Le meilleur choix serait probablement d'inclure le COLLATE DATABASE_DEFAULT avec vos requêtes. Cela traitera de nombreux problèmes de classement (mais pas tous).
Un exemple très simple ci-dessous:
SELECT [ITEM_KEY],[PERSON_NAME]
FROM [TempDB].[dbo].[ITEM] AS SC
JOIN [NonStandardCollation].[dbo].[REMOTEITEM] AS NSC
WHERE SC.ITEM_KEY COLLATE DATABASE_DEFAULT = NSC.ITEM_KEY
Dans ce cas, surtout s'il s'agit de plusieurs autres classements, cela simplifiera le code sur votre serveur.