ก่อนที่จะทำอะไรโปรดพิจารณาคำถามที่โพสต์โดย @RDFozz ในความคิดเห็นเกี่ยวกับคำถาม ได้แก่ :
มีใด ๆแหล่งอื่น ๆ นอกเหนือจาก[Q].[G]
ประชากรของตารางนี้?
ถ้าตอบอะไรนอก "ผม 100% บางอย่างที่ว่านี้เป็นเพียงแหล่งที่มาของข้อมูลสำหรับตารางปลายทางนี้" แล้วไม่ทำการเปลี่ยนแปลงใด ๆ โดยไม่คำนึงถึงหรือไม่ว่าข้อมูลปัจจุบันในตารางสามารถแปลงได้โดยไม่ต้อง การสูญเสียข้อมูล
มีใด ๆแผน / อภิปรายที่เกี่ยวข้องกับการเพิ่มแหล่งข้อมูลเพิ่มเติมเพื่อเติมข้อมูลนี้ในอนาคตอันใกล้?
และฉันจะเพิ่มคำถามที่เกี่ยวข้อง: ได้มีการอภิปรายใด ๆ รอบการสนับสนุนหลายภาษาในตารางมาในปัจจุบัน (คือ[Q].[G]
) โดยการแปลงมันไปNVARCHAR
?
คุณจะต้องถามเพื่อให้เข้าใจถึงความเป็นไปได้เหล่านี้ ฉันคิดว่าคุณยังไม่ได้รับการบอกกล่าวใด ๆ ที่จะชี้ไปในทิศทางนี้มิเช่นนั้นคุณจะไม่ถามคำถามนี้ แต่ถ้าคำถามเหล่านี้ถือว่าเป็น "ไม่" พวกเขาจะต้องถามและถามถึง ผู้ชมที่กว้างพอที่จะได้รับคำตอบที่ถูกต้อง / สมบูรณ์ที่สุด
ปัญหาหลักที่นี่มีไม่มากที่มีรหัส Unicode ชี้ว่า ไม่สามารถแปลงได้ (เคย) แต่มากขึ้นเพื่อให้มีจุดรหัสที่ไม่พอดีกับหน้ารหัสเดียว นั่นเป็นสิ่งที่ดีเกี่ยวกับ Unicode: มันสามารถเก็บอักขระจากหน้ารหัสทั้งหมด หากคุณแปลงจากNVARCHAR
- โดยที่คุณไม่ต้องกังวลเกี่ยวกับโค้ดเพจ - เป็นVARCHAR
คุณจะต้องตรวจสอบให้แน่ใจว่าการเรียงคอลัมน์คอลัมน์ปลายทางใช้โค้ดเพจเดียวกันกับคอลัมน์ซอร์ส สิ่งนี้ถือว่ามีแหล่งที่มาเดียวหรือหลายแหล่งโดยใช้โค้ดเพจเดียวกัน (ไม่จำเป็นต้องมี Collation เดียวกัน) แต่หากมีหลายแหล่งที่มีหลายหน้ารหัสคุณอาจพบปัญหาดังต่อไปนี้:
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;
ผลตอบแทน (ชุดผลลัพธ์ที่ 2):
ID SourceSlovak SourceHebrew Destination DestinationS DestinationH
1 Ţ ú NULL Ţ ú Ţ ú ? ?
2 NULL ט ת ? ? ט ת ט ת
อย่างที่คุณเห็นตัวละครทั้งหมดนั้น สามารถแปลงเป็นVARCHAR
ไม่ใช่ในVARCHAR
คอลัมน์เดียวกัน
ใช้แบบสอบถามต่อไปนี้เพื่อกำหนดว่าหน้ารหัสสำหรับแต่ละคอลัมน์ของตารางต้นฉบับของคุณคืออะไร:
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';
นั่นคือสิ่งที่กล่าวถึง ....
คุณพูดถึงว่าอยู่ใน SQL Server 2008 R2 แต่คุณไม่ได้พูดว่า Edition ใด หากคุณเกิดขึ้นกับ Enterprise Edition ให้ลืมสิ่งที่แปลงทั้งหมดนี้ (เนื่องจากคุณน่าจะทำเพื่อประหยัดพื้นที่) และเปิดใช้งานการบีบอัดข้อมูล:
การใช้การบีบอัด Unicode
ถ้าใช้ Standard Edition (และตอนนี้ดูเหมือนว่าคุณเป็น😞) แล้วมีความเป็นไปได้อีกอย่างคือ looooong-shot: อัปเกรดเป็น SQL Server 2016 เนื่องจาก SP1 มีความสามารถสำหรับทุกรุ่นในการใช้การบีบอัดข้อมูล (โปรดจำไว้ว่า "😉)
แน่นอนตอนนี้เพิ่งได้รับการชี้แจงว่ามีแหล่งข้อมูลเพียงแหล่งเดียวจากนั้นคุณไม่มีอะไรต้องกังวลเนื่องจากแหล่งข้อมูลไม่สามารถมีอักขระ Unicode-only หรืออักขระนอกรหัสที่เฉพาะเจาะจง หน้า. ในกรณีนี้สิ่งเดียวที่คุณควรระวังคือการใช้ Collation เดียวกันกับคอลัมน์ต้นฉบับหรืออย่างน้อยหนึ่งรายการที่ใช้หน้ารหัสเดียวกัน ความหมายถ้าคอลัมน์แหล่งที่มาใช้SQL_Latin1_General_CP1_CI_AS
คุณสามารถใช้Latin1_General_100_CI_AS
ที่ปลายทาง
เมื่อคุณรู้ว่าจะใช้ Collation ใดคุณสามารถ:
ALTER TABLE ... ALTER COLUMN ...
เป็นVARCHAR
(ต้องแน่ใจว่าได้ระบุการตั้งค่าปัจจุบันNULL
/ NOT NULL
) ซึ่งต้องใช้เวลาสักครู่และพื้นที่บันทึกธุรกรรมจำนวนมากสำหรับ 87 ล้านแถวหรือ
สร้างใหม่ "ColumnName_tmp" คอลัมน์สำหรับแต่ละคนและค่อยๆเติมผ่านการทำUPDATE
TOP (1000) ... WHERE new_column IS NULL
เมื่อแถวทั้งหมดมีประชากร (และตรวจสอบว่าพวกเขาคัดลอกทั้งหมดไปอย่างถูกต้อง! คุณอาจต้องมีทริกเกอร์ในการจัดการ UPDATE ถ้ามี) ในการทำธุรกรรมอย่างชัดเจนให้ใช้sp_rename
เพื่อสลับชื่อคอลัมน์ของคอลัมน์ "ปัจจุบัน" ที่จะ " _Old "จากนั้นคอลัมน์" _tmp "ใหม่ที่จะลบ" _tmp "ออกจากชื่อ จากนั้นโทรsp_reconfigure
บนโต๊ะเพื่อทำให้แผนการแคชใด ๆ ที่อ้างถึงตารางเป็นโมฆะและหากมีมุมมองใด ๆ ที่อ้างอิงถึงตารางคุณจะต้องโทรหาsp_refreshview
(หรืออะไรทำนองนั้น) เมื่อคุณตรวจสอบความถูกต้องของแอปแล้ว ETL ทำงานได้อย่างถูกต้องแล้วคุณสามารถวางคอลัมน์ได้
[G]
ETLed ผ่านไป[P]
แล้ว ถ้า[G]
เป็นvarchar
เช่นนั้นและกระบวนการ ETL เป็นเพียงวิธีเดียวที่ข้อมูลจะเข้ามา[P]
ดังนั้นหากกระบวนการไม่ได้เพิ่มอักขระ Unicode จริงก็ไม่ควรมี หากกระบวนการอื่นเพิ่มหรือแก้ไขข้อมูล[P]
คุณต้องระวังให้มากขึ้น - เพียงเพราะข้อมูลปัจจุบันทั้งหมดvarchar
ไม่สามารถหมายความว่าnvarchar
ข้อมูลไม่สามารถเพิ่มได้ในวันพรุ่งนี้ ในทำนองเดียวกันอาจเป็นไปได้ว่าสิ่งใดที่ใช้ข้อมูลที่[P]
ต้องการnvarchar
ข้อมูล