KDB+/Q:如何向含非一致性列表列的表执行upsert?
这个问题的核心是kdb+的upsert操作要求源表和目标表的对应列元素类型完全兼容。你的表x的datum列元素是tuple(比如(FOO;1084300i;1.5f)),而表y的datum列元素是**list**(比如993150 2543823 15100i)——哪怕你用enlist each把y的datum转成列表的列表,元素类型还是和x的tuple不匹配,所以触发'type`错误。
下面提供两种可行的解决方案,你可以根据后续数据的存储需求选择:
方案1:将y的datum列元素转换为tuple(匹配x的现有类型)
如果希望保留x中datum列的tuple格式,只需要把y的每个列表元素转成tuple即可:
// 将y的datum列的每个列表转换为tuple y[`datum]: (;)'y[`datum] // 现在执行upsert就不会报错了 x upsert y
解释:(;)'是kdb+里把列表转为tuple的惯用写法——它会将列表的每个元素拆分为tuple的成员。比如(;)'(993150 2543823 15100i)会生成(993150i;2543823i;15100i),和x中datum列的元素类型完全一致。
方案2:将x的datum列元素转换为list(匹配y的现有类型)
如果后续更倾向于用列表存储datum数据,可以先转换x的列类型,再执行upsert:
// 将x的datum列的每个tuple转换为list x[`datum]: (),/'x[`datum] // 直接upsert y即可 x upsert y
解释:(),/'会把每个tuple元素转为列表——比如(),/(FOO;1084300i;1.5f)会生成``FOO 1084300 1.5``,和y中datum列的列表类型匹配。转换完成后,x和y的datum`列元素类型统一为list,upsert操作就能正常执行。
验证类型匹配
执行转换后,可以用meta和type命令确认类型是否匹配:
// 查看转换后的列类型 meta x meta y // 查看列元素的类型(应该一致) type first x[`datum] type first y[`datum]
如果两者的类型输出相同(比如方案1中都是10h即tuple类型,方案2中都是0h即通用列表类型),就说明类型兼容,可以安全执行upsert了。
内容的提问来源于stack exchange,提问作者James

