Trước khi làm bất cứ điều gì, vui lòng xem xét các câu hỏi được đặt ra bởi @RDFozz trong một nhận xét về câu hỏi, cụ thể là:
Có bất kỳ nguồn khác ngoài việc điền [Q].[G]
vào bảng này không?
Nếu phản hồi là bất cứ điều gì ngoài "Tôi chắc chắn 100% rằng đây là nguồn dữ liệu duy nhất cho bảng đích này", thì đừng thực hiện bất kỳ thay đổi nào, bất kể dữ liệu hiện tại trong bảng có thể được chuyển đổi mà không mất dữ liệu.
Có ở đó không bất kỳ kế hoạch / thảo luận liên quan đến việc thêm nguồn bổ sung để cư dữ liệu này trong tương lai gần?
Và tôi sẽ thêm một câu hỏi liên quan: Đã có bất kỳ cuộc thảo luận nào về việc hỗ trợ nhiều ngôn ngữ trong bảng nguồn hiện tại (tức là [Q].[G]
) bằng cách chuyển đổi nó thành NVARCHAR
?
Bạn sẽ cần phải hỏi xung quanh để hiểu được những khả năng này. Tôi cho rằng bạn hiện chưa được nói bất cứ điều gì sẽ chỉ theo hướng này nếu không bạn sẽ hỏi câu hỏi này, nhưng nếu những câu hỏi này được cho là "không", thì chúng cần được hỏi và được hỏi về đối tượng đủ rộng để có được câu trả lời chính xác / đầy đủ nhất.
Vấn đề chính ở đây không phải là có quá nhiều điểm mã Unicode không thể chuyển đổi (bao giờ), mà còn có nhiều điểm mã không phù hợp với một trang mã. Đó là điều hay về Unicode: nó có thể chứa các ký tự từ TẤT CẢ các trang mã. Nếu bạn chuyển đổi từ NVARCHAR
- nơi bạn không cần phải lo lắng về các trang mã - sang VARCHAR
, thì bạn sẽ cần đảm bảo rằng Collation của cột đích đang sử dụng cùng một trang mã với cột nguồn. Điều này giả sử có một nguồn hoặc nhiều nguồn sử dụng cùng một trang mã (mặc dù không nhất thiết phải là Collation giống nhau). Nhưng nếu có nhiều nguồn với nhiều trang mã, thì bạn có khả năng gặp phải vấn đề sau:
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;
Trả về (tập kết quả thứ 2):
ID SourceSlovak SourceHebrew Destination DestinationS DestinationH
1 Ţ ú NULL Ţ ú Ţ ú ? ?
2 NULL ט ת ? ? ט ת ט ת
Như bạn có thể thấy, tất cả các ký tự đó có thể chuyển đổi thành VARCHAR
, chỉ không trong cùng một VARCHAR
cột.
Sử dụng truy vấn sau để xác định trang mã nào cho mỗi cột trong bảng nguồn của bạn:
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';
ĐÓ LÀ NÓI ....
Bạn đã đề cập đến trên SQL Server 2008 R2, NHƯNG, bạn không nói Phiên bản nào. NẾU bạn tình cờ có trên Phiên bản doanh nghiệp, sau đó quên tất cả nội dung chuyển đổi này (vì bạn có thể làm việc đó chỉ để tiết kiệm dung lượng) và bật Nén dữ liệu:
Thực hiện nén Unicode
Nếu sử dụng Phiên bản Chuẩn (và có vẻ như bạn là 😞) thì có một khả năng khác là: nâng cấp lên SQL Server 2016 kể từ SP1 bao gồm khả năng cho tất cả các Phiên bản sử dụng Nén dữ liệu (hãy nhớ, tôi đã nói "bắn lâu ").
Tất nhiên, bây giờ chúng ta mới làm rõ rằng chỉ có một nguồn cho dữ liệu, thì bạn không có gì phải lo lắng vì nguồn này không chứa bất kỳ ký tự hoặc ký tự Unicode nào ngoài mã cụ thể của nó trang. Trong trường hợp đó, điều duy nhất bạn cần lưu ý là sử dụng Collation giống như cột nguồn hoặc ít nhất một cái đang sử dụng cùng một Trang Mã. Có nghĩa là, nếu cột nguồn đang sử dụng SQL_Latin1_General_CP1_CI_AS
, thì bạn có thể sử dụngLatin1_General_100_CI_AS
tại đích.
Khi bạn biết Collation sẽ sử dụng, bạn có thể:
ALTER TABLE ... ALTER COLUMN ...
để được VARCHAR
(chắc chắn chỉ định hiện tại NULL
/ NOT NULL
cài đặt), yêu cầu một chút thời gian và nhiều không gian nhật ký giao dịch cho 87 triệu hàng, HOẶC
Tạo các cột "ColumnName_tmp" mới cho mỗi cột và từ từ cư trú thông qua UPDATE
việc thực hiện TOP (1000) ... WHERE new_column IS NULL
. Khi tất cả các hàng được điền (và được xác thực rằng tất cả chúng đều được sao chép chính xác! Bạn có thể cần một trình kích hoạt để xử lý CẬP NHẬT, nếu có), trong một giao dịch rõ ràng, hãy sử dụng sp_rename
để hoán đổi tên cột của các cột "hiện tại" thành " _Old "và sau đó các cột" _tmp "mới chỉ cần xóa" _tmp "khỏi tên. Sau đó gọi sp_reconfigure
vào bảng để vô hiệu hóa bất kỳ gói được lưu trong bộ nhớ cache nào tham chiếu bảng và nếu có bất kỳ Chế độ xem nào tham chiếu bảng, bạn sẽ cần gọi sp_refreshview
(hoặc đại loại như thế). Khi bạn đã xác thực ứng dụng và ETL đang hoạt động chính xác với ứng dụng đó, thì bạn có thể thả các cột.
[G]
được ETLed qua[P]
. Nếu[G]
làvarchar
, và quy trình ETL là cách duy nhất để dữ liệu đi vào[P]
, trừ khi quy trình thêm các ký tự Unicode thực sự, không nên có bất kỳ. Nếu các quy trình khác thêm hoặc sửa đổi dữ liệu[P]
, bạn cần cẩn thận hơn - chỉ vì tất cả dữ liệu hiện tại có thểvarchar
không có nghĩa lànvarchar
dữ liệu không thể được thêm vào ngày mai. Tương tự như vậy, có thể là bất cứ điều gì đang tiêu thụ dữ liệu trong[P]
nhu cầunvarchar
dữ liệu.