数据回写填报太头疼?方案请收好! 中介绍了回写报表常见场景的配置方案,但是啊,咱也经常有这些疑问,为啥,都提示保存成功了,为啥数据数据没入库?怎么这条数据就是删不掉啊?别急,今天就给大家奉上下面几个场景回写异常排查指南,让大家数据安全落库~
- 增删改不成功
- 输入一条数据,保存后变两条
- 允许插入/删除行设置无效
- 普通用户无法编辑单元格
- 删错数据行
- 主键自增不生效
开始讲各种场景之前,先快速了解三个重点,这是能让我们回写报表顺顺利利的大前提:
1、回写规则中的所有单元格的两个扩展方向的父子关系都是一个链表而不是一棵树。
2、如果是交叉报表,删除整行或整列时,对应的列或者行不可以有多个主键。
3、字段不能设置排序,如需排序建议在数据集中处理。
1、增删改不成功
有没有遇到过快乐点击保存按钮,提示保存成功,一查,但是报表/数据库那里并没有我刚修改的数据。不用emo,让我们来一步步排查,数据到底去哪了~
首先,我们回写的原理是,前端进行增删改数据,通过回写规则生成SQL,把对应SQL送到数据库执行,数据库执行完之后再返回到smartbi,也就是执行成功会提示保存成功,失败就会弹出报错的窗口。
1.1 数据库并未执行SQL
既然是数据库执行后返回的,我们大胆点,是不是可能数据库没执行呢?是的,没错,是有可能的,比如需要把 A 表数据回写到 B 表中,只拖了 A 表字段,回写规则配置 B 表,报表层面并没有手动修改单元格数据,这个时候数据库是没执行的。
还记得大明湖畔的回写规则吗,开头链接的文章也提到了,这有个配置项,是【回写修改内容】和【回写所有内容】。因为此时单元格内容是没有修改的,而回写规则里默认是【回写修改内容】,也就是修改哪行回写哪行,此时没监控到修改的单元格,所以就没回写进去。如果是这个场景,那回写内容配置为【回写所有内容】即可。

但是此时其实还是可能存在问题,比如B表本身有数据,想要根据主键更新咋办?这个时候就得使用回写规则的下方的更新和插入功能了,需要配置为【强制先执行更新再执行插入】,此时会根据回写规则先去B表中将对应主键一样的数据update,再把不存在的数据去insert。
1.2 数据库执行了SQL但结果异常
那如果数据库执行了SQL,又该怎么排查呢?那既然有SQL了,我们来看看SQL,往往这种就是数据库本身执行异常了,所以得结合对应SQL语句、数据库执行结果来进行问题排查。
1.2.1 前端报错
首先比较常见的就是前端直接抛出异常了,如下图:

看到报错提示【回写异常】,后面跟着带一堆问号的update语句,是不是很懵?数据库怎么执行?别慌,这其实是预编译SQL的标准格式,那些问号会被后面中括号里的值按顺序替换掉。
为啥要用预编译 SQL 而非直接生成处理好的 SQL?因为预编译能防止 SQL 注入呀~也就是这种方式安全性更高。那,怎么验证?
机智的你想到了:直接复制SQL,把问号替换成实际值,然后丢给数据库执行不就完事了?这个思路没啥毛病,不过更省事的办法是直接看【显示栈信息】里的【Caused by】部分,那里通常会告诉你问题根源。
比如这个报错:【Data truncation: Data too long for column 'c_file' at row 2】,数据太大,字段存不下啦,得去调整下字段长度或者类型,这个示例是文件太大,去数据库调整下字段的类型即可。

同理,像下面这个报错【Duplicate entry '1' for key 'PRIMARY'】,也就是主键冲突,数据库插入报错了:

对于主键冲突,这里涉及有个产品功能点,很多小伙伴以为,只要我的数据库有那条记录,在界面通过参数那些过滤了,或者空表单回写,这时候直接输入对应数据,会自动update。
其实并不是的,Smartbi是当你是修改对应展示出来的数据,这个时候是update。当空表单,或者是插入了一行新的数据,这个时候会insert,并不会再去校验已经存储到数据库表的数据,也就是数据库表配置了主键,填入的数据又是主键数据已存在,就会insert失败。所以后续回写的时候,如果要更新,还是需要对展示出来的数据修改保存。
同理类似的还有个批量回写的场景,大家也可以了解下:回写-电子表格批量导入报主键或唯一约束冲突:ORA-00001:违反唯一约束条件
1.2.2 保存成功,但增删改数据不对
上面说的两种报错场景都是前端抛出异常了,那有没可能前端没异常,提示保存成功了,那又该咋获取SQL排查呢?
我知道你很急,但是你先别急,这个时候我们可以去【用户日志】或者【系统监控】那里获取呀,下面用个示例一起来看。
小陈想删除第二条数据,点击删除后,保存,提示保存成功了,但是点击确认后刷新数据还会出来,why?

