2015-01-27 8 views
8

से SQL सर्वर में टेक्स्ट मान कनवर्ट करें मेरे पास utf8 SQL_Latin1_General_CP1_CI_AS एन्कोडिंग के साथ SQL सर्वर में एक कॉलम है। मैं आईएसओ 885 9 -1 एन्कोडिंग में पाठ को कैसे परिवर्तित और सहेज सकता हूं? मैं SQL सर्वर पर एक क्वेरी में बात करना चाहता हूं। कोई सुझाव?यूटीएफ 8 से आईएसओ 8859-1

Olá। गोस्टे डू जोगो। Quando "baixei" atÃÆ'à ¢ एक £ o iria curtir muito

+1

के बाद से एसक्यूएल सर्वर वास्तव में समर्थन नहीं करता है UTF-8 पर ध्यान नहीं देता ! –

+0

कॉलम का डेटाटाइप क्या है: nvarchar, varchar या varbinary? और क्या यह सादे पाठ के रूप में संग्रहीत है, या यह प्रतिशत एनकोडेड है? –

+0

इसे सादे पाठ के रूप में संग्रहीत किया जाता है और टाइप टेक्स्ट का होता है। मैंने – bobK

उत्तर

13

मैं एक समारोह के लिए UTF-8 पाठ है कि एक varchar क्षेत्र में संग्रहीत किया जाता है की मरम्मत के लिए लिखा है।

तय मूल्यों की जाँच करने के लिए आप इसे इस तरह का उपयोग कर सकते हैं:

CREATE TABLE #Table1 (Column1 varchar(max)) 

INSERT #Table1 
VALUES ('Olá. Gostei do jogo. Quando "baixei" até achei que não iria curtir muito') 

SELECT *, NewColumn1 = dbo.DecodeUTF8String(Column1) 
FROM Table1 
WHERE Column1 <> dbo.DecodeUTF8String(Column1) 

आउटपुट:

Column1 
------------------------------- 
Olá. Gostei do jogo. Quando "baixei" até achei que não iria curtir muito 

NewColumn1 
------------------------------- 
Olá. Gostei do jogo. Quando "baixei" até achei que não iria curtir muito 

कोड:

