/ / Intercalaciones y páginas de códigos de SQL Server - sql-server, intercalación

Páginas de códigos y colaciones de SQL Server - sql-server, colación

¿Existe alguna forma en SQL Server de determinar lo que representaría un carácter en una página de códigos sin crear realmente una base de datos de prueba de esa colación?

Ejemplo. Si creo una base de datos de prueba con colación SQL_Ukrainian_CP1251_CS_AS y luego hacer CHAR(255) vuelve я.

Si intento lo siguiente en una base de datos con SQL_Latin1_General_CP1_CS_AS colación sin embargo

SELECT CHAR(255) COLLATE SQL_Ukrainian_CP1251_CS_AS

Vuelve y

SELECT CHAR(255)

Devoluciones ÿ por lo que obviamente va primero a través de la intercalación predeterminada de la base de datos y luego trata de encontrar el equivalente más cercano a eso en la intercalación explícita. ¿Se puede evitar esto?

Respuestas

2 para la respuesta № 1

Mientras que MS SQL admite páginas de códigos y Unicodedesafortunadamente, no proporciona ninguna función para convertir entre los dos, por lo que averiguar qué carácter está representado por un valor en una página de códigos diferente es un cerdo.

Hay dos métodos potenciales que he visto para manejar las conversiones, uno se detalla aquí http://www.codeguru.com/cpp/data/data-misc/values/article.php/c4571 e implica incorporar un programa de conversión personalizado a la base de datos y usarlo para las conversiones.

El otro es construir una tabla db que consta de

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

con el valor Unicode almacenado como int que representa el carácter Unicode que se convertirá usando nchar()o el propio nchar

Estás usando la colación SQL_Ukrainian_CP1251_CS_AS que es la página de códigos 1251 (CP1251 desde el centro de la cadena). Puede obtener su tabla de traducción aquí http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT

Es un TSV, por lo que después de recortar la parte superior, los datos sin procesar deberían importar de forma bastante limpia.

Personalmente, me inclinaría más por lo último que por lo primero, especialmente para un servidor de producción, ya que lo primero puede introducir inestabilidad.


7 para la respuesta № 2

De hecho, ahora he encontrado una respuesta a mi pregunta. Un poco torpe, pero ¿funciona a menos que haya una mejor manera de salir?

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