将表插入到内存中现有的展开表导致错误:`type (Q/KDB+)

Posted

技术标签:

【中文标题】将表插入到内存中现有的展开表导致错误:`type (Q/KDB+)【英文标题】:Upsert a table to existing splayed table in memory leading to error: `type (Q/KDB+) 【发布时间】:2022-01-23 18:11:49 【问题描述】:

我正在使用新的 Q 语言和 KDB+ 数据库。我无法将另一个表插入到内存中现有的张开表中。

我有一个名为temp 的表格,然后将其保存为`:temp 中的张开表格

col1 col2 col3
--------------
a    0    1   
b    1.5  2.5 
c    1.1  2.2 
d    0.99 0.98

张开表的目录结构:

temp
|  .d
|  col1
|  col2
|  col3
|  sym

假设我有另一张桌子new

new: ([] col1:`e`f`g; col2:1.0 1.1 1.1; col3: 2.25 2.20 2.70)

我的问题是:我们如何将new 插入`:temp

我已经阅读了https://code.kx.com/q/ref/upsert/,但是给出的示例只更新了一条记录(而不是整个表)。我试过`:temp upsert (`sym?new) 导致type 错误。

编辑(我运行的所有命令)

q)temp: ([] col1:`a`b`c`d; col2:0.0 1.5 1.1 0.99; col3: 1.0 2.5 2.2 0.98)
q)`:temp/ set .Q.en[`:.;temp]
`:temp/
q)new: ([] col1:`e`f`g; col2:1.0 1.1 1.1; col3: 2.25 2.20 2.70)
q)`:temp upsert new
'type
  [0]  `:temp upsert new
              ^

【问题讨论】:

【参考方案1】:

如果您已经将temp 保存为张开的表格,您可以使用以下命令将new 插入到其中:

q) new:([]col1:`e`f`g;col2:1.0 1.1 1.1;col3:2.25 2.20 2.70)
q) `:temp upsert new
`:temp
q) get`:temp
col1 col2 col3
--------------
a    0    1
b    1.5  2.5
c    1.1  2.2
d    0.99 0.98
e    1    2.25
f    1.1  2.2
g    1.1  2.7

然后您就可以看到所需的结果。如果您离开 q 会话并将其加载到新会话中,您将看到它已被保存。

【讨论】:

嗯,我仍然收到 `:type 错误。当我将temp 保存为张开的表格时,我怀疑代码不正确。这是保存张开的桌子的正确方法吗? temp:.Q.en[`:temp;temp] 后跟`:temp/ set temp【参考方案2】:

您需要使用enum extend“手动”枚举任何符号类型列

q)`:temp/ set([]col1:`:sym?`a`b;col2:1 2f;col3:10 20f);
q)`:temp upsert([]col1:`:sym?`e`f`g;col2:1.0 1.1 1.1;col3:2.25 2.20 2.70);
q)get`:sym
`a`b`e`f`g
q)get`:temp
col1 col2 col3
--------------
a    1    10
b    2    20
e    1    2.25
f    1.1  2.2
g    1.1  2.7

或使用.Q.en等辅助函数之一

q)`:temp/ set .Q.en[`:.;([]col1:`A`B;col2:1 2f;col3:10 20f)];
q)`:temp upsert .Q.en[`:.;([]col1:`e`f`g;col2:1.0 1.1 1.1;col3:2.25 2.20 2.70)];
q)get`:sym
`A`B`e`f`g
q)get`:temp
col1 col2 col3
--------------
A    1    10
B    2    20
e    1    2.25
f    1.1  2.2
g    1.1  2.7

在更新插入持久文件时还有其他需要注意的事项,例如

任何应用了属性的文件都将通过 upsert 操作删除这些属性(排序除外,如果列表保持升序,则会保留该属性) 如果任何带有属性的文件被压缩,除非您采取其他措施以确保它们不会被压缩,否则它们将在未压缩的情况下被重写
q)(`:groupedVector;17;2;6)set `g#1 2 3;
q)-21!`:groupedVector
compressedLength  | 113
uncompressedLength| 240
algorithm         | 2i
logicalBlockSize  | 17i
zipLevel          | 6i
q)attr get`:groupedVector
`g
q)
q)`:groupedVector upsert 4 5;
q)get `:groupedVector
1 2 3 4 5
q)-21!`:groupedVector       // compression lost
q)attr get`:groupedVector   // attribute lost
`
由开发人员确保磁盘上的列文件与要附加的数据之间的兼容性 - 否则您可能会以不同长度的列文件结束,例如
q)`:temp/ set([]char:"ab";long:1 2);
q)`:temp upsert ("c";3);
q)`:temp upsert ("d";4i);
'type
  [0]  `:temp upsert ("d";4i);
              ^
q)get`:temp/char
"abcd"
q)get`:temp/long
1 2 3

【讨论】:

有没有办法在不“手动输入”表定义的情况下进行更新插入?假设我有一个 100 行的张开表,我想更新一百万条记录,手动输入类似 ([]col1:`:sym?`e`f`g;col2:1.0 1.1 1.1;col3:2.25 2.20 2.70) 的内容是不可能的,对吧? 我期待像`:temp upsert (colnames ! entries) 这样的东西,在上面的例子中colnames`col1`col2`col3。我希望你明白我的意思 @Meinung 命令将与表名相同,例如`:temp/ set .Q.en[`:.;temp],我也注意到您保存枚举的方式意味着您将 sym 文件保存在与列相同的位置,确保它与表目录相同,即使用上面的示例,不要使用`:temp/ set .Q.en[`:temp;temp] @CameronMcKee 谢谢你的建议。但我仍然无法将新记录更新到`:temp。我已经尝试了@Leah Carragher 建议的`:temp/ upsert new,但我仍然收到`type 错误。如果我问的事情太琐碎,我深表歉意 哦,我终于可以在不通过`:temp upsert .Q.en[`:.] new 得到`type 错误的情况下进行更新插入了!!非常感谢大家的帮助

以上是关于将表插入到内存中现有的展开表导致错误:`type (Q/KDB+)的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery:将表插入到具有分片表的现有 Google 分析中

将表插入到我使用 sqlite 在 python 中创建的数据库中时出错

新手试图从 excel 将数据插入 SQL Server 2008

缓存表 内存表(将表keep到内存)

关于字段超长导致的插入错误的提示信息(value too long for type character varying)

如何将具有自定义枚举类型的数据从 csv 插入现有的 PostgreSQL 表