首先需要明确的是,不是点击完删除,就万事大吉了,因为这个时候其实数据库并没有执行delete的语句,也就是那行记录并没有被删除。得记得点完了删除之后点保存,才算是整个操作完了。
回到这个示例,接下来,我们去【系统监控】->【SQL监控】看看刚刚执行的SQL:

这里显示有delete,咦那这不是没问题?别急,我们把那个【3321】的id替换SQL后面的问号得到最终执行SQL,去数据库执行:
delete from `writedb_zhangsan`.`write_sale` where `id` = '3321'
欸,数据库执行也是没删除成功。然后有些小伙伴可能注意到了,id应该是前面的编号,现在传进去的是后面的销售量的数据了,那这又是为啥呢?
前面说了,我们是根据回写规则去生成SQL的,所以回去看回写规则,发现回写规则配置错啦!id字段配置的是G4,也就是销售量那个单元格,改回来C4就正常啦。

同理,如果更新不成功,也是可以去看执行SQL,看看是不是回写规则配置有误。
除此以外,如果回写没问题,数据库也落地了对应数据,但是前端展示有差异的话,那就要看对应数据集取数逻辑哦,比如是不是数据集过滤掉了对应数据,又或是配置了数据权限之类的过滤了数据。此处可按数据排查问题跟踪,排查数据问题之前也发过了哦,大家想了解也可以看看:如何找SQL看数据不对问题(数据模型)、如何找SQL看数据不对问题(旧数据集)
1.3 父子链异常导致数据删除不成功
上面说了回写规则异常导致没删除成功,接下来我们来唠唠上面说的大前提,第1条!回写规则里面设置的单元格是否是一个链表而不是一棵树,这个原因导致删除不成功的场景。这句话怎么理解呢。来来来我们看看下面的例子:
如下表样,所有字段从上到下扩展,黄色单元格在回写规则中设置为回写联合主键。
- row,row2,column,same,val为扩展字段,row-func,same-func为公式,其中same-func值引用same单元格。
- 回写的单元格为C5、H5、I5、D5、G5,E5及F5非回写单元格。

如果按照所有单元格默认左父格(以单元格的左侧最近的扩展字段单元格为左父格),整个表样的父子关系长得就是一颗树了:

上图标黄的节点为包含在回写规则中的单元格。很明显,回写规则设置的单元格G5 没有在一条链表中,因此,该表样不满足第一个条件,回写时会存在问题。
在这个示例中,删除行时会失效,因为same-func公式单元格作为主键,无法正确获取。
对该资源的单元格父子关系进行微调,将same-func的左父格设置为val

此时,整个表样的父子关系如下:

这个时候就是变成了一条链(E5不需要回写),那么,数据就可以删除成功了。所以,我们要是遇到删除不成功的,首先检查一下父子关系是否是正确的。
关于检查是否存在多个链路,还可以在日志里面看,咋看呢?让我们回想一下咱们怎么看的执行sql,对对对就是那个用户日志,想起来了吗?
在【用户日志】里面的【服务端】->【开启监控】,然后去【清空缓存】之后再在电子表格上重新操作一下,这个时候日志里面会打印链路:

若日志中的回写规则链路是多行的记录,则通常仍是回写规则链路存在分支,比如上面有两条。
正常来说是只有一条:

如果有些版本没有这样的日志输出,那就需要根据上面的说明自己检查看看是不是只有一条链路了,也可以把资源简化之后执行操作看看是不是对的,毕竟资源简化之后更容易排查问题,对吧。
2、输入一条数据,保存后变两条
这个应该很多同学遇到过了,即,明明只输入了一条数据,但是,保存之后怎么数据库里面有两条数据呢!这里其实还是和1.3里面介绍的,父子不是一条链路导致的问题。
如下图,本身有一条数据:

这个时候修改row2和same的单元格的数据,保存,显示两条数据,这个不对,正常来说我是想要修改,那应该修改完成后是只有一条数据:

为啥呢,其实就是和1.3一样,因为存在多个链路,导致最终变成了两条数据,如下图,开启用户日志的监控之后点保存,这个时候可以看到是有两条:

那么来检查一下回写规则,注意到这里有一个设置了主键的单元格是静态单元格,即字段不是动态扩展的:

会有什么问题呢。这里就要涉及另一个概念,父格,什么情况下才会有父格?只有拥有【扩展】属性的单元格才能被设为父格。通常单元格的父格都是默认,默认表示的是,子格将向左或向上寻找离其最近的,具有扩展属性的单元格为其左父格或上父格。
那么,以F5为例,它左边的 E5 是固定不扩展的,所以不能当它的父格。F5 真正的左父格得往更左边找,也就是 D5。这个时候设置E5是主键的情况下,那因为E5无法作为左父格,这个链路就有两条了,其实也就对应日志里面打印的两条链路:
F5,H5,C5,D5,(I5) 以及 C5,D5,(E5)

