PDA

View Full Version : Collation nào cho tiếng Việt?



thangvq
19-06-2007, 19:27
Hi,

Để nhập dữ liệu tiếng Việt Unicode (dựng sẵn) thì chỉ cần dùng collation SQL_Latin1_General_CP1_CI_AS (mặc định) là được. Tuy nhiên kết quả sắp xếp lại không đúng theo thứ tự trong tự điển. Tôi thử (insert/query trong SQL Server 2000) với các chữ a, á, â, ẩ... thì thấy dấu ngã được xếp trước dấu hỏi; chữ ầ xếp trước chữ ả,...

Vậy collaction nào hỗ trợ sắp xếp tiếng Việt Unicode dựng sẵn?

QuanN
03-03-2008, 08:30
Bạn thử collation Vietnamese_CI_AS. Không bảo đảm sẽ work với Unicode dựng sẵn vì 1258 tương tự với Unicode tổ hợp.

Windows System Locale: Vietnamese
LCID (Locale ID): 0x42a
Default SQL Collation: Vietnamese_CI_AS
Code page: 1258

QuanN
03-03-2008, 10:49
Thử chạy query này để lấy tên collation cho TV:


SELECT
name,
COLLATIONPROPERTY(name, 'CodePage') as CodePage,
COLLATIONPROPERTY(name, 'LCID') as LCID,
COLLATIONPROPERTY(name, 'ComparisonStyle') as ComparisonStyle,
description
FROM ::fn_helpcollations()

vqt
15-03-2008, 00:33
Cảm ơn bạn,

Tôi tìm đỏ cả mắt mà không tìm thấy dòng Vietnamese trong mục Windows System Locale. Vậy là không đổi được locale tiếng Việt cho Windows. Tại sao lại thế nhỉ. Tôi thử trên Window XP Pro SP2 & SP3 đều như vậy. Có ai biết không?

Cách đổi Windows System Locale như sau: http://www.java.com/en/download/help/locale.xml

QuanN
16-03-2008, 08:30
Đơn giản là vì Vietnamese locale không được loaded by default. Bạn phải manually load nó.

How to add a language collection in Windows XP?
• From Start menu, select Settings then Control Panel.
• Start Regional Options.
• Click on Languages tab.
• In Supplemental language support box, check the checkboxes of desired language collection(s) (select Install files for complex script for Vietnamese) and click OK.
• Additional files will be copied to your machine. You may need to provide the Windows XP CD or the network share name.
• After reboot, support for new languages will become available.

vqt
18-03-2008, 01:55
Cảm ơn bạn,

Tôi đã setup được rồi. Đúng như bạn đề nghị là Windows System Locale: Vietnamese, Default SQL Collation: Vietnamese_CI_AS. Tuy nhiên kết quả thử nghiệm thấy vẫn không ổn. Giả sử có bảng dữ liệu như sau:

1 ả ả
2 à à
3 ạ ạ
4 ê ê
5 â â
6 ậ ậ
7 ẩ ẩ
8 ằ ắ
9 ắ ắ
10 ă ă
11 á á
12 a a

Trong đó cột chữ thứ nhất dùng bảng mã Unicode, cột chữ thứ 2 dùng bảng mã Vietnamese locale CP 1258 theo cách gọi của Unikey.

Query order by cột chữ thứ nhất:

12 a a
11 á á
2 à à
9 ắ ắ
8 ằ ắ
1 ả ả
7 ẩ ẩ
3 ạ ạ
6 ậ ậ
5 â â
10 ă ă
4 ê ê

Query order by cột chữ thứ hai:

12 a a
1 ả ả
3 ạ ạ
11 á á
2 à à
5 â â
7 ẩ ẩ
6 ậ ậ
10 ă ă
9 ắ ắ
8 ằ ắ
4 ê ê

