web-dev-qa-db-fra.com

SQL Server - Convertir varchar en un autre classement (page de codes) pour corriger l'encodage des caractères

J'interroge une base de données SQL Server qui utilise le classement SQL_Latin1_General_CP850_BIN2. L'une des lignes du tableau a un varchar avec une valeur qui inclut le caractère +/- (code décimal 177 dans la page de code Windows-1252).

Lorsque j'interroge la table directement dans SQL Server Management Studio, j'obtiens un caractère charabia au lieu du caractère +/- dans cette ligne. Lorsque j'utilise cette table comme source dans un package SSIS, la table de destination (qui utilise le classement SQL_Latin1_General_CP1_CI_AS typique) se termine avec le bon caractère +/-.

Je dois maintenant créer un mécanisme qui interroge directement la table source sans SSIS. Comment dois-je procéder pour obtenir le bon caractère au lieu de charabia? Je suppose que je devrais convertir/convertir la colonne en classement SQL_Latin1_General_CP1_CI_AS, mais cela ne fonctionne pas car je reçois toujours un caractère charabia.

J'ai essayé ce qui suit sans succès:

select 
columnName collate SQL_Latin1_General_CP1_CI_AS
from tableName

select 
cast (columnName as varchar(100)) collate SQL_Latin1_General_CP1_CI_AS
from tableName

select 
convert (varchar, columnName) collate SQL_Latin1_General_CP1_CI_AS
from tableName

Qu'est-ce que je fais mal?

20
lunadesign

La conversion du jeu de caractères se fait implicitement au niveau de la connexion à la base de données. Vous pouvez forcer la conversion automatique dans la chaîne de connexion ODBC ou ADODB avec le paramètre "Auto Translate = False". Ceci n'est PAS recommandé. Voir: https://msdn.Microsoft .com/en-us/library/ms130822.aspx

Il y a eu une incompatibilité de page de code dans SQL Server 2005 lorsque la page de code de la base de données et du client ne correspondait pas. https://support.Microsoft.com/kb/KbView/9048

SQL-Management Console 2008 et versions ultérieures est une application UNICODE. Toutes les valeurs saisies ou demandées sont interprétées comme telles au niveau de l'application. La conversation vers et depuis le classement des colonnes se fait implicitement. Vous pouvez le vérifier avec:

SELECT CAST(N'±' as varbinary(10)) AS Result

Cela renverra 0xB100 qui est le caractère Unicode U + 00B1 (tel qu'il est entré dans la fenêtre de la console de gestion). Vous ne pouvez pas désactiver la "traduction automatique" pour Management Studio.

Si vous spécifiez un classement différent dans la sélection, vous vous retrouvez finalement dans une double conversion (avec une perte de données possible) tant que "Traduction automatique" est toujours actif. Le caractère d'origine est d'abord transformé dans le nouveau classement lors de la sélection, qui à son tour obtient "Auto Traduit" à la page de code de l'application "appropriée". C'est pourquoi vos différents tests COLLATION montrent toujours le même résultat.

Vous pouvez vérifier que la spécification du classement a un effet dans la sélection, si vous convertissez le résultat en VARBINARY au lieu de VARCHAR afin que la transformation SQL Server ne soit pas invalidée par le client avant d'être présentée :

SELECT cast(columnName COLLATE SQL_Latin1_General_CP850_BIN2 as varbinary(10)) from tableName
SELECT cast(columnName COLLATE SQL_Latin1_General_CP1_CI_AS as varbinary(10)) from tableName

Cela vous donnera 0xF1 ou 0xB1 respectivement si columnName contient uniquement le caractère '±'

Vous pouvez toujours obtenir le résultat correct et pourtant un mauvais caractère, si la police que vous utilisez ne fournit pas le glyphe approprié.

Veuillez vérifier la représentation interne réelle de votre personnage en lançant la requête sur VARBINARY sur un échantillon approprié et vérifiez si ce code correspond bien au classement de base de données défini SQL_Latin1_General_CP850_BIN2

SELECT CAST(columnName as varbinary(10)) from tableName

Les différences dans le classement des applications et le classement des bases de données peuvent passer inaperçues tant que la conversion se fait toujours de la même manière à l'intérieur et à l'extérieur. Des problèmes surviennent dès que vous ajoutez un client avec un classement différent. Vous pourriez alors constater que la conversion interne ne peut pas faire correspondre correctement les caractères.

Cela dit, vous devez garder à l'esprit que Management Studio n'est généralement pas la référence finale lors de l'interprétation des jeux de résultats. Même si cela ressemble à du charabia dans MS, ce pourrait toujours être la sortie correcte. La question est de savoir si les enregistrements s'affichent correctement dans vos applications.

13
Robert Orso

Doit être utilisé converti, non coulé:

SELECT
 CONVERT(varchar(50), N'æøåáäĺćçčéđńőöřůýţžš')
 COLLATE Cyrillic_General_CI_AI

( http://blog.sqlpositive.com/2010/03/using-convert-with-collate-to-strip-accents-from-unicode-strings/ )

5
castleless

Nous pourrions avoir besoin de plus d'informations. Voici ce que j'ai fait pour reproduire sur SQL Server 2008:

CREATE DATABASE [Test] ON  PRIMARY 
    ( 
    NAME = N'Test'
    , FILENAME = N'...Test.mdf' 
    , SIZE = 3072KB 
    , FILEGROWTH = 1024KB 
    )
    LOG ON 
    ( 
    NAME = N'Test_log'
    , FILENAME = N'...Test_log.ldf' 
    , SIZE = 1024KB 
    , FILEGROWTH = 10%
    )
    COLLATE SQL_Latin1_General_CP850_BIN2
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[MyTable]
    (
    [SomeCol] [varchar](50) NULL
    ) ON [PRIMARY]
GO
Insert MyTable( SomeCol )
Select '±' Collate SQL_Latin1_General_CP1_CI_AS
GO
Select SomeCol, SomeCol Collate SQL_Latin1_General_CP1_CI_AS
From MyTable

Les résultats montrent le caractère original. La déclaration du classement dans la requête doit renvoyer le caractère approprié du point de vue de SQL Server, mais il se peut que la couche de présentation soit ensuite convertie en quelque chose de différent comme UTF-8.

1
Thomas

essayer:

SELECT CAST( CAST([field] AS VARBINARY) AS varchar) 
1
user1403869