2015-12-28 6 views
1

Я использую инвентарь OCS для инвентаризации наших ПК. Он работает почти отлично, но ... но 99% этих компьютеров работают под Windows (R): XP и Seven. И нет никакого стандарта для информации WMI.MySQL: сочетание кодировки в том же столбце

Например, OCS Агент (резидентной программы на целевом компьютере, который собирает данные и отправляет их на OCS сервер) может получить ответ как «Realtek PCIe GBE Family Controller (1 Гбит/с)» (чистый английский, кодирование не является проблемой) или как «¨ £ ¨« á á ¥ ¥ ¢ ® ¥ ¯® ¯ á ¥ ¥ ¥ ¥ Intel (R) 82566DM-2 (100 Мбит/с) "(неверно , Русский, CP1251) или как «Realtek RTL8169/8110 Семейный сетевой адаптер Gigabit Ethernet - 100 Мбит/с» (неверно, русский, CP866). Или "VIA Rhine III Fast Ethernet Adapter - Минипорт планировщика пакетов (100 Мб/с)" (правильный, русский, UTF8 или другой Unicode)

У меня нет никакого способа, чтобы заставить Windows вернуть эти результаты только в одной кодировке: кажется, все зависит от производителей драйверов: какая кодировка использовалась в файле .INF драйвера, эта кодировка будет возвращена WMI.

В основном это не проблема, но мои боссы очень не любят видеть «иероглифы» в квартальных отчетах о состоянии нашей ИТ-инфраструктуры. И они кажутся правильными.

Есть ли способ перекодировать отдельные поля из одной кодировки в другую на лету? Я не буду перекодировать весь столбец из-за смешанного содержимого. Я могу грубо определить, какая кодировка была использована, но я не знаю, как перекодировать , используя только SQL-язык MySQL для получения правильных отчетов.

Любые рабочие предложения, пожалуйста?

ответ

0

Похоже, что единственный способ - записать хранимую процедуру. Я сделал это. Левая колонка (castbin) текст перед обработкой, правая (converted) тот же текст после обработки

enter image description here

Пусть увидеть код

... 
#above and below are regular MySQL statements 
@castbin:=cast(networks.description as char character set binary) as castbin, 
@convv:=convert(repcxaxex(@castbin) using cp866) as converted 
... 

@castbin переменная используется только для осветления и читаемости , Вся работа выполнена функцией repCxAxEx, названной в честь «заменить 0xCx 0xAx на 0xCx 0xEx». Вот очень inoptimal но рабочий код этой функции (взято из MySQL Studio)

See corrected text of the function below in update section 

Сначала мы ищем, если строка конвертируемая, а затем делает два преобразования - для 0xC2 и 0xC3 префиксов, поскольку эти префиксы означают различные ошибки кодирования ,

ОБНОВЛЕНИЕ: Тщательное тестирование выявило некоторые ошибки.

Внутри запроса я использую оператор group_concat для объединения значений нескольких свойств одного и того же ПК в одну длинную строку с разделителем «\ n». В таких случаях преобразование может не работать.

-- -------------------------------------------------------------------------------- 
-- Routine DDL 
-- Note: comments before and after the routine body will not be stored by the server 
-- -------------------------------------------------------------------------------- 
DELIMITER $$ 

CREATE DEFINER=`root`@`%` FUNCTION `repcxaxex`(s2c text charset binary) RETURNS blob 
begin 
/*исправляем проблемы с кодировками*/ 
    set @i:=0; 
    set @s:=s2c; 
    set @altered:='0'; 
    if ((left(@s,1)=char(0xc2)) or instr(@s,char(32,0xc2)) or instr(@s,char(0x0a,0xc2))) then 
    while @i<16 do 
     set @s:=replace(@s,char(0xc3,([email protected])),char(0xd3,([email protected]))); 
     set @i:[email protected]+1; 
    end while; 
    set @i:=1; 
    while @i<4 do 
     set @s:=replace(@s,char([email protected]),''); 
     set @s:=replace(@s,char([email protected]),''); 
     set @i:[email protected]+1; 
    end while; 
    set @altered:='1'; 
    end if; 
    set @i:=0; 
    if ((left(@s,1)=char(0xc3)) or instr(@s,char(32,0xc3)) or instr(@s,char(0x0a,0xc3))) then 
    while @i<16 do 
     set @s:=replace(@s,char(0xc3,([email protected])),char(0xd3,([email protected]))); 
     set @i:[email protected]+1; 
    end while; 
    set @i:=1; 
    while @i<4 do 
     set @s:=replace(@s,char([email protected]),''); 
     set @s:=replace(@s,char([email protected]),''); 
     set @i:[email protected]+1; 
    end while; 
    set @altered:='2'; 
    end if; 
/*Добавляем 0 или 1 в начало строки, чтобы показать, конвертировали ее или нет 
выводить надо будет, начиная со второго символа*/ 
    set @s=concat(@altered,@s); 
    return @s; 
end 

При выходе функция добавляет одну цифру в начало возвращаемой строки.Сама цифра определяется переменной @altered, и ее код является самоочевидным.

Более корректная форма вызова является:

If (left(repcxaxex(string-to-convert),1)='0',string-to-convert,mid(convert(repcxaxex(string-to-convert) using cp866),2))