Tidak dapat menyelesaikan konflik pemeriksaan antara "SQL_Latin1_General_CP1_CI_AS" dan "Latin1_General_CI_AS" dalam operasi yang sama dengan

342

Saya memiliki kode berikut

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

Ketika menjalankan kode saya mendapatkan kesalahan yang disisipkan dalam judul setelah menambahkan dua gabungan untuk tabel C. Saya pikir ini mungkin ada hubungannya dengan fakta saya menggunakan SQL Server 2008 dan telah mengembalikan salinan db ini ke mesin saya yaitu 2005.

jhowe
sumber

Jawaban:

307

Anda memiliki ketidakcocokan dua susunan berbeda di meja Anda. Anda dapat memeriksa koleksi apa yang dimiliki setiap kolom dalam tabel Anda dengan menggunakan kueri ini:

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

Kolasi diperlukan dan digunakan saat memesan dan membandingkan string. Ini umumnya ide yang baik untuk memiliki satu, unik unik digunakan di seluruh database Anda - jangan gunakan berbeda dalam satu tabel atau database - Anda hanya meminta masalah ....

Setelah Anda puas dengan satu susunan tunggal, Anda dapat mengubah tabel / kolom yang belum cocok menggunakan perintah ini:

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

Marc

PEMBARUAN: untuk menemukan indeks teks lengkap dalam basis data Anda, gunakan kueri ini di sini:

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

Anda kemudian dapat menjatuhkan indeks teks lengkap menggunakan:

DROP FULLTEXT INDEX ON (tablename)
marc_s
sumber
Terima kasih marc, itulah jenis hal yang saya cari, salah satu tabel adalah susunan yang berbeda untuk beberapa alasan bodoh! Saya akan mencoba mengubah susunan standar dan melihat apa yang terjadi.
jhowe
marc saya mendapatkan ini sekarang: Tidak dapat mengubah atau menjatuhkan kolom karena diaktifkan untuk Pencarian Teks Lengkap.
jhowe
1
Dalam hal ini, Anda harus menjatuhkan indeks fulltext Anda di atas meja yang sementara, mengubah pemeriksaan, dan kemudian kembali membuat indeks fulltext lagi
marc_s
1
Terima kasih OP, saya menyiapkan tabel sementara sehingga ini membantu, tetapi karena saya tidak dapat mengubah tabel, saya hanya perlu mendeklarasikannya dengan benar untuk memulai dengan (sebagai berikut): DECLARE @Table TABLE (CompareMessage VARCHAR (50) COLLATE SQL_Latin1_General_CP1_CI_AS TIDAK NULL)
FrostbiteXIII
1
mengapa kita tidak dapat memiliki 2 susunan berbeda pada tabel yang sama Jika saya memiliki 1 kolom sebagai nvarchar yang hanya membutuhkan nama bahasa Inggris dan kolom lainnya sebagai huruf Rusia, kolom lainnya sebagai huruf Jepang. Bagaimana saya mengatur ini? Apakah ada satu collation yang mencakup semua ini?
batmaci
854

Saya melakukan hal berikut:

...WHERE 
    fieldname COLLATE DATABASE_DEFAULT = otherfieldname COLLATE DATABASE_DEFAULT

Bekerja setiap saat. :)

Valkyrie
sumber
68
Ini adalah salah satu posting paling berguna di SO
Jamie Strauss
2
Menggunakan solusi ini karena saya bekerja dengan dua sistem lama menggunakan db yang sama jadi saya tidak yakin apakah mengubah susunan tabel akan merusak fungsionalitas.
paolobueno
5
Jika dua bidang yang sama digunakan bersama di tempat lain (perbandingan, serikat, penggabungan, dll ...) pastikan bahwa masing-masing bidang juga memiliki susunan yang ditentukan.
Zarepheth
5
Ini sangat berguna. Saya menggunakan database lokal dan menanyakan terhadap server yang terhubung dan mereka memiliki dua susunan berbeda. Jelas saya tidak dapat mengubah susunan pada server yang ditautkan, dan saya tidak ingin mengganti tambang secara lokal, jadi ini benar-benar jawaban terbaik.
jtate
7
@ppumkin Meskipun ini adalah solusi hebat, tetap saja hanya menghindari masalah, bukan menyelesaikannya. Kecuali jika Anda ingin mengubah susunan untuk setiap kueri, yang membosankan dan tidak berkinerja optimal. Meskipun ini adalah jawaban yang bagus, jawaban yang diterima yang saya rasakan adalah jawaban yang lebih baik.
Rob
80

