Неможливо вирішити конфлікт зіставлення між "SQL_Latin1_General_CP1_CI_AS" та "Latin1_General_CI_AS" рівним операції


344

У мене є такий код

SELECT tA.FieldName As [Field Name],
       COALESCE(tO_A.[desc], tO_B.[desc], tO_C.Name, tA.OldVAlue) AS [Old Value],
       COALESCE(tN_A.[desc], tN_B.[desc], tN_C.Name, tA.NewValue) AS [New Value],
       U.UserName AS [User Name],
       CONVERT(varchar, tA.ChangeDate) AS [Change Date] 
  FROM D tA
       JOIN 
       [DRTS].[dbo].[User] U 
         ON tA.UserID = U.UserID
       LEFT JOIN 
       A tO_A 
         on tA.FieldName = 'AID' 
        AND tA.oldValue = CONVERT(VARCHAR, tO_A.ID)
       LEFT JOIN 
       A tN_A 
         on tA.FieldName = 'AID' 
        AND tA.newValue = CONVERT(VARCHAR, tN_A.ID)
       LEFT JOIN 
       B tO_B 
         on tA.FieldName = 'BID' 
        AND tA.oldValue = CONVERT(VARCHAR, tO_B.ID)
       LEFT JOIN 
       B tN_B 
         on tA.FieldName = 'BID' 
        AND tA.newValue = CONVERT(VARCHAR, tN_B.ID)
       LEFT JOIN 
       C tO_C 
         on tA.FieldName = 'CID' 
        AND tA.oldValue = tO_C.Name
       LEFT JOIN 
       C tN_C 
         on tA.FieldName = 'CID' 
        AND tA.newValue = tN_C.Name
 WHERE U.Fullname = @SearchTerm
ORDER BY tA.ChangeDate

Під час запуску коду я отримую помилку, вставлену в заголовку після додавання двох приєднань до таблиці C. Я думаю, що це може бути пов'язане з тим, що я використовую SQL Server 2008 і відновив копію цього db на моя машина, яка 2005 року.

Відповіді:


307

У вашій таблиці є невідповідність двох різних порівнянь. Ви можете перевірити, які зразки мають кожен стовпець у ваших таблицях, скориставшись цим запитом:

SELECT
    col.name, col.collation_name
FROM 
    sys.columns col
WHERE
    object_id = OBJECT_ID('YourTableName')

Збірники потрібні та використовуються при замовленні та порівнянні рядків. Як правило, хороша ідея мати єдине унікальне порівняння, яке використовується у вашій базі даних - не використовуйте різні порівняння в межах однієї таблиці чи бази даних - ви лише просите проблем ...

Після того, як ви погодилися на одне зіставлення, ви можете змінити ті таблиці / стовпці, які ще не відповідають цій команді:

ALTER TABLE YourTableName
  ALTER COLUMN OffendingColumn
    VARCHAR(100) COLLATE Latin1_General_CI_AS NOT NULL

Марк

ОНОВЛЕННЯ: щоб знайти індекси повного тексту у вашій базі даних, використовуйте цей запит тут:

SELECT
    fti.object_Id,
    OBJECT_NAME(fti.object_id) 'Fulltext index',
    fti.is_enabled,
    i.name 'Index name',
    OBJECT_NAME(i.object_id) 'Table name'
FROM 
    sys.fulltext_indexes fti
INNER JOIN 
    sys.indexes i ON fti.unique_index_id = i.index_id

Потім можна скинути індекс повного тексту за допомогою:

DROP FULLTEXT INDEX ON (tablename)

Дякую Марку, що саме той тип речей, який я шукав, одна з таблиць була різною порівнянням з якоїсь дурної причини! Я спробую змінити стандартне порівняння і побачити, що станеться.
jhowe

marc, я отримую це зараз: Не вдається змінити або відпустити стовпчик, оскільки він включений для повнотекстового пошуку.
jhowe

1
У такому випадку вам потрібно буде тимчасово скинути індекс повного тексту на цю таблицю, змінити зіставлення, а потім знову створити індекс
повного тексту

1
Дякую ОП, я налаштовував тимчасову таблицю, тому це допомогло, але, оскільки я не зміг змінити таблицю, мені потрібно було просто оголосити її правильно, щоб почати з (наступним чином): ДЕКЛАРАЦІЯ @ TABLE TABLE (ПорівнятиМасаж VARCHAR (50) СУПРАВИТИ SQL_Latin1_General_CP1_CI_AS NOT NULL)
FrostbiteXIII

