myt给定一个由以下定义的空表
myt:([] id:`int$(); score:`int$())
Run Code Online (Sandbox Code Playgroud)
例如,向其中插入一条或多条记录很简单
`myt upsert `id`score!1 100
Run Code Online (Sandbox Code Playgroud)
但当涉及到定义一个插入给定表的函数时,这似乎是一个不同的技巧。
第一次尝试的版本可能是
upd:{[t] t upsert `id`score!42 314;}
upd[myt]
Run Code Online (Sandbox Code Playgroud)
显然它不会更新myt自身,只是更新它的本地副本版本。
设myt为全局变量,然后将在函数内访问该变量。
upd:{`myt upsert `id`score!42 314;}
upd[]
Run Code Online (Sandbox Code Playgroud)
它看起来是一个很好的解决方案,预计是否myt需要很多。在这种情况下,必须提供大量的upd功能副本,如下所示
upd0:{`myt0 upsert `id`score!42 314;}
upd1:{`myt1 upsert `id`score!42 314;}
upd2:{`myt2 upsert `id`score!42 314;}
...
Run Code Online (Sandbox Code Playgroud)
所以,全局变量的解决方案在这里并不是一个好的解决方案。
还可以通过myt在函数外部进行修改来解决问题,通过删除结尾返回修改后的结果;。
upd:{[t] t upsert `id`score!42 314} / return inserted valued
myt:upd[myt]
Run Code Online (Sandbox Code Playgroud)
有用!但在运行这段代码数百万次之后,它的运行速度越来越慢。因为这个解决方案抛弃了“就地”属性upsert,因此复制开销随着表大小的变大而增加。
也许这里有“按引用传递”解决方案的概念。或者也许 q 对于这个问题有自己的解决方案,但我还没有得到本质的想法。
myt正如cillianreilly回答的那样,在将其传递给函数时,在前面添加“`”符号将其声明为全局变量很简单。所以完美的解决办法就是直接。
upd:{[t] t upsert `id`score!42 314;}
upd[`myt] / it works
Run Code Online (Sandbox Code Playgroud)
小智 5
您的第一个版本应该达到您想要的效果。如果将表名作为符号传递,它将更新全局变量并返回表名。如果您传递表本身,它将返回更新后的表,您可以在分配中使用该表,就像您在可能的解决方案 2 中找到的那样。请注意,此操作不会更新实际表。
q){[t;x]t upsert x}[myt;`id`score!42 314]
id score
--------
42 314
q)count myt
0
q){[t;x]t upsert x}[`myt;`id`score!42 314]
`myt
q)count myt
1
Run Code Online (Sandbox Code Playgroud)
对于可能的解决方案 1,为什么需要数百个 myt 表?无论如何,不需要将表名称硬编码到函数中。您可以将表名称作为符号传递,如上所示,这将为您更新全局。在他们的 github 上给出的官方 kx kdb tick 示例正是针对这种情况使用insert,但实际上很多开发人员使用upsert。https://github.com/KxSystems/kdb-tick/blob/master/tick/rq#L6
希望这可以帮助。