Gunakan collateklausa dalam kueri Anda:

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

Saya mungkin tidak memiliki sintaks yang tepat (centang BOL), tetapi Anda dapat melakukan ini untuk mengubah collation on-the-fly untuk kueri - Anda mungkin perlu menambahkan klausa untuk setiap bergabung.

sunting: Saya menyadari ini tidak benar - klausa susun berjalan setelah bidang yang perlu Anda ubah - dalam contoh ini saya mengubah susunan di tA.oldValuelapangan.

sinar
sumber
29

Identifikasi bidang yang dilemparnya kesalahan ini dan tambahkan berikut ini: COLLATE DATABASE_DEFAULT

Ada dua tabel yang tergabung dalam bidang Kode:

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

Perbarui kueri Anda ke:

...
and table1.Code COLLATE DATABASE_DEFAULT = table2.Code COLLATE DATABASE_DEFAULT
...
Palak.Maheria
sumber
Terima kasih. Saat bekerja dalam basis data prod, kami tidak selalu dapat mengubah struktur basis data seperti yang disarankan oleh jawaban yang diterima.
Jennifer Wood
20

Ini dapat dengan mudah terjadi ketika Anda memiliki 2 database yang berbeda dan 2 database yang berbeda dari 2 server yang berbeda. Pilihan terbaik adalah mengubahnya menjadi koleksi umum dan melakukan join atau perbandingan.

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

@ Valkyrie jawaban yang luar biasa. Pikir saya memasukkan kasus di sini ketika melakukan hal yang sama dengan subquery di dalam prosedur tersimpan, karena saya bertanya-tanya apakah jawaban Anda bekerja dalam kasus ini, dan itu luar biasa.

...WHERE fieldname COLLATE DATABASE_DEFAULT in (
          SELECT DISTINCT otherfieldname COLLATE DATABASE_DEFAULT
          FROM ...
          WHERE ...
        )
Ikram M.
sumber
12

Di tempat kriteria menambahkan collate SQL_Latin1_General_CP1_CI_AS

Ini bekerja untuk saya.

WHERE U.Fullname = @SearchTerm  collate SQL_Latin1_General_CP1_CI_AS
Carlos de Jesus Baez
sumber
6

Akar penyebabnya adalah bahwa database server sql tempat Anda mengambil skema memiliki susunan yang berbeda dari instalasi lokal Anda. Jika Anda tidak ingin khawatir tentang collation, instal ulang SQL Server secara lokal menggunakan collation yang sama dengan database SQL Server 2008.

Robert
sumber
Punya masalah yang sama, pertama-tama Anda perlu memeriksa properti server dan basis data Anda untuk melihat apakah mereka memiliki susunan yang sama
madan
5

kesalahan (Tidak dapat menyelesaikan konflik pemeriksaan antara ....) biasanya terjadi saat membandingkan data dari beberapa basis data.

karena Anda tidak dapat mengubah susunan basis data sekarang, gunakan COLLATE DATABASE_DEFAULT.

----------
AND db1.tbl1.fiel1 COLLATE DATABASE_DEFAULT =db2.tbl2.field2 COLLATE DATABASE_DEFAULT 
chaminda welgamage
sumber
ini tidak berbeda dari jawaban lain yang sudah diberikan: stackoverflow.com/a/1607725/479251
Pac0
4

Saya memiliki sesuatu seperti ini sebelumnya, dan apa yang kami temukan adalah bahwa susunan antara 2 tabel berbeda.

Periksa apakah ini sama.

Adriaan Stander
sumber
4

Berkat jawaban marc_s, saya memecahkan masalah awal saya - terinspirasi untuk mengambil langkah lebih lanjut dan memposting satu pendekatan untuk mengubah seluruh tabel pada suatu waktu - skrip tsql untuk menghasilkan pernyataan kolom alter:

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)

mendapat: ALTER TABLE Afiliasi ALTER COLUM myTable NVARCHAR (4000) COLLATE Latin1_General_CI_AS BUKAN NULL

Saya akan mengaku bingung oleh kebutuhan untuk col.max_length / 2 -