1
чому не можемо мати два різних зіставлення на одному столі. Якщо у мене є 1 стовпчик як nvarchar, якому потрібні лише англійські імена та інший стовпець як російські літери, інший стовпчик як японські літери. Як я це впорядкую? Чи є єдине порівняння, яке охоплює все це?
batmaci

856

Я роблю наступне:

...WHERE 
    fieldname COLLATE DATABASE_DEFAULT = otherfieldname COLLATE DATABASE_DEFAULT

Працює кожен раз. :)


68
Це одне з найкорисніших дописів у програмі SO
Jamie Strauss

2
Використовував це рішення, тому що я працював із двома застарілими системами, використовуючи той самий db, тому я не був впевнений, що якщо зміна складання таблиць порушить функціональність.
paolobueno

5
Якщо ті ж самі два поля використовуються разом в інших місцях (порівняння, об'єднання, з'єднання тощо), переконайтеся, що для кожного з них також вказано порівняння.
Зарефет

5
Це надзвичайно корисно. Я використовую локальну базу даних і здійснюю запити щодо пов'язаного сервера, і вони мають два різних зіставлення. Очевидно, що я не можу змінити порівняння на пов'язаному сервері, і я не хотів міняти свою локально, тому це абсолютно найкраща відповідь.
jtate

7
@ppumkin Хоча це чудове рішення, воно все ще лише уникає проблеми, а не вирішує її. Якщо ви не хочете змінити порівняння для кожного запиту, який є стомлюючим і не забезпечує оптимальне виконання. Хоча це чудова відповідь, я вважаю, що прийнята відповідь є кращою.
Роб

80

Використовуйте collateпункт у запиті:

LEFT JOIN C tO_C on tA.FieldName = 'CID' AND tA.oldValue COLLATE Latin1_General_CI_AS = tO_C.Name  

У мене може не бути синтаксису правильно (перевірити BOL), але ви можете це зробити, щоб змінити зіставлення під час запиту - можливо, вам потрібно буде додати пункт для кожного об’єднання.

редагувати: Я зрозумів, що це не зовсім правильно - пункт порівняння йде після поля, яке потрібно змінити - у цьому прикладі я змінив порівняння на tA.oldValueполі.


29

Визначте поля, для яких він видає цю помилку, та додайте до них наступне: COLLATE DATABASE_DEFAULT

У полі Код об'єднано дві таблиці:

...
and table1.Code = table2.Code
...

Оновіть запит на:

...
and table1.Code COLLATE DATABASE_DEFAULT = table2.Code COLLATE DATABASE_DEFAULT
...

Дякую. Працюючи в базі даних prod, ми не завжди можемо змінювати структуру бази даних, як це запропоновано прийнятою відповіддю.
Дженніфер Вуд

20

Це може бути легко, якщо у вас є 2 різних бази даних і спеціально 2 різні бази даних з двох різних серверів. Найкращий варіант - змінити його на загальну колекцію та виконати приєднання чи порівняння.

SELECT 
   *
FROM sd
INNER JOIN pd ON sd.SCaseflowID COLLATE Latin1_General_CS_AS = pd.PDebt_code COLLATE Latin1_General_CS_AS

13

@Valkyrie дивовижна відповідь. Думав, я вклав сюди випадок, коли виконуючи те ж саме з підзапитом, всередині зберігається процедури, тому що я задумався, чи працює ваша відповідь у цьому випадку, і це було приголомшливо.

...WHERE fieldname COLLATE DATABASE_DEFAULT in (
          SELECT DISTINCT otherfieldname COLLATE DATABASE_DEFAULT
          FROM ...
          WHERE ...
        )


6

Першопричиною є те, що база даних серверів sql, з якої ви взяли схему, має порівняння, яке відрізняється від локальної установки. Якщо ви не хочете турбуватися про зіставлення, перевстановіть SQL Server локально, використовуючи те саме порівняння, що і база даних SQL Server 2008.


Якщо у вас була така ж проблема, спершу потрібно перевірити властивість вашого сервера та бази даних, щоб побачити, чи є у них однакове зіставлення
мадан

5

помилка (Неможливо вирішити конфлікт зіставлення між ....) зазвичай виникає при порівнянні даних із кількох баз даних.

оскільки ви зараз не можете змінити збірку баз даних, використовуйте COLLATE DATABASE_DEFAULT.

----------
AND db1.tbl1.fiel1 COLLATE DATABASE_DEFAULT =db2.tbl2.field2 COLLATE DATABASE_DEFAULT 