Có thể thấy là cái thứ hai sắp xếp tốt hơn cái thứ nhất. Cái thứ nhất a với ă còn lẫn vào nhau. Cái thứ hai chỉ lẫn về dấu. Theo đúng trật tự từ điển thì phải là không dấu rồi dấu sắc, huyền, hỏi, ngã và nặng.

QuanN
19-03-2008, 07:36
Vì Vietnamese_CI_AS tạo theo chuẩn CP 1258 cho nên kết quả chính xác cho Tổ hợp (Unicode composite) hơn cho Dựng sẵn (precomposed), nhưng do có bug trong Collation Table phần Tiếng Việt trong Windows cho nên vẫn sai.

http://dotnetfire.com/news.aspx?newsID=3925

Đáng lẽ bug trên được sửa trong Vista, nhưng do không có ai lưu tâm tới cho nên lại bị bug khác khi MS sửa chữa bug nguyên thủy, thành ra sắp xếp TV vẫn không hoàn chỉnh.

http://blogs.msdn.com/michkap/archive/2005/08/27/457224.aspx

TV được sắp xếp theo thứ tự "huyền, hỏi, ngã, sắc, nặng".

http://vietunicode.sourceforge.net/charset/vietalphabet.html

QuanN
19-03-2008, 07:42
Ngoài ra, tôi nghĩ là không cần phải đổi Windows System Locale để có Vietnamese_CI_AS collation. Bạn có thể override default collation, như sau:


SELECT * FROM aTable ORDER BY aColumn COLLATE Vietnamese_CI_AS

vqt
19-03-2008, 22:25
Cảm ơn bạn. Thông tin của bạn rất có giá trị. Nhưng có điều lạ là sao từ trước tới giờ ít người quan tâm đến vấn đề này thế nhỉ. Đến nỗi cái tay Michael đấy nói là không thấy ai report và còn bảo mấy cái chữ bị lỗi chắc là ít dùng. Hy vọng là ngoài bạn ra còn nhiều người khác nữa sẽ theo đuổi vấn đề này.

QuanN
12-05-2009, 11:19
MS cần sửa collation data của Windows để SQL Server có thể sắp xếp dữ liệu Tiếng Việt theo đúng thứ tự abc (sort data in correct Vietnamese alphabetical order).