justSteve
sumber
Saya pikir pembagian dengan dua diperlukan karena panjangnya disimpan sebagai jumlah byte secara internal. Nvarchar mengambil dua byte per karakter alih-alih satu sebagai varchar.
Zebi
Kerja bagus, bagaimana pun di atas jumlah dosis kueri untuk tipe data ncha mungkin karena col.max_length / 2 -
Imran
2

Bagi mereka yang memiliki skrip CREATE DATABASE (seperti kasus saya) untuk database yang menyebabkan masalah ini, Anda dapat menggunakan skrip CREATE berikut untuk mencocokkan collation:

-- 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

atau

-- 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

Ini menerapkan susunan yang diinginkan untuk semua tabel, yang memang saya butuhkan. Ini sangat ideal untuk mencoba dan menjaga pemeriksaan yang sama untuk semua database di server. Semoga ini membantu.

Info lebih lanjut tentang tautan berikut: SQL SERVER - Membuat Basis Data dengan Berbagai Susunan di Server

pechar
sumber
2

Saya telah menggunakan konten dari situs ini untuk membuat skrip berikut yang mengubah susunan semua kolom di semua tabel:

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
Chagbert
sumber
1
SYSCOLUMNS. Panjang kolom nvarchar harus dibagi 2
palota
2

Periksa tingkat susunan yang tidak cocok (server, database, tabel, kolom, karakter).

Jika itu adalah server, langkah-langkah ini membantu saya sekali:

  1. Hentikan server
  2. Temukan alat sqlservr.exe Anda
  3. Jalankan perintah ini:

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

  4. Mulai server sql Anda:

    net start name_of_instance

  5. Periksa susunan server Anda lagi.

Ini info lebih lanjut:

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

WholeLifeLearner
sumber
2

Jika ini terjadi di seluruh DB Anda, maka lebih baik untuk mengubah susunan DB Anda seperti:

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 

Rujukan di sini

Justin
sumber
sayangnya ini tidak akan mengubah susunan untuk tabel yang ada, tetapi hanya default untuk tabel baru
RockScience
2

Menambahkan kode ke jawaban @ JustSteve untuk menangani kolom varchar dan 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)
Goner Doug
sumber
2

Untuk mengatasi masalah ini dalam kueri tanpa mengubah basis data, Anda dapat memberikan ekspresi di sisi lain dari tanda "=" dengan

COLLATE SQL_Latin1_General_CP1_CI_AS

seperti yang disarankan di sini .

Lars Ericson
sumber
1

Saya memiliki kesalahan yang serupa (Tidak dapat menyelesaikan konflik pemeriksaan antara "SQL_Latin1_General_CP1_CI_AS" dan "SQL_Latin1_General_CP1250_CI_AS" dalam operasi INTERSECT), ketika saya menggunakan driver jdbc lama.

Saya menyelesaikan ini dengan mengunduh driver baru dari Microsoft atau proyek open-source jTDS .

Krzy-wa
sumber
1

inilah yang kami lakukan, dalam situasi kami, kami memerlukan kueri ad hoc untuk dieksekusi menggunakan batasan tanggal pada permintaan, dan kueri tersebut didefinisikan dalam tabel.

Permintaan baru kami harus mencocokkan data antara database yang berbeda dan memasukkan data dari keduanya.

Tampaknya COLLATION berbeda antara db yang mengimpor data dari sistem iSeries / AS400, dan basis data pelaporan kami - ini bisa jadi karena tipe data spesifik (seperti aksen Yunani pada nama dan sebagainya).

Jadi kami menggunakan klausa gabungan di bawah ini:

...LEFT Outer join ImportDB..C4CTP C4 on C4.C4CTP COLLATE Latin1_General_CS_AS=CUS_Type COLLATE Latin1_General_CS_AS
Manusia kita di Pisang
sumber
1

Anda dapat dengan mudah melakukan ini dengan menggunakan 4 langkah mudah

  1. backup database Anda, cukup memetikan
  2. ubah susunan basis data: klik kanan basis data, pilih properti, buka opsi dan ubah susunan ke susunan yang diperlukan.
  3. Buat skrip untuk Jatuhkan dan Buat kembali semua objek basis data Anda: klik kanan basis data Anda, pilih tugas, pilih buat skrip ... (pastikan Anda memilih Drop & Buat pada opsi Advanced Wizard, Juga pilih Skema & Data)
  4. Jalankan Script Generated di atas
Felix Mwiti Mugambi
sumber
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 )
Arati
sumber
0