це не відрізняється від іншої вже даної відповіді: stackoverflow.com/a/1607725/479251
Pac0

4

У мене було щось подібне раніше, і ми виявили, що порівняння між двома таблицями було різним.

Перевірте, чи вони однакові.


4

Завдяки відповіді marc_s я вирішив свою первісну проблему - надихнувшись зробити її на крок далі і застосувати один підхід до трансформації цілої таблиці за раз - скрипт tsql для генерації висловлювань змінного стовпця:

DECLARE @tableName VARCHAR(MAX)
SET @tableName = 'affiliate'
--EXEC sp_columns @tableName
SELECT  'Alter table ' + @tableName + ' alter column ' + col.name
        + CASE ( col.user_type_id )
            WHEN 231
            THEN ' nvarchar(' + CAST(col.max_length / 2 AS VARCHAR) + ') '
          END + 'collate Latin1_General_CI_AS ' + CASE ( col.is_nullable )
                                                    WHEN 0 THEN ' not null'
                                                    WHEN 1 THEN ' null'
                                                  END
FROM    sys.columns col
WHERE   object_id = OBJECT_ID(@tableName)

отримує: ALTER TABLE Партнерська ALTER COLUMN myTable NVARCHAR (4000) COLLATE Latin1_General_CI_AS NOT NULL

Я визнаю, що мене спантеличить потреба col.max_length / 2 -


Я думаю, що ділення на два потрібно, тому що довжина зберігається як кількість байтів всередині. Нварчар бере два байти на символ замість одного як варчар.
Зебі

Чудова робота, як колись вище кількість дози запитів для типів даних ncha, ймовірно, через col.max_length / 2 -
Імран

2

Для тих, у кого CREATE DATABASE скрипт (як у моєму випадку) для бази даних, яка викликає цю проблему, ви можете використовувати такий сценарій CREATE, щоб відповідати зіставленням:

-- Create Case Sensitive Database
CREATE DATABASE CaseSensitiveDatabase
COLLATE SQL_Latin1_General_CP1_CS_AS -- or any collation you require
GO
USE CaseSensitiveDatabase
GO
SELECT *
FROM sys.types
GO
--rest of your script here

або

-- Create Case In-Sensitive Database
CREATE DATABASE CaseInSensitiveDatabase
COLLATE SQL_Latin1_General_CP1_CI_AS -- or any collation you require
GO
USE CaseInSensitiveDatabase
GO
SELECT *
FROM sys.types
GO
--rest of your script here

Це застосовує бажане порівняння до всіх таблиць, що було саме те, що мені потрібно. Ідеально спробувати зберегти зіставлення однаковим для всіх баз даних на сервері. Сподіваюсь, це допомагає.

Більше інформації за наступним посиланням: SQL SERVER - Створення бази даних з різним складанням на сервері


2

Я використовував вміст цього сайту, щоб створити наступний скрипт, який змінює зіставлення всіх стовпців у всіх таблицях:

CREATE PROCEDURE [dbo].[sz_pipeline001_collation] 
    -- Add the parameters for the stored procedure here
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;


SELECT 'ALTER TABLE [' + SYSOBJECTS.Name + '] ALTER COLUMN [' + SYSCOLUMNS.Name + '] ' +
SYSTYPES.name + 
    CASE systypes.NAME
    WHEN 'text' THEN ' '
    ELSE
    '(' + RTRIM(CASE SYSCOLUMNS.length
    WHEN -1 THEN 'MAX'
    ELSE CONVERT(CHAR,SYSCOLUMNS.length)
    END) + ') ' 
    END

    + ' ' + ' COLLATE Latin1_General_CI_AS ' + CASE ISNULLABLE WHEN 0 THEN 'NOT NULL' ELSE 'NULL' END
    FROM SYSCOLUMNS , SYSOBJECTS , SYSTYPES
    WHERE SYSCOLUMNS.ID = SYSOBJECTS.ID
    AND SYSOBJECTS.TYPE = 'U'
    AND SYSTYPES.Xtype = SYSCOLUMNS.xtype
    AND SYSCOLUMNS.COLLATION IS NOT NULL
    AND NOT ( sysobjects.NAME LIKE 'sys%' )
    AND NOT ( SYSTYPES.name LIKE 'sys%' )

END

1
SYSCOLUMNS. довжина стовпчиків nvarchar повинна бути поділена на 2
palota

2

Перевірте рівень невідповідності (сервер, база даних, таблиця, стовпець, символ).

