You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure资源管理器精简版Kusto如何模拟DUAL表实现常量查询?

问题

在Kusto中,是否可以无需源表直接选择常量值?例如类似Oracle中使用DUAL表(或其他多数查询语言中无FROM子句的SELECT语句)的方式?

示例:() | project colA = 'hello', colB = 'world'……但该语句无法运行。

注:我需要的是适用于Azure资源管理器中Kusto精简版的解决方案。

背景

注:这是一个XY问题,上述问题的解决方案可作为我实际问题的变通方案……以下是我要解决的真实问题。

我有一个查询用于判断给定CIDR是否与Azure中现有虚拟网络(VNet)重叠,以便在分配新CIDR前进行测试,或查找给定IP所属的VNet:

resources 
| where type =~ 'Microsoft.Network/virtualNetworks'
| project id, subscriptionId, resourceGroup, name, addressPrefixes = properties['addressSpace'].['addressPrefixes']
| mv-expand addressPrefixes
| extend cidrSplit = array_concat(split(split(addressPrefixes, '/')[0],'.'), split(split(addressPrefixes, '/')[1],'x'))
| extend firstIpVal = toint(cidrSplit[0]) * 16777216 + toint(cidrSplit[1]) * 65536 + toint(cidrSplit[2]) * 256 + toint(cidrSplit[3])
| extend lastIpVal = firstIpVal + pow(2,32-cidrSplit[4])-1
| project-away cidrSplit
// 10.11.12.13/28 defined in both rows below:
| where firstIpVal <= 10 * 16777216 + 11 * 65536 + 12 * 256 + 13 + pow(2,32-28)-1
  and lastIpVal >= 10 * 16777216 + 11 * 65536 + 12 * 256 + 13
| project subscriptionId, resourceGroup, name, addressPrefixes, firstIpVal, lastIpVal
| order by firstIpVal, lastIpVal

但上述查询难以针对不同CIDR进行更新,也不方便阅读者识别当前查询的CIDR。

我更希望采用如下形式,但Azure资源管理器不支持变量定义:

let newCidr = "10.11.12.13/28";

let newCidrSplit = array_concat(split(split(newCidr, '/')[0],'.'), split(split(newCidr, '/')[1],'x'))

let newCidrFirst = toint(newCidrSplit[0]) * 16777216 + toint(newCidrSplit[1]) * 65536 + toint(newCidrSplit[2]) * 256 + toint(newCidrSplit[3]);

let newCidrLast = newCidrFirst + pow(2,32-newCidrSplit[4])-1;

resources 
| where type =~ 'Microsoft.Network/virtualNetworks'
| project id, subscriptionId, resourceGroup, name, addressPrefixes = properties['addressSpace'].['addressPrefixes']
| mv-expand addressPrefixes
| extend cidrSplit = array_concat(split(split(addressPrefixes, '/')[0],'.'), split(split(addressPrefixes, '/')[1],'x'))
| extend firstIpVal = toint(cidrSplit[0]) * 16777216 + toint(cidrSplit[1]) * 65536 + toint(cidrSplit[2]) * 256 + toint(cidrSplit[3])
| extend lastIpVal = firstIpVal + pow(2,32-cidrSplit[4])-1
| project-away cidrSplit
| where firstIpVal <= newCidrLast and lastIpVal >= newCidrFirst
| project subscriptionId, resourceGroup, name, addressPrefixes, firstIpVal, lastIpVal
| order by firstIpVal, lastIpVal

因此我希望找到无需定义变量即可实现“变量”功能的方法;例如若存在dual表(确保始终仅有一行的表),我可以采用如下方式(虽略显繁琐,但便于修改查询的IP,且易于阅读):