Anda mungkin tidak memiliki masalah pengumpulan apa pun di basis data Anda, tetapi jika Anda mengembalikan salinan basis data Anda dari cadangan di server dengan susunan berbeda dari asalnya, dan kode Anda membuat tabel sementara, tabel temporer tersebut akan mewarisi pengumpulan dari server dan akan ada konflik dengan database Anda.

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

Saya memiliki persyaratan serupa; mendokumentasikan pendekatan saya di sini untuk siapa pun dengan skenario yang sama ...

Skenario

  • Saya memiliki database dari instalasi yang bersih dengan koleksi yang benar.
  • Saya memiliki database lain yang memiliki susunan yang salah.
  • Saya perlu memperbarui yang terakhir untuk menggunakan koleksi yang ditentukan pada yang sebelumnya.

Larutan

Gunakan perbandingan skema SQL Server (dari SQL Server Data Tools / Visual Studio) untuk membandingkan sumber (instalasi bersih) dengan tujuan (db dengan susunan tidak valid).

Dalam kasus saya, saya membandingkan dua DB secara langsung; meskipun Anda dapat bekerja melalui proyek untuk memungkinkan Anda untuk secara manual mengubah bagian di antara ...

  • Jalankan Visual Studio
  • Buat Proyek Data SQL Server baru
  • Klik Alat, SQL Server, Perbandingan Skema Baru
  • Pilih basis data sumber
  • Pilih database target
  • Opsi klik (⚙)
    • Di bawah Object Typespilih hanya jenis yang Anda minati (bagi saya itu hanya Viewsdan Tables)
    • Di bawah Generalpilih:
      • Blokir kemungkinan hilangnya data
      • Nonaktifkan & aktifkan pemicu DDL
      • Abaikan jalur file penyedia kriptografis
      • Abaikan File & Log File Path
      • Abaikan ukuran file
      • Abaikan penempatan filegroup
      • Abaikan jalur file katalog teks lengkap
      • Abaikan casing kata kunci
      • Abaikan SID login
      • Abaikan pengidentifikasi yang dikutip
      • Abaikan rute seumur hidup
      • Abaikan titik koma di antara pernyataan
      • Abaikan spasi putih
      • Modul refresh skrip
      • Validasi skrip untuk kendala baru
      • Verifikasi kompatibilitas susunan
      • Verifikasi penyebaran
  • Klik Bandingkan
    • Hapus tanda centang pada objek yang ditandai untuk dihapus (NB: objek tersebut mungkin masih memiliki masalah collation; tetapi karena mereka tidak didefinisikan dalam sumber / template kita db kita tidak tahu; bagaimanapun, kita tidak ingin kehilangan sesuatu jika kita hanya penargetan yang akan diubah). Anda dapat menghapus centang pada semua sekaligus dengan mengklik kanan pada DELETEfolder dan memilih EXCLUDE.
    • Demikian juga untuk mengecualikan CREATE objek (di sini karena mereka tidak ada dalam target mereka tidak dapat memiliki susunan yang salah di sana; apakah mereka harus ada adalah pertanyaan untuk topik lain).
    • Klik pada setiap objek di bawah GANTI untuk melihat skrip untuk objek itu. Gunakan diff untuk memastikan bahwa kami hanya mengubah susunan (apa pun perbedaan lain yang terdeteksi secara manual Anda mungkin ingin mengecualikan / menangani objek-objek itu secara manual).
  • Klik Updateuntuk mendorong perubahan

Ini masih melibatkan beberapa upaya manual (mis. Memeriksa bahwa Anda hanya memengaruhi pemeriksaan) - tetapi ini menangani dependensi untuk Anda.

Anda juga dapat menyimpan proyek database dari skema yang valid sehingga Anda dapat menggunakan templat universal untuk DB Anda jika Anda memiliki lebih dari 1 untuk memperbarui, dengan asumsi semua DB target harus berakhir dengan skema yang sama.

Anda juga dapat menggunakan temukan / ganti pada file dalam proyek basis data jika Anda ingin mengubah pengaturan di sana secara massal (misalnya agar Anda dapat membuat proyek dari basis data yang tidak valid menggunakan skema bandingkan, mengubah file proyek, kemudian beralih sumber / target dalam skema bandingkan untuk mendorong perubahan Anda kembali ke DB).

JohnLBevan
sumber