Gửi yêu cầu tới Microsoft về Tiếng Việt trong Windows 7 (http://ddth.com/showthread.php?t=272339)

dq_ninh
13-05-2009, 07:21
Cảm ơn bạn. Thông tin của bạn rất có giá trị. Nhưng có điều lạ là sao từ trước tới giờ ít người quan tâm đến vấn đề này thế nhỉ. Đến nỗi cái tay Michael đấy nói là không thấy ai report và còn bảo mấy cái chữ bị lỗi chắc là ít dùng. Hy vọng là ngoài bạn ra còn nhiều người khác nữa sẽ theo đuổi vấn đề này.

Bạn vào www.phuong-dong.com, rồi qua mục Kiến Thức. Trong đó có bài viết về phương pháp lấy bảng theo thứ tự ABC.

Các mẫu Unicode tiếng Việt đều không theo thứ tự ABC có dấu. Đây là một chuyện đáng tiếc, nhưng không thể thay đổi được, vì nó liên quan đến nhiều vấn đề khác, đặc biệt là bàn phím và keyboard driver. Nếu muốn có một mẫu Unicode có thứ tự ABC có dấu, chúng ta phải có bàn phím riêng, và phải có phiên bản Windows cho tiếng Việt riêng. Và nếu có bàn phím riêng, phiên bản Windows riêng, chúng ta lại có thêm những vấn đề mới rắc rối hơn.

Van8Hien62
15-05-2009, 10:38
Tôi thấy nhiều bạn bi quan quá, có nhiều đường đến được Roma kia mà. Trước đây và hiện nay vẫn còn nhiều nơi sử dụng tiếng Việt không dấu, không phải là chưa được. Cách nay trên 15 năm đã có VietRes, VietWare rồi. Một phần có do ích kỷ của một số LTV, như VietKey 4.x, một phần do cán bộ cấp cao bận việc, phần nữa do chúng ta ham chơi, không tìm, không làm, nên nó không phổ biến.

Có những người như Phạm Kim Long, ( UniKey,) như anh dq_ninh (www.phuong-dong.com) thật đáng trân trọng. Dù CT chưa phải là tối ưu, nhưng tấm lòng thật đáng biết ơn.

Sẵn tôi gửi các bạn tham khảo đoạn script sau:

--Udds / Domains: tiếng Việt dài nhất là "nghiêng" 7 chữ cái
exec sp_addType N'aWord', N'nVarChar(10)', N'not null'
exec sp_addType N'Parag', N'nVarChar(30)', N'null'
exec sp_addType N'FnRet', N'Varchar(102)', N'not null'
go
--exec sp_droptype N'Parag'
create function conv_uVni2Ascii(
@sHo5 aWord, @sLot1 Parag, @sTen6 aWord
)
returns FnRet --with encryption
as begin-- Tên Họ Lót / rightMost middle leftMost
declare @idx int, @iLn int, @nDiv int, @nMod int
, @sUni nVarChar(61), @sRet FnRet, @sTmp FnRet, @Ktu nChar
--Phân hoạch lấy phần cuối bảng mã Ascii
if(@sLot1 is null or @sLot1 = '')
set @sTmp = lower( @sTen6 + ' ' + @sHo5 )
else set @sTmp = lower( @sTen6 + ' ' + @sHo5 + ' ' + @sLot1 )
--
select @sRet = N''
, @sUni = N'aáàảãạăắằẳẵặâấầẩẫậe éèẻẽẹêếềểễệiíìỉĩịoóò õọơớờởỡợôốồổỗộuúùủũ ụưứừửữựyýỳỷỹỵdđ'
-- N'aáàảãạ' + N'ăắằẳẵặ' + N'âấầẩẫậ' + N'eéèẻẽẹ' + N'êếềểễệ' + N'iíìỉĩị'
-- + N'oóòỏõọ' + N'ơớờởỡợ' + N'ôốồổỗộ' + N'uúùủũụ' + N'ưứừửữự' + N'yýỳỷỹỵ' + N'dđ'
, @idx = 0, @iLn = len( @sTmp )
while( @idx < @iLn ) begin
select @idx = @idx + 1, @Ktu = subString(@sTmp, @idx, 1), @nDiv = charIndex(@Ktu, @sUni) -1
if (@nDiv > -1) begin
select @nMod = @nDiv % 6, @nDiv = @nDiv / 6
--Phần trước bảng mã, thuật toán the Caesar cipher
if (@nDiv = 0) set @sRet = @sRet + N'a' + char( @nMod + 48 + 0)--ofs1 a
else if (@nDiv = 1) set @sRet = @sRet + N'a' + char( @nMod + 48 + 10)--ofs2 ă
else if (@nDiv = 2) set @sRet = @sRet + N'a' + char( @nMod + 48 + 20)--ofs3 â
else if (@nDiv = 3) set @sRet = @sRet + N'e' + char( @nMod + 48 + 0)--ofs1 e
else if (@nDiv = 4) set @sRet = @sRet + N'e' + char( @nMod + 48 + 10)--ofs2 ê
else if (@nDiv = 5) set @sRet = @sRet + N'i' + char( @nMod + 48 + 0)--ofs1 i
else if (@nDiv = 6) set @sRet = @sRet + N'o' + char( @nMod + 48 + 0)--ofs1 o
else if (@nDiv = 7) set @sRet = @sRet + N'o' + char( @nMod + 48 + 10)--ofs2 ơ
else if (@nDiv = 8) set @sRet = @sRet + N'o' + char( @nMod + 48 + 20)--ofs3 ô
else if (@nDiv = 9) set @sRet = @sRet + N'u' + char( @nMod + 48 + 0)--ofs1 u
else if (@nDiv = 10)set @sRet = @sRet + N'u' + char( @nMod + 48 + 10)--ofs2 ư
else if (@nDiv = 11)set @sRet = @sRet + N'y' + char( @nMod + 48 + 0)--ofs1 y
else if (@nDiv = 12)set @sRet = @sRet + N'd' + char( @nMod + 48 + 0)--ofs1 d, đ
end else set @sRet = @sRet + @Ktu
end
return @sRet
end
go
--
create table bgNhan6Vien6 (
stt int IDENTITY (1, 1) primary key ,
Ho5 aWord ,
Lot1 Parag ,
Ten6 aWord ,
Ho5Va2Ten6 as Ho5 + isNull(' ' + Lot1, '') + ' ' + Ten6 ,
Cot6Sap81Xep61 as dbo.conv_uVni2Ascii(Ho5, Lot1, Ten6) --Bạn có thể dùng Trigger
--Các column khác ...
) --on [primary]
go

insert bgNhan6Vien6(Ho5, Lot1, Ten6) values(N'Dương', N'Quang', N'Thiện')
insert bgNhan6Vien6(Ho5, Lot1, Ten6) values(N'Hoàng', N'Thị', N'Loan')
insert bgNhan6Vien6(Ho5, Lot1, Ten6) values(N'Trương', N'Công', N'Tuấn')
insert bgNhan6Vien6(Ho5, Lot1, Ten6) values(N'Văn', N'Như', N'Cương')
insert bgNhan6Vien6(Ho5, Ten6) values(N'Văn', N'Tần')
insert bgNhan6Vien6(Ho5, Lot1, Ten6) values(N'Văn', N'Tấn', N'Văn')
insert bgNhan6Vien6(Ho5, Ten6) values(N'Nguyễn', N'Hiền')
insert bgNhan6Vien6(Ho5, Ten6) values(N'Văn', N'Hiền')
insert bgNhan6Vien6(Ho5, Lot1, Ten6) values(N'Lê', N'Tiến', N'Vương')
go
-- Lưu ý việc kiểm soát chứa trong Domain / Uddt
--insert bgNhan6Vien6(Ho5, Lot1) values(N'Võ', N'Nguyên')
--insert bgNhan6Vien6(Lot1, Ten6) values(N'Nguyên', N'Giáp')
--
select stt, 'Họ và Tên Nhân Viên'= Ho5Va2Ten6 from bgNhan6Vien6 order by Cot6Sap81Xep61
go
--truncate table bgNhan6Vien6

--
/*
drop table bgNhan6Vien6
drop function get_uVni2Ascii
exec sp_droptype N'Parag'
exec sp_droptype N'aWord'
exec sp_droptype N'FnRet'
*/
Thân

[=========> Bổ sung bài viết <=========]

Do forum này không đúng là WYSIWYG, các bạn có thể vào (www.phuong-dong.com) xem lại những ký tự không hiện thị được. Script tôi viết có phần nào đó giống với anh qn_ninh.

Văn Hiền

[=========> Bổ sung bài viết <=========]

các bạn vui lòng sửa :
exec sp_addType N'FnRet', N'Varchar(102)', N'not null'
thành exec sp_addType N'FnRet', N'Varchar(104)', N'not null'

@sUni nVarChar(61), thành @sUni nVarChar(74),
và drop function get_uVni2Ascii thành drop function conv_uVni2Ascii

74= 12( khối ) * 6 ( ký tự ) + 2 ( dđ)
102= 2 * ( 10 + 1 + 30 + 1 + 10 )

xin cáo lỗi, CT cũ không kịp cập nhật.

[=========> Bổ sung bài viết <=========]

Tôi trình bày giải pháp, có ý để lại vài lỗi. Tôi buồn lòng khi chưa nhận thấy sự phản hồi. Không lẽ những người dám tự hào là ( thần ) dân IT chỉ có khả năng nhờ người khác giải quyết vấn đề mình không làm được, chứ không phải là hỏi ( người khác ) để khẳng định ý kiến của chính bản thân mình!!!