CREATE FUNCTION dbo.DecodeUTF8String (@value varchar(max)) 
RETURNS nvarchar(max) 
AS 
BEGIN 
    -- Transforms a UTF-8 encoded varchar string into Unicode 
    -- By Anthony Faull 2014-07-31 
    DECLARE @result nvarchar(max); 

    -- If ASCII or null there's no work to do 
    IF (@value IS NULL 
     OR @value NOT LIKE '%[^ -~]%' COLLATE Latin1_General_BIN 
    ) 
     RETURN @value; 

    -- Generate all integers from 1 to the length of string 
    WITH e0(n) AS (SELECT TOP(POWER(2,POWER(2,0))) NULL FROM (VALUES (NULL),(NULL)) e(n)) 
     , e1(n) AS (SELECT TOP(POWER(2,POWER(2,1))) NULL FROM e0 CROSS JOIN e0 e) 
     , e2(n) AS (SELECT TOP(POWER(2,POWER(2,2))) NULL FROM e1 CROSS JOIN e1 e) 
     , e3(n) AS (SELECT TOP(POWER(2,POWER(2,3))) NULL FROM e2 CROSS JOIN e2 e) 
     , e4(n) AS (SELECT TOP(POWER(2,POWER(2,4))) NULL FROM e3 CROSS JOIN e3 e) 
     , e5(n) AS (SELECT TOP(POWER(2.,POWER(2,5)-1)-1) NULL FROM e4 CROSS JOIN e4 e) 
    , numbers(position) AS 
    (
     SELECT TOP(DATALENGTH(@value)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) 
     FROM e5 
    ) 
    -- UTF-8 Algorithm (http://en.wikipedia.org/wiki/UTF-8) 
    -- For each octet, count the high-order one bits, and extract the data bits. 
    , octets AS 
    (
     SELECT position, highorderones, partialcodepoint 
     FROM numbers a 
     -- Split UTF8 string into rows of one octet each. 
     CROSS APPLY (SELECT octet = ASCII(SUBSTRING(@value, position, 1))) b 
     -- Count the number of leading one bits 
     CROSS APPLY (SELECT highorderones = 8 - FLOOR(LOG(~CONVERT(tinyint, octet) * 2 + 1)/LOG(2))) c 
     CROSS APPLY (SELECT databits = 7 - highorderones) d 
     CROSS APPLY (SELECT partialcodepoint = octet % POWER(2, databits)) e 
    ) 
    -- Compute the Unicode codepoint for each sequence of 1 to 4 bytes 
    , codepoints AS 
    (
     SELECT position, codepoint 
     FROM 
     (
      -- Get the starting octect for each sequence (i.e. exclude the continuation bytes) 
      SELECT position, highorderones, partialcodepoint 
      FROM octets 
      WHERE highorderones <> 1 
     ) lead 
     CROSS APPLY (SELECT sequencelength = CASE WHEN highorderones in (1,2,3,4) THEN highorderones ELSE 1 END) b 
     CROSS APPLY (SELECT endposition = position + sequencelength - 1) c 
     CROSS APPLY 
     (
      -- Compute the codepoint of a single UTF-8 sequence 
      SELECT codepoint = SUM(POWER(2, shiftleft) * partialcodepoint) 
      FROM octets 
      CROSS APPLY (SELECT shiftleft = 6 * (endposition - position)) b 
      WHERE position BETWEEN lead.position AND endposition 
     ) d 
    ) 
    -- Concatenate the codepoints into a Unicode string 
    SELECT @result = CONVERT(xml, 
     (
      SELECT NCHAR(codepoint) 
      FROM codepoints 
      ORDER BY position 
      FOR XML PATH('') 
     )).value('.', 'nvarchar(max)'); 

    RETURN @result; 
END 
GO 
+0

पर एक स्निपेट जोड़ा, क्या आप इसे समझा सकते हैं? मैं अपने कॉलम मानों को बदलने के लिए इसका उपयोग कैसे करूं? – bobK

+0

जब मैं इसे SQL सर्वर प्रबंधन स्टूडियो में डालता हूं तो मुझे निम्न त्रुटियां मिलती हैं: संदेश 174, स्तर 15, राज्य 1, प्रक्रिया DecodeUTF8String, रेखा 29 लॉग फ़ंक्शन को 1 तर्क (ओं) की आवश्यकता होती है। संदेश 102, स्तर 15, राज्य 1, प्रक्रिया DecodeUTF8String, रेखा 30 'ई' के पास गलत वाक्यविन्यास। संदेश 102, स्तर 15, राज्य 1, प्रक्रिया DecodeUTF8String, लाइन 31 'एफ' के पास गलत वाक्यविन्यास। संदेश 195, स्तर 15, राज्य 10, रेखा 3 'DecodeUTF8String' एक मान्यता प्राप्त अंतर्निहित फ़ंक्शन नाम नहीं है। – bobK

+0

ठीक है, तो आप SQL सर्वर का पुराना संस्करण उपयोग कर रहे हैं। उस अभिव्यक्ति को 'फ़्लोर (LOG (2 * ~ CONVERT (tinyint, octet) + 1)/LOG (2)) में बदलने की कोशिश करें) - 1) ' –

0

मुझे वह क्वेरी मिली जो मुझे करने की ज़रूरत है, अभी तक एन्कोडिंग नहीं है।

ALTER TABLE dbo.MyTable ALTER COLUMN CharCol 
     varchar(10)COLLATE Latin1_General_CI_AS NOT NULL; 
1

Jason Penny भी written एक एसक्यूएल कार्य करने के लिए है यूटीएफ -8 को यूनिकोड (एमआईटी लाइसेंस) में परिवर्तित करें जो एक साधारण परीक्षा में काम करता है मेरे लिए मिसाल:

CREATE FUNCTION dbo.UTF8_TO_NVARCHAR(@in VarChar(MAX)) 
    RETURNS NVarChar(MAX) 
AS 
BEGIN 
    DECLARE @out NVarChar(MAX), @i int, @c int, @c2 int, @c3 int, @nc int 

    SELECT @i = 1, @out = '' 

    WHILE (@i <= Len(@in)) 
    BEGIN 
     SET @c = Ascii(SubString(@in, @i, 1)) 

     IF (@c < 128) 
     BEGIN 
     SET @nc = @c 
     SET @i = @i + 1 
     END 
     ELSE IF (@c > 191 AND @c < 224) 
     BEGIN 
     SET @c2 = Ascii(SubString(@in, @i + 1, 1)) 

     SET @nc = (((@c & 31) * 64 /* << 6 */) | (@c2 & 63)) 
     SET @i = @i + 2 
     END 
     ELSE 
     BEGIN 
     SET @c2 = Ascii(SubString(@in, @i + 1, 1)) 
     SET @c3 = Ascii(SubString(@in, @i + 2, 1)) 

     SET @nc = (((@c & 15) * 4096 /* << 12 */) | ((@c2 & 63) * 64 /* << 6 */) | (@c3 & 63)) 
     SET @i = @i + 3 
     END 

     SET @out = @out + NChar(@nc) 
    END 
    RETURN @out 
END 
GO 

टिक जवाब एंथोनी से "लग रहा है" मेरे लिए बेहतर है, लेकिन हो सकता है चलाने के दोनों अगर रूपांतरण कर रही है और किसी भी discrepencies जांच ?!

इसके अलावा हम बीएमपी पेज यूनिकोड वर्ण कि UTF-8 के रूप में एन्कोड और फिर varchar से बदल रहे थे क्षेत्रों NVARCHAR को पता लगाने के लिए बहुत बदसूरत नीचे कोड का इस्तेमाल किया, कि यूसीएस -16 में बदला जा सकता।

LIKE (N'%[' + CONVERT(NVARCHAR,(CHAR(192))) + CONVERT(NVARCHAR,(CHAR(193))) + CONVERT(NVARCHAR,(CHAR(194))) + CONVERT(NVARCHAR,(CHAR(195))) + CONVERT(NVARCHAR,(CHAR(196))) + CONVERT(NVARCHAR,(CHAR(197))) + CONVERT(NVARCHAR,(CHAR(198))) + CONVERT(NVARCHAR,(CHAR(199))) + CONVERT(NVARCHAR,(CHAR(200))) + CONVERT(NVARCHAR,(CHAR(201))) + CONVERT(NVARCHAR,(CHAR(202))) + CONVERT(NVARCHAR,(CHAR(203))) + CONVERT(NVARCHAR,(CHAR(204))) + CONVERT(NVARCHAR,(CHAR(205))) + CONVERT(NVARCHAR,(CHAR(206))) + CONVERT(NVARCHAR,(CHAR(207))) + CONVERT(NVARCHAR,(CHAR(208))) + CONVERT(NVARCHAR,(CHAR(209))) + CONVERT(NVARCHAR,(CHAR(210))) + CONVERT(NVARCHAR,(CHAR(211))) + CONVERT(NVARCHAR,(CHAR(212))) + CONVERT(NVARCHAR,(CHAR(213))) + CONVERT(NVARCHAR,(CHAR(214))) + CONVERT(NVARCHAR,(CHAR(215))) + CONVERT(NVARCHAR,(CHAR(216))) + CONVERT(NVARCHAR,(CHAR(217))) + CONVERT(NVARCHAR,(CHAR(218))) + CONVERT(NVARCHAR,(CHAR(219))) + CONVERT(NVARCHAR,(CHAR(220))) + CONVERT(NVARCHAR,(CHAR(221))) + CONVERT(NVARCHAR,(CHAR(222))) + CONVERT(NVARCHAR,(CHAR(223))) + CONVERT(NVARCHAR,(CHAR(224))) + CONVERT(NVARCHAR,(CHAR(225))) + CONVERT(NVARCHAR,(CHAR(226))) + CONVERT(NVARCHAR,(CHAR(227))) + CONVERT(NVARCHAR,(CHAR(228))) + CONVERT(NVARCHAR,(CHAR(229))) + CONVERT(NVARCHAR,(CHAR(230))) + CONVERT(NVARCHAR,(CHAR(231))) + CONVERT(NVARCHAR,(CHAR(232))) + CONVERT(NVARCHAR,(CHAR(233))) + CONVERT(NVARCHAR,(CHAR(234))) + CONVERT(NVARCHAR,(CHAR(235))) + CONVERT(NVARCHAR,(CHAR(236))) + CONVERT(NVARCHAR,(CHAR(237))) + CONVERT(NVARCHAR,(CHAR(238))) + CONVERT(NVARCHAR,(CHAR(239))) 
    + N'][' + CONVERT(NVARCHAR,(CHAR(128))) + CONVERT(NVARCHAR,(CHAR(129))) + CONVERT(NVARCHAR,(CHAR(130))) + CONVERT(NVARCHAR,(CHAR(131))) + CONVERT(NVARCHAR,(CHAR(132))) + CONVERT(NVARCHAR,(CHAR(133))) + CONVERT(NVARCHAR,(CHAR(134))) + CONVERT(NVARCHAR,(CHAR(135))) + CONVERT(NVARCHAR,(CHAR(136))) + CONVERT(NVARCHAR,(CHAR(137))) + CONVERT(NVARCHAR,(CHAR(138))) + CONVERT(NVARCHAR,(CHAR(139))) + CONVERT(NVARCHAR,(CHAR(140))) + CONVERT(NVARCHAR,(CHAR(141))) + CONVERT(NVARCHAR,(CHAR(142))) + CONVERT(NVARCHAR,(CHAR(143))) + CONVERT(NVARCHAR,(CHAR(144))) + CONVERT(NVARCHAR,(CHAR(145))) + CONVERT(NVARCHAR,(CHAR(146))) + CONVERT(NVARCHAR,(CHAR(147))) + CONVERT(NVARCHAR,(CHAR(148))) + CONVERT(NVARCHAR,(CHAR(149))) + CONVERT(NVARCHAR,(CHAR(150))) + CONVERT(NVARCHAR,(CHAR(151))) + CONVERT(NVARCHAR,(CHAR(152))) + CONVERT(NVARCHAR,(CHAR(153))) + CONVERT(NVARCHAR,(CHAR(154))) + CONVERT(NVARCHAR,(CHAR(155))) + CONVERT(NVARCHAR,(CHAR(156))) + CONVERT(NVARCHAR,(CHAR(157))) + CONVERT(NVARCHAR,(CHAR(158))) + CONVERT(NVARCHAR,(CHAR(159))) + CONVERT(NVARCHAR,(CHAR(160))) + CONVERT(NVARCHAR,(CHAR(161))) + CONVERT(NVARCHAR,(CHAR(162))) + CONVERT(NVARCHAR,(CHAR(163))) + CONVERT(NVARCHAR,(CHAR(164))) + CONVERT(NVARCHAR,(CHAR(165))) + CONVERT(NVARCHAR,(CHAR(166))) + CONVERT(NVARCHAR,(CHAR(167))) + CONVERT(NVARCHAR,(CHAR(168))) + CONVERT(NVARCHAR,(CHAR(169))) + CONVERT(NVARCHAR,(CHAR(170))) + CONVERT(NVARCHAR,(CHAR(171))) + CONVERT(NVARCHAR,(CHAR(172))) + CONVERT(NVARCHAR,(CHAR(173))) + CONVERT(NVARCHAR,(CHAR(174))) + CONVERT(NVARCHAR,(CHAR(175))) + CONVERT(NVARCHAR,(CHAR(176))) + CONVERT(NVARCHAR,(CHAR(177))) + CONVERT(NVARCHAR,(CHAR(178))) + CONVERT(NVARCHAR,(CHAR(179))) + CONVERT(NVARCHAR,(CHAR(180))) + CONVERT(NVARCHAR,(CHAR(181))) + CONVERT(NVARCHAR,(CHAR(182))) + CONVERT(NVARCHAR,(CHAR(183))) + CONVERT(NVARCHAR,(CHAR(184))) + CONVERT(NVARCHAR,(CHAR(185))) + CONVERT(NVARCHAR,(CHAR(186))) + CONVERT(NVARCHAR,(CHAR(187))) + CONVERT(NVARCHAR,(CHAR(188))) + CONVERT(NVARCHAR,(CHAR(189))) + CONVERT(NVARCHAR,(CHAR(190))) + CONVERT(NVARCHAR,(CHAR(191))) 
    + N']%') COLLATE Latin1_General_BIN 

ऊपर:

  • का पता लगाता है U + 0080 U + FFFF (U + 0080 के लिए U + 07FF करने के लिए एन्कोडिंग इनकोडिंग मल्टी-बाइट दृश्यों 110xxxxx 10xxxxxx, U + 0800 यू करने के लिए + FFFF के रूप में 1110xxxx 10xxxxxx 10xxxxxx)
  • यानी यह पता लगाता है हेक्स 0xEF 0xBF को हेक्स बाइट 0x80 द्वारा पीछा करने के लिए 0xC0 बाइट के रूप में एन्कोड किया गया है
  • पर ध्यान नहीं देता ASCII नियंत्रण वर्ण U + 0000 यू करने के लिए + 001F
  • पर ध्यान नहीं देता अक्षर हैं जो पहले से ही सही ढंग से इनकोड यूनिकोड> = यू +0100 (यानी यूटीएफ -8 नहीं)
  • यू + 0080 से यू + 00 एफएफ को यूनिकोड वर्णों को अनदेखा करता है अगर वे यूटीएफ -8 अनुक्रम का हिस्सा नहीं दिखते हैं उदा। "Coöperatief"।
  • के लिए एक्स = संभावित मिलान की वजह से वाई = 0xBF को 0x80 की तरह "% [XY]" का उपयोग नहीं करता मुद्दों
  • का उपयोग करता CONVERT (VARCHAR, CHAR (एक्स)) NCHAR के बजाय क्योंकि हम NCHAR हो रही के साथ समस्या नहीं थी गलत मान में परिवर्तित (कुछ मानों के लिए)। यह एक चुनौती होगा -
  • UTF U + FFFF से अधिक वर्ण (जो 0xFD को हेक्स 0xF0 की पहली बाइट है 4 से 6 बाइट दृश्यों)
संबंधित मुद्दे