Кодовые страницы и сопоставления SQL Server - PullRequest
5 голосов
/ 03 марта 2011

Есть ли способ в SQL Server определить, что символ в кодовой странице будет представлять без фактического создания тестовой базы данных этого сопоставления?

Пример. Если я создаю тестовую базу данных с сопоставлением SQL_Ukrainian_CP1251_CS_AS, а затем выполняю CHAR(255), возвращается я.

Если я попробую следующее в базе данных с SQL_Latin1_General_CP1_CS_AS сопоставлением, однако

SELECT CHAR(255) COLLATE SQL_Ukrainian_CP1251_CS_AS

Возвращает y

SELECT CHAR(255)

Возвращает ÿ, поэтому он, очевидно, сначала проходит через сопоставление по умолчанию для базы данных, а затем пытается найти ближайший эквивалент этого в явном сопоставлении. Можно ли этого избежать?

Ответы [ 2 ]

7 голосов
/ 05 марта 2011

На самом деле я нашел ответ на свой вопрос сейчас. Немного неуклюже, но справляется ли работа, если нет лучшего выхода?

SET NOCOUNT ON;

CREATE TABLE #Collations
(
     code TINYINT PRIMARY KEY
);

WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1),   --2
        E02(N) AS (SELECT 1 FROM E00 a, E00 b), --4
        E04(N) AS (SELECT 1 FROM E02 a, E02 b), --16
        E08(N) AS (SELECT 1 FROM E04 a, E04 b) --256
INSERT INTO #Collations
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) - 1
FROM E08    

DECLARE @AlterScript NVARCHAR(MAX) = ''

SELECT @AlterScript = @AlterScript + ' 
RAISERROR(''Processing' + name + ''',0,1) WITH NOWAIT;
ALTER TABLE #Collations ADD ' + name + ' CHAR(1) COLLATE ' + name + ';
EXEC(''UPDATE #Collations SET ' + name + '=CAST(code AS BINARY(1))'');
EXEC(''UPDATE #Collations SET ' + name + '=NULL WHERE ASCII(' + name + ') <> code'');
'
FROM   sys.fn_helpcollations()
WHERE  name LIKE '%CS_AS'
       AND name NOT IN    /*Unicode Only Collations*/
                        ( 'Assamese_100_CS_AS', 'Bengali_100_CS_AS',
                         'Divehi_90_CS_AS', 'Divehi_100_CS_AS' ,
                         'Indic_General_90_CS_AS', 'Indic_General_100_CS_AS',
                             'Khmer_100_CS_AS', 'Lao_100_CS_AS',
                         'Maltese_100_CS_AS', 'Maori_100_CS_AS',
                         'Nepali_100_CS_AS', 'Pashto_100_CS_AS',
                         'Syriac_90_CS_AS', 'Syriac_100_CS_AS',
                         'Tibetan_100_CS_AS' )


EXEC (@AlterScript)

SELECT * FROM #Collations

DROP TABLE #Collations
2 голосов
/ 03 марта 2011

Хотя MS SQL и бесполезно поддерживает обе кодовые страницы и Unicode, он не предоставляет никаких функций для преобразования между ними, поэтому выяснение того, какой символ представлен значением в другой кодовой странице, является свиньей.

Есть два потенциальных метода обработки конверсий, один из которых подробно описан здесь. http://www.codeguru.com/cpp/data/data-misc/values/article.php/c4571 и включает в себя прикрепление пользовательской программы преобразования к базе данных и использование ее для преобразований.

Другой состоит в создании таблицы БД, состоящей из

[CodePage], [ANSI Value], [UnicodeValue]

со значением Unicode, хранящимся как int, представляющий символ Unicode для преобразования с использованием nchar(), так и сам nchar

Вы используете сопоставление SQL_Ukrainian_CP1251_CS_AS, которое является кодовой страницей 1251 (CP1251 от центра строки). Вы можете взять его таблицу перевода здесь http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT

Это TSV, поэтому после обрезки вершины необработанные данные должны импортироваться довольно аккуратно.

Лично я бы больше склонялся к последнему, чем к первому, особенно для производственного сервера, поскольку первый может привести к нестабильности.

...