¿Hay una manera más fácil de resolver los desajustes de intercalación de SQL Server / base de datos que cambiar cada columna?

8

DESCARGO DE RESPONSABILIDAD: Sé que esta pregunta se ha hecho cientos de veces antes, pero solo quería comprobar que no había una solución más fácil que podría haber perdido antes de seguir adelante y escribí / obtuve un montón de código para hacerlo.

Nuestro software utiliza una base de datos que fue diseñada originalmente para SQL Server 7 y, como tal, todos los scripts que la crean no especifican ninguna clasificación explícita para ninguna columna de caracteres. En cambio, cuando se crea / restaura una base de datos a SQL Server 2000 o superior, cada columna hereda la clasificación de la base de datos (lo que sucede SQL_Latin1_General_CP1_CI_ASporque ese era el valor predeterminado de SQL Server 7).

Teóricamente, esto no importaría demasiado, ya que si nuestra base de datos se crea desde cero en el servidor de un cliente, hereda la intercalación del servidor del cliente (que normalmente es el valor predeterminado de instalación moderno Latin1_General_CP1_CI_AS) y todo simplemente funciona. Sin embargo, este escenario se rompe cuando nos envían una copia de seguridad de la base de datos, o les enviamos una copia de seguridad de la base de datos, y nosotros o ellos recibimos el temido error de desajuste de intercalación cada vez que el código intenta acceder a las tablas temporales, etc.

Hemos intentado educar a los clientes para que instalen o reconstruyan sus instancias de SQL Server para usar nuestra clasificación preferida, pero, por supuesto, eso no siempre sucede y no siempre es posible.

Las soluciones que implican crear una nueva base de datos y copiar los datos no son realmente prácticas para nosotros, necesitamos una "varita mágica" que podamos agitar en una base de datos en vivo para corregir todas las columnas en su lugar sin alterar los datos. Estoy pensando en escribir una utilidad para hacer esto, pero dado que será un trabajo bastante grande, ¿alguien tiene alguna sugerencia más simple?

Christian Hayter
fuente

Respuestas:

6

Una opción es "probar" su código contra la incompatibilidad de colación.

Puede usar la clasificación especial "DATABASE_DEFAULT" para coaccionar sin saber cuál es la clasificación real. Lo usa en columnas de tipo char en tablas temporales, variables de tabla y tablas de sistema que necesita usar.

Ejemplo:

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

Esto también significa que cuando sus clientes migran su base de datos a una nueva caja de SQL Server con otra recopilación diferente, también funciona ...

gbn
fuente
2

La respuesta corta es que no hay una manera fácil. He tenido el mismo problema en el pasado.

Lo que diría es 2 cosas, primero cuando su cliente le envía una base de datos con una clasificación inesperada, instale una nueva instancia de SQL con una clasificación predeterminada que coincida con su base de datos y trabaje con ella dentro de eso.

El segundo es asegurarse de que su aplicación funcionará con otras intercalaciones luego de los valores predeterminados (ya que podrían cambiar en el futuro) y funcionará correctamente siempre que la intercalación en el servidor SQL y la base de datos coincidan. Entonces es bastante fácil que el cliente instale el servidor SQL con una clasificación que coincida con su base de datos y luego funcione.

O escriba una utilidad que actualizará todas las tablas, etc. en su base de datos como usted dijo, pero eso podría ser más trabajo de lo que desea.

SpaceManSpiff
fuente
2

Si todas las columnas de la base de datos tienen la misma clasificación, solo le causará problemas al realizar consultas entre bases de datos (o su aplicación es sensible al orden de clasificación).

El punto difícil llega cuando te das cuenta de que unirte a tablas temporales es una base de datos cruzada, ya que están en tempdb. Sin embargo, eso es fácil de ordenar, solo asegúrese de que cualquier columna de texto en tablas temporales se cree explícitamente con la COLLATE database_defaultdirectiva. Esto significa que la columna se creará con la clasificación predeterminada de la base de datos actual en lugar de la colección predeterminada de tempdb (que será la misma que la predeterminada del servidor).

David Spillett
fuente