Sebelum melakukan sesuatu, harap pertimbangkan pertanyaan yang diajukan oleh @RDFozz dalam komentar pada pertanyaan, yaitu:
Apakah ada setiap sumber lain selain [Q].[G]
mengisi tabel ini?
Jika responsnya adalah sesuatu di luar "Saya 100% yakin bahwa ini adalah satu - satunya sumber data untuk tabel tujuan ini", maka jangan membuat perubahan apa pun, terlepas dari apakah data saat ini dalam tabel dapat dikonversi tanpa Data hilang.
Apakah ada setiap rencana / diskusi terkait dengan menambahkan sumber tambahan untuk mengisi data ini dalam waktu dekat?
Dan saya akan menambahkan pertanyaan terkait: Sudah ada diskusi sekitar yang mendukung beberapa bahasa dalam tabel sumber arus (yaitu [Q].[G]
) dengan mengkonversi itu untuk NVARCHAR
?
Anda perlu bertanya-tanya untuk mengetahui kemungkinan-kemungkinan ini. Saya berasumsi bahwa saat ini Anda belum diberi tahu apa pun yang akan mengarah ke arah ini, Anda tidak akan mengajukan pertanyaan ini, tetapi jika pertanyaan-pertanyaan ini dianggap "tidak", maka mereka perlu ditanyakan, dan ditanya tentang audiens yang cukup luas untuk mendapatkan jawaban yang paling akurat / lengkap.
Masalah utama di sini adalah tidak begitu banyak memiliki poin kode Unicode yang tidak dapat dikonversi (pernah), tetapi lebih dari itu memiliki poin kode yang tidak akan cocok semua ke halaman kode tunggal. Itu hal yang menyenangkan tentang Unicode: itu dapat menampung karakter dari SEMUA halaman kode. Jika Anda mengonversi dari NVARCHAR
- tempat Anda tidak perlu khawatir tentang halaman kode - ke VARCHAR
, maka Anda perlu memastikan bahwa Kolasi kolom tujuan menggunakan halaman kode yang sama dengan kolom sumber. Ini mengasumsikan memiliki satu sumber, atau beberapa sumber menggunakan halaman kode yang sama (meskipun tidak harus sama dengan Collation). Tetapi jika ada banyak sumber dengan banyak halaman kode, maka Anda berpotensi mengalami masalah berikut:
DECLARE @Reporting TABLE
(
ID INT IDENTITY(1, 1) PRIMARY KEY,
SourceSlovak VARCHAR(50) COLLATE Slovak_CI_AS,
SourceHebrew VARCHAR(50) COLLATE Hebrew_CI_AS,
Destination NVARCHAR(50) COLLATE Latin1_General_CI_AS,
DestinationS VARCHAR(50) COLLATE Slovak_CI_AS,
DestinationH VARCHAR(50) COLLATE Hebrew_CI_AS
);
INSERT INTO @Reporting ([SourceSlovak]) VALUES (0xDE20FA);
INSERT INTO @Reporting ([SourceHebrew]) VALUES (0xE820FA);
UPDATE @Reporting
SET [Destination] = [SourceSlovak]
WHERE [SourceSlovak] IS NOT NULL;
UPDATE @Reporting
SET [Destination] = [SourceHebrew]
WHERE [SourceHebrew] IS NOT NULL;
SELECT * FROM @Reporting;
UPDATE @Reporting
SET [DestinationS] = [Destination],
[DestinationH] = [Destination]
SELECT * FROM @Reporting;
Pengembalian (set hasil 2):
ID SourceSlovak SourceHebrew Destination DestinationS DestinationH
1 Ţ ú NULL Ţ ú Ţ ú ? ?
2 NULL ט ת ? ? ט ת ט ת
Seperti yang Anda lihat, semua karakter itu dapat dikonversi menjadi VARCHAR
, hanya saja tidak di VARCHAR
kolom yang sama .
Gunakan kueri berikut untuk menentukan apa halaman kode untuk setiap kolom tabel sumber Anda:
SELECT OBJECT_NAME(sc.[object_id]) AS [TableName],
COLLATIONPROPERTY(sc.[collation_name], 'CodePage') AS [CodePage],
sc.*
FROM sys.columns sc
WHERE OBJECT_NAME(sc.[object_id]) = N'source_table_name';
YANG TELAH DIBILANG....
Anda menyebutkan berada di SQL Server 2008 R2, TAPI, Anda tidak mengatakan Edisi apa. JIKA Anda berada di Edisi Perusahaan, lupakan semua hal konversi ini (karena Anda kemungkinan melakukannya hanya untuk menghemat ruang), dan aktifkan Kompresi Data:
Implementasi Kompresi Unicode
Jika menggunakan Edisi Standar (dan sekarang sepertinya Anda adalah 😞) maka ada kemungkinan lain yang lebih mudah: perbarui ke SQL Server 2016 karena SP1 mencakup kemampuan untuk semua Edisi untuk menggunakan Kompresi Data (ingat, saya memang mengatakan "tembakan panjang" "😉).
Tentu saja, sekarang baru saja diklarifikasi bahwa hanya ada satu sumber untuk data, maka Anda tidak perlu khawatir karena sumber tidak dapat berisi karakter hanya Unicode, atau karakter di luar kode spesifiknya halaman. Dalam hal ini, satu-satunya hal yang harus Anda perhatikan adalah menggunakan Collation yang sama dengan kolom sumber, atau setidaknya satu yang menggunakan Halaman Kode yang sama. Artinya, jika kolom sumber menggunakan SQL_Latin1_General_CP1_CI_AS
, maka Anda bisa menggunakan Latin1_General_100_CI_AS
di tempat tujuan.
Setelah mengetahui Collation apa yang akan digunakan, Anda dapat:
ALTER TABLE ... ALTER COLUMN ...
menjadi VARCHAR
(pastikan untuk menentukan pengaturan NULL
/ saat ini NOT NULL
), yang membutuhkan sedikit waktu dan banyak ruang log transaksi untuk 87 juta baris, ATAU
Buat kolom "ColumnName_tmp" baru untuk masing-masing kolom dan perlahan-lahan isi dengan UPDATE
melakukan TOP (1000) ... WHERE new_column IS NULL
. Setelah semua baris diisi (dan divalidasi bahwa mereka semua disalin dengan benar! Anda mungkin perlu pemicu untuk menangani UPDATE, jika ada), dalam transaksi eksplisit, gunakan sp_rename
untuk menukar nama kolom dari kolom "saat ini" menjadi " _Old "dan kemudian kolom" _tmp "baru untuk menghapus" _tmp "dari nama. Kemudian panggil sp_reconfigure
meja untuk membatalkan rencana cache yang mereferensikan tabel, dan jika ada Tampilan yang mereferensikan tabel Anda perlu menelepon sp_refreshview
(atau sesuatu seperti itu). Setelah Anda memvalidasi aplikasi dan ETL bekerja dengan benar, maka Anda dapat menjatuhkan kolom.
[G]
ETLed ke[P]
. Jika[G]
adalahvarchar
, dan proses ETL adalah satu-satunya cara data yang datang ke dalam[P]
, maka kecuali proses menambahkan karakter Unicode yang benar, ada tidak boleh ada. Jika proses lain menambah atau memodifikasi data[P]
, Anda harus lebih berhati-hati - hanya karena semua data saatvarchar
ini tidak berarti bahwanvarchar
data tidak dapat ditambahkan besok. Demikian pula, ada kemungkinan bahwa apa pun yang mengkonsumsi data dalam data[P]
kebutuhannvarchar
.