dual // i.e. a table with one row, where we don't really care about the row's contents
| project testCidr = "10.11.12.13/28" // set the "variable" here; one place in an easy to read format, near the top so it's easy to spot
| extend testCidrSplit = array_concat(split(split(testCidr, '/')[0],'.'), split(split(testCidr, '/')[1],'x'))
| extend testCidrFirstIp = toint(testCidrSplit[0]) * 16777216 + toint(testCidrSplit[1]) * 65536 + toint(testCidrSplit[2]) * 256 + toint(testCidrSplit[3])
| extend testCidrLastIp = testCidrFirstIp + pow(2,32-testCidrSplit[4])-1
| extend joinhack = 1
| join kind = inner
(
    resources 
    | where type =~ 'Microsoft.Network/virtualNetworks'
    | project id, subscriptionId, resourceGroup, name, addressPrefixes = properties['addressSpace'].['addressPrefixes'], joinhack = 1
    | mv-expand addressPrefixes
    | extend cidrSplit = array_concat(split(split(addressPrefixes, '/')[0],'.'), split(split(addressPrefixes, '/')[1],'x'))
    | extend firstIpVal = toint(cidrSplit[0]) * 16777216 + toint(cidrSplit[1]) * 65536 + toint(cidrSplit[2]) * 256 + toint(cidrSplit[3])
    | extend lastIpVal = firstIpVal + pow(2,32-cidrSplit[4])-1
    | project-away cidrSplit
)
on joinhack
| where firstIpVal <= testCidrLastIp and lastIpVal >= testCidrfirstIp
| project subscriptionId, resourceGroup, name, addressPrefixes, firstIpVal, lastIpVal
| order by firstIpVal, lastIpVal

注:我当然可以用查询订阅的方式替代上述dual(假设查询时至少存在一个订阅),再用limit获取一行……但这种方式过于繁琐,我希望从语言层面找到解决方案。

resourcecontainers
| where type == "microsoft.resources/subscriptions"
| limit 1
| project colA = 'hello', colB = 'world'

解决方案

直接获取常量值的方法

在Kusto(包括Azure资源管理器中的精简版)中,可使用print语句直接生成包含常量值的单行结果,无需依赖任何源表,效果等同于Oracle的DUAL表:

print colA = 'hello', colB = 'world'

针对CIDR重叠检测的优化查询

利用print语句替代设想的dual表,可实现集中管理测试CIDR的需求,同时兼容Azure资源管理器的Kusto精简版:

// 只需修改此处的testCidr值即可
print testCidr = "10.11.12.13/28"
| extend testCidrParts = split(testCidr, '/')
| extend testIpParts = split(testCidrParts[0], '.')
| extend testPrefixLen = toint(testCidrParts[1])
| extend testCidrFirstIp = toint(testIpParts[0]) * 16777216 + toint(testIpParts[1]) * 65536 + toint(testIpParts[2]) * 256 + toint(testIpParts[3])
| extend testCidrLastIp = testCidrFirstIp + pow(2, 32 - testPrefixLen) - 1
| extend joinhack = 1
| join kind=inner (
    resources 
    | where type =~ 'Microsoft.Network/virtualNetworks'
    | project subscriptionId, resourceGroup, name, addressPrefixes = properties['addressSpace'].['addressPrefixes']
    | mv-expand addressPrefixes
    | extend cidrParts = split(addressPrefixes, '/')
    | extend ipParts = split(cidrParts[0], '.')
    | extend prefixLen = toint(cidrParts[1])
    | extend firstIpVal = toint(ipParts[0]) * 16777216 + toint(ipParts[1]) * 65536 + toint(ipParts[2]) * 256 + toint(ipParts[3])
    | extend lastIpVal = firstIpVal + pow(2, 32 - prefixLen) - 1
    | project-away cidrParts, ipParts, prefixLen
    | extend joinhack = 1
) on joinhack
| where firstIpVal <= testCidrLastIp and lastIpVal >= testCidrFirstIp
| project subscriptionId, resourceGroup, name, addressPrefixes, firstIpVal, lastIpVal
| order by firstIpVal, lastIpVal

该查询做了以下优化:

  • 用print直接定义测试CIDR,无需依赖其他表
  • 拆分CIDR的逻辑更清晰,避免嵌套split导致的可读性问题
  • 明确转换前缀长度为整数类型,避免潜在的类型错误
  • 移除了不必要的字段投影,简化查询结构

内容的提问来源于stack exchange,提问作者JohnLBevan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 07:17:01