Якщо це сервер, ці кроки мені допомогли один раз:

  1. Зупинити сервер
  2. Знайдіть свій інструмент sqlservr.exe
  3. Виконайте цю команду:

    sqlservr -m -T4022 -T3659 -s"name_of_insance" -q "name_of_collation"

  4. Запустіть сервер sql:

    net start name_of_instance

  5. Ще раз перевірте порівняння вашого сервера.

Ось додаткова інформація:

https://www.mssqltips.com/sqlservertip/3519/changing-sql-server-collation-after-installation/


2

Якщо це відбувається у всій вашій БД, то краще змінити зіставлення БД так:

USE master;  
GO  
ALTER DATABASE MyOptionsTest  
COLLATE << INSERT COLATION REQUIRED >> ;  
GO  

--Verify the collation setting.  
SELECT name, collation_name  
FROM sys.databases  
WHERE name = N'<< INSERT DATABASE NAME >>';  
GO 

Довідка тут


на жаль, це не змінить порівняння для існуючих таблиць, а лише за замовчуванням для нових таблиць
RockScience

2

Доданий код до відповіді @ JustSteve для вирішення стовпців varchar та varchar (MAX):

DECLARE @tableName VARCHAR(MAX)
SET @tableName = 'first_notes'
--EXEC sp_columns @tableName
SELECT  'Alter table ' + @tableName + ' alter column ' + col.name
        + CASE ( col.user_type_id )
            WHEN 231
            THEN ' nvarchar(' + CAST(col.max_length / 2 AS VARCHAR) + ') '
            WHEN 167
            THEN ' varchar(' + CASE col.max_length 
                                WHEN -1 
                                THEN 'MAX'
                                ELSE 
                                CAST(col.max_length AS VARCHAR)
                                end
                                 + ') '
          END + 'collate Latin1_General_CI_AS ' + CASE ( col.is_nullable )
                                                    WHEN 0 THEN ' not null'
                                                    WHEN 1 THEN ' null'
                                                  END
FROM    sys.columns col
WHERE   object_id = OBJECT_ID(@tableName)

2

Щоб вирішити цю проблему в запиті, не змінюючи жодної бази даних, ви можете передавати вирази на іншій стороні знаку "=" за допомогою

COLLATE SQL_Latin1_General_CP1_CI_AS

як тут запропоновано .


1

У мене була подібна помилка (Не вдалося вирішити конфлікт зіставлення між "SQL_Latin1_General_CP1_CI_AS" та "SQL_Latin1_General_CP1250_CI_AS" в операції INTERSECT), коли я використовував старий драйвер jdbc.

Я вирішив це, завантаживши новий драйвер з Microsoft або проект з відкритим кодом jTDS .


1

ось що ми зробили, в нашій ситуації нам потрібен спеціальний запит, який виконується за допомогою обмеження дати за запитом, а запит визначено в таблиці.

Наш новий запит повинен відповідати даним між різними базами даних і включати дані з обох.

Схоже, КОЛЛАЦІЯ відрізняється між db, який імпортує дані з системи iSeries / AS400, і нашою базою звітів - це може бути через специфічні типи даних (наприклад, грецькі акценти на імена тощо).

Тож ми використали нижченаведений пункт приєднання:

...LEFT Outer join ImportDB..C4CTP C4 on C4.C4CTP COLLATE Latin1_General_CS_AS=CUS_Type COLLATE Latin1_General_CS_AS

1

Ви можете легко зробити це, скориставшись 4 простими кроками

  1. створити резервну копію вашої бази даних
  2. змінити зіставлення бази даних: клацніть правою кнопкою миші, виберіть властивості, перейдіть до параметрів та змініть порівняння на необхідне порівняння.
  3. Створіть сценарій для видалення та відтворення всіх об'єктів вашої бази даних: клацніть правою кнопкою миші базу даних, виберіть завдання, виберіть генерувати сценарій ... (переконайтеся, що ви вибрали пункт Drop & Create у розширених параметрах майстра; також виберіть схему та дані)
  4. Запустіть створений вище сценарій

1
INSERT INTO eSSLSmartOfficeSource2.[dbo].DeviceLogs  (DeviceId,UserId,LogDate,UpdateFlag) 
SELECT DL1.DeviceId ,DL1.UserId COLLATE DATABASE_DEFAULT,DL1.LogDate 
,0 FROM eSSLSmartOffice.[dbo].DeviceLogs DL1 
WHERE  NOT EXISTS 
(SELECT DL2.DeviceId ,DL2.UserId COLLATE DATABASE_DEFAULT
,DL2.LogDate ,DL2.UpdateFlag 
FROM eSSLSmartOfficeSource2.[dbo].DeviceLogs DL2    
WHERE  DL1.DeviceId =DL2.DeviceId
 and DL1.UserId collate  Latin1_General_CS_AS=DL2.UserId collate  Latin1_General_CS_AS
  and DL1.LogDate =DL2.LogDate )

