2

我使用 OCS Inventory 来清点我们的 PC。它几乎可以正常工作,但是……但是这些 PC 中有 99% 可以在 Windows(R):XP 和 7 下工作。WMI 信息没有任何标准。

例如,OCS Agent(目标 PC 上的常驻程序,它收集数据并将其发送到 OCS Server)可能会得到响应为“ Realtek PCIe GBE Family Controller (1 Gb/s) ”(纯英文,编码不是问题),或“ ¨£¡¨â®¥ á¥â¥¢®¥ ¯®¤ª«î票¥ Intel(R) 82566DM-2 (100 Mb/s) ”(不正确,俄语,CP1251),或“ Realtek RTL8169/8110 系列千兆以太网 NIC - Ìèíèïîðò ïëàíèðîâùèêà ïàêåòîâ (100 Mb/s) ”(不正确,俄语,CP866)。或“ VIA Rhine III 快速以太网适配器 - Минипорт планировщика пакетов (100 Mb/s) ”(正确,俄语,UTF8 或其他 Unicode)

我无法让 Windows 仅以一种编码返回这些结果:这似乎取决于驱动程序制造商的想法:驱动程序的 .INF 文件中使用了哪种编码,WMI 将返回该编码。

大多数情况下这不是问题,但我的老板非常不喜欢在关于我们 IT 基础设施状态的季度报告中看到“象形文字”。他们似乎是对的。

有什么方法可以即时将单个字段从一种编码重新编码为另一种?由于内容混合,我不会重新编码整个列。我可以大致确定使用了哪种编码,但我不知道如何仅使用 MySQL 的 SQL 语言重新编码以生成正确的报告。

请问有什么工作建议吗?

4

1 回答 1

0

看起来唯一的方法是编写存储过程。我做到了。左列(castbin)为处理前的文本,右列( )为处理converted后的相同文本

在此处输入图像描述

来看看代码

...
#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 0xEx 替换 0xCx 0xAx”命名。这是此函数的非常不理想但有效的代码(取自 MySQL Studio)

See corrected text of the function below in update section

首先我们查看字符串是否可转换,然后进行两次转换 - for0xC20xC3前缀,因为这些前缀意味着不同的编码错误。

更新:彻底的测试发现了一些错误。

在查询的某处,我使用group_concat运算符将​​同一台 PC 的多个属性的值合并为一个长字符串,其中 "\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,(160+@i)),char(0xd3,(224+@i)));
        set @i:=@i+1;
    end while;
    set @i:=1;
    while @i<4 do
        set @s:=replace(@s,char(0xc0+@i),'');
        set @s:=replace(@s,char(0xd0+@i),'');
        set @i:=@i+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,(176+@i)),char(0xd3,(224+@i)));
        set @i:=@i+1;
    end while;
    set @i:=1;
    while @i<4 do
        set @s:=replace(@s,char(0xc0+@i),'');
        set @s:=replace(@s,char(0xd0+@i),'');
        set @i:=@i+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))
于 2015-12-29T01:48:05.143 回答