Existe-t-il un moyen plus facile de résoudre les incompatibilités de classement SQL Server / base de données que de modifier chaque colonne?

8

AVERTISSEMENT: Je sais que cette question a été posée cent fois auparavant, mais je voulais juste vérifier qu'il n'y avait pas de solution plus simple que j'aurais pu manquer avant d'aller de l'avant et d'écrire / de trouver beaucoup de code pour le faire.

Notre logiciel utilise une base de données conçue à l'origine pour SQL Server 7, et en tant que tel, tous les scripts qui le créent ne spécifient aucun classement explicite pour les colonnes de caractères. Au lieu de cela, lorsqu'une base de données est créée / restaurée vers SQL Server 2000 ou supérieur, chaque colonne hérite du classement de la base de données (qui se trouve être SQL_Latin1_General_CP1_CI_AScomme c'était la valeur par défaut de SQL Server 7).

Théoriquement, cela n'aurait pas trop d'importance, car si notre base de données est créée à partir de zéro sur le serveur d'un client, elle hérite du classement du serveur du client (qui est normalement l'installation par défaut moderne Latin1_General_CP1_CI_AS) et tout fonctionne. Cependant, ce scénario tombe en panne lorsqu'ils nous envoient une sauvegarde de base de données, ou nous leur envoyons une sauvegarde de base de données, et nous ou ils obtiennent l'erreur de non-concordance de classement redoutée chaque fois que le code essaie d'accéder aux tables temporaires, etc.

Nous avons essayé d'éduquer les clients à installer ou à reconstruire leurs instances SQL Server pour utiliser notre classement préféré, mais bien sûr, cela ne se produit pas toujours et ce n'est pas toujours possible.

Les solutions qui impliquent la création d'une nouvelle base de données et la copie des données ne sont pas vraiment pratiques pour nous, nous avons besoin d'une "baguette magique" que nous pouvons agiter dans une base de données en direct pour corriger toutes les colonnes en place sans perturber les données. Je pense à écrire un utilitaire pour ce faire, mais comme ce sera un gros travail, quelqu'un a-t-il des suggestions plus simples?

Christian Hayter
la source

Réponses:

6

Une option consiste à "vérifier" votre code contre les différences de classement.

Vous pouvez utiliser le classement spécial "DATABASE_DEFAULT" pour contraindre sans connaître le classement réel. Vous l'utilisez sur les colonnes de type char dans les tables temporaires, les variables de table et les tables système que vous devez utiliser.

Exemple:

CREATE TABLE #Currency (CCY CHAR(3))
GO
INSERT #Currency VALUES ('GBP')
INSERT #Currency VALUES ('CHF')
INSERT #Currency VALUES ('EUR')
GO
SELECT Something
FROM myTable M JOIN #Currency C ON M.CCY = C.CCY --error!
GO
-- in join too
SELECT Something
FROM myTable M JOIN #Currency C ON M.CCY = C.CCY COLLATE DATABASE_DEFAULT --no error
GO
DROP TABLE #Currency
GO


CREATE TABLE  #Currency (CCY CHAR(3) COLLATE DATABASE_DEFAULT)
GO
INSERT #Currency VALUES ('GBP')
INSERT #Currency VALUES ('CHF')
INSERT #Currency VALUES ('EUR')
GO
SELECT Something
FROM myTable M JOIN #Currency C ON M.CCY = C.CCY --no error!
GO

DROP TABLE #Currency
GO

Cela signifie également que lorsque vos clients migrent leur base de données vers une nouvelle boîte SQL Server géniale avec un autre classement différent, cela fonctionne aussi ...

gbn
la source
2

La réponse courte est qu'il n'y a pas de moyen facile. J'ai eu le même problème dans le passé.

Ce que je dirais, c'est 2 choses, d'abord lorsque votre client vous envoie une base de données avec un classement inattendu, installez une nouvelle instance SQL avec un classement par défaut qui correspond à leur base de données et travaillez avec elle dans ce cadre.

La seconde est de vous assurer que votre application fonctionnera avec d'autres classements, puis les valeurs par défaut (car celles-ci pourraient changer à l'avenir) et fonctionneront correctement tant que le classement sur le serveur SQL et la base de données correspond. Ensuite, il est assez facile pour le client d'installer SQL Server avec un classement qui correspond à sa base de données et fonctionnera ensuite.

Ou écrivez un utilitaire qui mettra à jour toutes les tables, etc. dans votre base de données comme vous l'avez dit, mais cela pourrait être plus de travail que vous le souhaitez.

SpaceManSpiff
la source
2

Si toutes les colonnes de la base de données sont du même classement, cela ne vous posera de problèmes que lors des requêtes entre bases de données (ou votre application est sensible à l'ordre de tri).

Le point épineux survient lorsque vous réalisez que la jointure à des tables temporaires est inter-base de données, comme elles le sont dans tempdb. C'est facile à trier cependant - assurez-vous simplement que toutes les colonnes de texte dans les tables temporaires sont explicitement créées avec la COLLATE database_defaultdirective. Cela signifie que la colonne sera créée avec le classement par défaut de la base de données actuelle au lieu de la collection par défaut de tempdb (qui sera la même que celle par défaut du serveur).

David Spillett
la source