咋整呢?如果是一定要E5作为主键,那就需要设置E5的左父格为回写规则里动态扩展字段的最后一个,这里最后一个单元格是I5:

此时只有一条链路,数据修改成功:


也可以看到日志里面的链路只剩下一条了,so,这样就是回写成功了:

如果可以不用静态单元格作为主键,改为其它动态单元格,例如这里改为D5,那也是可以回写成功的。
其实父子关系设置不正确,在编辑回写规则的时候点击保存也会有提示,也可以根据提示检查是否是要重新设置父子关系:

3、允许插入/删除行设置无效
如题所述,这是为什么?这个通常是配置项的原因,也和父格有关系,也就是上面说的,他们在不在一条链里。
大致是分为以下情况:
①若单元格自身已设置【允许修改】且【可以插入/删除行】,则单元格允许新增删除行。

②若父链中没有任何单元格允许新增删除行 → 该单元格不允许新增删除行。
③若父链中存在允许新增删除行的单元格 → 继续判断该单元格是否与回写规则相关:
- 单元格在回写规则中存在 → 允许新增删除行。
- 单元格虽未直接在回写规则中提及,但属于回写规则中主键单元格的父链层级 → 允许新增删除行。
4、普通用户无法编辑单元格
这个场景也很常见,开开心心开发了一个报表给用户填报数据,结果用户一打开,欸,怎么没办法填报,这是咋回事呢?
①检查电子表格的权限设置
电子表格支持更为细致的权限控制。请确保已经给用户分配电子表格回写的操作权限。如果仍无法回写,请检查是否设置了单元格编辑权限。注意:此“权限功能”目前仅支持电子表格,Web电子表格暂不支持。
电子表格回写的操作权限设置入口参考:操作权限
②检查是否受宏代码影响
宏代码也能控制单元格编辑权限。可尝试禁用宏,或将报表移出宏资源包,检查编辑功能是否可以正常。
③检查是否查看的同一张报表
看似简单,但很常见:管理员看的是报表A,用户看的是报表B,而填报功能设在报表A上。怎么检查呢。
- 对资源右键,【资源属性】获取资源ID,确认普通用户所打开的资源是否设置了【填报属性】。或管理员在报表中新增内容并发布,检查用户是否可见。用户看不到,那说明不是一张报表了~
总的来说,按照这三个方向排查,大部分情况都能迎刃而解~如果还搞不定,那么就找找官方支持渠道来支支招吧!
5、删错数据行
有没有遇到过删除了A那条数据,保存后,A没被删除,反而B被删除了呢。没遇到也没关系,提前先get下这个知识,后面出现就可以知道咋解决了。
这个问题主要需要排查以下两个方面:
①单元格属性是否有配置【排序】

②数据库返回数据随机
为啥上面两个会引起删除错呢?是因为某些数据库对应每一次报表刷新返回的数据都可能不同,因此选中行删除数据时,看到删除的是第一行数据,但实际上在点击删除时,报表重新刷新返回的数据顺序与一开始返回的数据顺序并不相同,所以会出现删除选中行以外的其他行数据。
(注:因考虑到报表存在公式计算的情况,因此在操作报表进行增删改时,报表是必须重新刷新的。)
此场景建议是去掉单元格属性中的排序,如果有需要排序可考虑数据库中对主键字段进行排序,对主键字段排序是为了避免数据库每次返回数据都不一致。
但这里要注意,直接在模型里面的【SQL查询】写的order by设置排序会不生效,建议是使用【模型汇总查询】或是【模型明细查询】,在里面对字段排好序再拖拽到电子表格中展示。
如果是用旧数据集,可以在【原生sql】数据集里排序。
6、主键自增不生效
回写规则配置了主键自增,为啥回写的时候没有自增呢。

如果真遇到这个场景,那得好好看看上次的回写方案:数据回写填报太头疼?方案请收好!-4、回写保存主键自增
得先业务库表建好主键自增字段,产品这边只是标识这个主键是自增的,无需再获取单元格数据进行insert。
来个总结
洋洋洒洒这么多,来来来,让我们总结一下,回写遇到问题怎么办?敲敲黑板,记住啦!
1、冰糖葫芦串:回写单元格关系要是一个链表,就像冰糖葫芦一样串成一条线,严禁变成一棵树。
2、交叉表别任性:删整行整列时,对象行/列不能有多个主键,否则系统会懵圈。
3、排序找数据库:在电子表格中排序不可靠!建议在数据集中处理:
- 数据模型:排序用【模型汇总查询】或【模型明细查询】里对字段进行排序
- 旧数据集:在【原生SQL】中直接写好ORDER BY
4、日志会说话:遇事不决看日志,插入删除全记录,还能检查冰糖葫芦串没串好。
记住:小问题查日志,大问题找官方!收藏这份指南,让你优雅搞定回写问题~ |