1

我正在尝试在 Spiceworks 中编写使用 SQLite 查询的自定义报告。该报告将获取硬盘序列号,不幸的是,这些序列号以几种不同的方式存储,具体取决于机器上的 Windows 和 WMI 版本。

三个常见示例(足以解决实际问题)如下:

实际序列号: 5VG95AZF
带前导空格的 2020202057202d44585730354341543934383433
十六进制字符串:带前导零的十六进制字符串: 3030303030303030313131343330423137454342

这两个十六进制字符串更加复杂,因为即使将它们转换为 ASCII 表示,每对数字实际上都是倒数的。这是一个例子:

3030303030303030313131343330423137454342评估为00000000111430B17ECB

但是,该硬盘驱动器上的实际序列号是1141031BE7BC,没有前导零并且交换了字节。根据我在本网站上阅读的其他问题和答案,这与数据的“字节顺序”有关。

到目前为止,我的临时查询看起来像这样(缩短到仅相关部分):

SELECT  pd.model as HDModel,
  CASE
     WHEN pd.serial like "30303030%" THEN
         cast(('X''' || pd.serial || '''') as TEXT)
     WHEN pd.serial like "202020%" THEN
         LTRIM(X'2020202057202d44585730354341543934383433')
  ELSE
     pd.serial
  END  as HDSerial

该查询的结果是这样的:

HDModel             HDSerial
-----------------   -------------------------------------------
Normal Serial       5VG95AZF
202020% test case   W -DXW05CAT94843
303030% test case   X'3030303030303030313131343330423137454342'

这表明当给定一个完全文字数字(202020% 线)时,X'....'符号样式确实转换为正确(但向后)的结果。W -DXW05CAT94843但是,我需要找到一种方法来对列中的实际数据执行相同的操作,但pd.serial我找不到方法。

我最初的想法是,如果我可以构建符号的字符串表示X'...',那么也许cast()会评估它。但正如您所看到的,这最终只是吐出X'3030303030303030313131343330423137454342'而不是预期的00000000111430B17ECB. 这意味着串联工作正常,但我找不到与手动测试用例一样将其评估为十六进制的方法。

我整个早上都在谷歌搜索,看看是否缺少一些语法,但我最接近的是使用||运算符的连接。

编辑: 最终我只想能够在我的查询中有一个简单的 case 语句,如下所示:

SELECT  pd.model as HDModel,
  CASE
     WHEN pd.serial like "30303030%" THEN
         LTRIM(X'pd.serial')
     WHEN pd.serial like "202020%" THEN
         LTRIM(X'pd.serial')
  ELSE
     pd.serial
  END  as HDSerial

但是因为 pd.serial 被单引号括起来,所以它被当作文字字符串而不是作为该列中包含的数据。我的希望是/是我需要指定一个字符或运算符,比如X'$pd.serial'或其他东西。

结束编辑

如果我能克服这第一个障碍,我的下一个任务将是尝试删除前导零(LTRIM 吃前导空格的方式)并反转字节,但老实说,即使那部分不是,我也会满足。这是不可能的,因为在 Excel 中对该报告进行后处理并不难。

如果有人能指出我正确的方向,我将不胜感激!如果我使用 PHP 或其他东西来执行此处理,显然会容易得多,但是因为我试图让它成为 Spiceworks 中的嵌入式报告,所以我必须在单个 SQLite 查询中完成所有这些操作。

4

1 回答 1

0

X'...' 是 sqlite 中的二进制表示。如果值是字符串,则可以直接使用它们。

这应该是一个开始:

sqlite> select X'3030303030303030313131343330423137454342';
00000000111430B17ECB
sqlite> select ltrim(X'3030303030303030313131343330423137454342','0');
111430B17ECB

我希望这能让你走上正确的道路。

于 2012-04-18T16:56:58.390 回答