[comment]: # ({36f796e5-dc992d4f})
# 12 利用ODBC SQL查询执行自动发现

[comment]: # ({/36f796e5-dc992d4f})

[comment]: # ({d13fdb00-dcf4796a})
#### 概述

这种类型的低级[发现](/manual/discovery/low_level_discovery)是使用 SQL 查询完成的，其结果会自动转换为适用于低级发现的 JSON 对象。

[comment]: # ({/d13fdb00-dcf4796a})

[comment]: # ({7d92c807-c1ef39b4})
#### 监控项键值

SQL 查询使用“Database monitor”监控项类型执行。
因此，为了获得可正常工作的“Database monitor”发现规则，[ODBC monitoring](/manual/config/items/itemtypes/odbc_checks) 页面中的大多数说明同样适用。

在“Database monitor”发现规则中可使用两个监控项键值：

-   **db.odbc.discovery**\[<唯一简短描述>,<dsn>,<connection string>\] - 此监控项会将 SQL 查询结果转换为 JSON 数组，把查询结果中的列名转换为低级别发现宏名称，并与发现的字段值配对。
这些宏可用于创建监控项、触发器等原型。
另请参见：[Using db.odbc.discovery](#using-dbodbcdiscovery)。

-   **db.odbc.get**\[<唯一简短描述>,<dsn>,<connection string>\] - 此监控项会将 SQL 查询结果转换为 JSON 数组，保留查询结果中的原始列名作为 JSON 中的字段名，并与发现的值配对。
与 `db.odbc.discovery[]` 相比，此监控项不会在返回的 JSON 中创建低级别发现宏，因此无需检查列名是否可以作为有效的宏名称。
可根据需要使用 [custom LLD macro](/manual/discovery/low_level_discovery#custom-macros) 功能，并通过 JSONPath 指向返回 JSON 中发现的值，将低级别发现宏定义为附加步骤。
另请参见：[Using db.odbc.get](#using-dbodbcget)。

[comment]: # ({/7d92c807-c1ef39b4})

[comment]: # ({04774767-0f9c9410})
#### 使用 db.odbc.discovery

以下示例演示了如何基于对 Zabbix 数据库的 ODBC 查询，使用 Zabbix proxy 的低级别发现将 SQL 查询转换为 JSON。
这对于自动创建用于监控哪些 proxy 处于存活状态的 "zabbix\[proxy,<name>,lastaccess\]" [内部监控项](/manual/config/items/itemtypes/internal) 很有用。

首先从发现规则配置开始：

![lld\_rule\_odbc.png](../../../../../assets/en/manual/discovery/low_level_discovery/lld_rule_odbc.png)

所有必填输入字段都用红色星号标记。

这里，使用了以下针对 Zabbix 数据库的直接查询来选择所有 Zabbix proxy，以及它们正在监控的主机数量。
例如，主机数量可用于过滤掉空的 proxy：

```sqlmysql
mysql> SELECT h1.host, COUNT(h2.host) AS count FROM hosts h1 LEFT JOIN hosts h2 ON h1.hostid = h2.proxyid WHERE h1.status IN (5, 6) GROUP BY h1.host;
+---------+-------+
| host    | count |
+---------+-------+
| Japan 1 |     5 |
| Japan 2 |    12 |
| Latvia  |     3 |
+---------+-------+
3 rows in set (0.01 sec)
```

通过 "db.odbc.discovery\[,{$DSN}\]" 监控项的内部工作机制，此查询结果会被自动转换为以下 JSON：

```json
[
    {
        "{#HOST}": "Japan 1",
        "{#COUNT}": "5"
    },
    {
        "{#HOST}": "Japan 2",
        "{#COUNT}": "12"
    },
    {
        "{#HOST}": "Latvia",
        "{#COUNT}": "3"
    }
]
```

可以看到，列名会变成宏名称，而选中的行会成为这些宏的值。

::: noteclassic
如果列名将如何转换为宏名称并不明显，建议像上面的示例那样使用列别名，例如 "COUNT(h2.host) AS count"。

如果某个列名无法转换为有效的宏名称，则发现规则会变为不支持状态，错误消息中会详细说明有问题的列编号。
如果需要更多帮助，可在 Zabbix 服务器日志文件中通过 DebugLevel=4 查看获取到的列名：

    $ grep db.odbc.discovery /tmp/zabbix_server.log
     ...
     23876:20150114:153410.856 In db_odbc_discovery() query:'SELECT h1.host, COUNT(h2.host) FROM hosts h1 LEFT JOIN hosts h2 ON h1.hostid = h2.proxy_hostid WHERE h1.status IN (5, 6) GROUP BY h1.host;'
     23876:20150114:153410.860 db_odbc_discovery() column[1]:'host'
     23876:20150114:153410.860 db_odbc_discovery() column[2]:'COUNT(h2.host)'
     23876:20150114:153410.860 End of db_odbc_discovery():NOTSUPPORTED
     23876:20150114:153410.860 Item [Zabbix server:db.odbc.discovery[proxies,{$DSN}]] error: Cannot convert column #2 name to macro.

:::

现在我们已经了解了 SQL 查询如何被转换为 JSON 对象，就可以在监控项原型中使用 {\#HOST} 宏：

![item\_prototype\_odbc.png](../../../../../assets/en/manual/discovery/low_level_discovery/item_prototype_odbc.png)

一旦执行发现，就会为每个 proxy 创建一个监控项：

![discovered\_items\_odbc1.png](../../../../../assets/en/manual/discovery/low_level_discovery/discovered_items_odbc1.png)

[comment]: # ({/04774767-0f9c9410})

[comment]: # ({76d189b2-43f8549f})
#### 使用 db.odbc.get

使用 `db.odbc.get[,{$DSN}]` 和以下 SQL 示例：

```sqlmysql
mysql> SELECT h1.host, COUNT(h2.host) AS count FROM hosts h1 LEFT JOIN hosts h2 ON h1.hostid = h2.proxyid WHERE h1.status IN (5, 6) GROUP BY h1.host;
+---------+-------+
| host    | count |
+---------+-------+
| Japan 1 |     5 |
| Japan 2 |    12 |
| Latvia  |     3 |
+---------+-------+
3 rows in set (0.01 sec)
```

将返回以下 JSON：

```json
[
    {
        "host": "Japan 1",
        "count": "5"
    },
    {
        "host": "Japan 2",
        "count": "12"
    },
    {
        "host": "Latvia",
        "count": "3"
    }
]
```

如您所见，其中没有低级别发现宏。  
不过，可以在发现规则的 [LLD macros](/manual/discovery/low_level_discovery#custom-macros) 选项卡中使用 JSONPath 创建自定义低级别发现宏，例如：

```default
{#HOST} → $.host
```

现在，这个 {\#HOST} 宏可在监控项原型中使用：

![item\_prototype\_odbc.png](../../../../../assets/en/manual/discovery/low_level_discovery/item_prototype_odbc.png)

[comment]: # ({/76d189b2-43f8549f})