0

У вашій базі даних можуть не виникати жодних проблем зі збіркою, але якщо ви відновили копію вашої бази даних із резервної копії на сервері з іншим порівнянням, ніж походження, і ваш код створює тимчасові таблиці, ці тимчасові таблиці успадкують зіставлення від сервер і виникли конфлікти з вашою базою даних.


0
ALTER DATABASE test2            --put your database name here
COLLATE Latin1_General_CS_AS    --replace with the collation you need

0

У мене була схожа вимога; документування мого підходу для тих, хто має подібний сценарій ...

Сценарій

  • У мене є база даних з чистої установки з правильними порівняннями.
  • У мене є ще одна база даних, яка має неправильні порівняння.
  • Мені потрібно оновити останнє, щоб використовувати порівняння, визначені на першому.

Рішення

Використовуйте порівняння схем SQL Server (з інструментів даних SQL Server) / Visual Studio) для порівняння джерела (чистої установки) з пунктом призначення (db з невірним зіставленням).

У моєму випадку я порівняв два БД безпосередньо; хоча ви можете працювати над проектом, який дозволяє вам вручну підлаштовувати шматки між ними ...

  • Запустіть Visual Studio
  • Створіть новий проект даних SQL Server
  • Клацніть Інструменти, SQL Server, Порівняння нових схем
  • Виберіть вихідну базу даних
  • Виберіть цільову базу даних
  • Параметри клацання (⚙)
    • Під Object Typesвиберіть лише ті типи, які вас цікавлять (для мене це було лише ViewsіTables )
    • Під Generalвибором:
      • Блокувати можливі втрати даних
      • Вимкнення та повторне включення тригерів DDL
      • Ігноруйте шлях до файлу криптографічного провайдера
      • Ігнорувати шлях до файлу та журналу
      • Ігнорувати розмір файлу
      • Ігноруйте розміщення групи файлів
      • Ігнорувати повний текстовий шлях до каталогу каталогу
      • Ігноруйте корпус ключових слів
      • Ігнорувати SID-адреси входу
      • Ігноруйте цитовані ідентифікатори
      • Ігноруйте життя маршруту
      • Ігноруйте крапку з комою між твердженнями
      • Ігноруйте пробіли
      • Модуль оновлення сценарію
      • Перевірка сценарію для нових обмежень
      • Перевірте сумісність зіставлення
      • Перевірте розгортання
  • Клацніть Порівняти
    • Зніміть прапорці для об'єктів, позначених для видалення (зверніть увагу: у них все ще можуть виникнути проблеми зіставлення; але оскільки вони не визначені в нашому джерелі / шаблоні db, ми не знаємо; в будь-якому випадку ми не хочемо втрачати речі, якщо ми зміни лише порівняння націлювання). Ви можете зняти прапорець усі відразу, клацнувши правою кнопкою миші на DELETEпапці та вибравши EXCLUDE.
    • Аналогічно виключити для будь-якого CREATE об’єкти (тут, оскільки вони не існують у цілі, вони там не можуть мати неправильне зіставлення; чи вони повинні існувати - це питання для іншої теми).
    • Клацніть на кожному об'єкті під ЗМІНУ, щоб побачити сценарій для цього об’єкта. Використовуйте diff, щоб переконатися, що ми змінюємо лише порівняння (будь-які інші розбіжності, виявлені вручну, ви, можливо, захочете виключити / обробити ці об’єкти вручну).
  • Клацніть, Updateщоб натиснути зміни

Це все ще передбачає певні зусилля вручну (наприклад, перевірка того, що ви тільки впливаєте на порівняння) - але це справляється із залежностями для вас.

Крім того, ви можете зберегти проект бази даних дійсної схеми, щоб ви могли використовувати універсальний шаблон для ваших БД, якщо у вас буде більше 1 для оновлення, припускаючи, що всі цільові БД повинні закінчуватися тією ж схемою.

Ви також можете використовувати знайти / замінити файли в проекті бази даних, якщо ви хочете масово змінити налаштування там (наприклад, щоб ви могли створити проект з недійсної бази даних за допомогою схеми порівняння, змінити файли проекту, а потім переключити джерело / ціль у схему порівняння, щоб повернути свої зміни назад до БД).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.