SQL方式连接数据源

概述

SQL方式连接数据源是指用户在Sugar上编辑SQL语句,并且建立字段模型(录入各字段名称、数据类型等信息),然后通过连接用户提供的数据库执行SQL,最后将SQL执行的结果绑定到Sugar的图表或过滤条件上进行展示和使用。过程中无需任何FE、RD开发投入,轻松搭建可视化报表页面。

SQL方式连接数据源需要用户了解SQL语法、会写SQL语句,如果您对SQL不太了解,建议您首先学习一下SQL相应的知识,避免因SQL语句相关问题而浪费您的时间。

数据源

SQL方式连接的数据源是管理员在空间中「数据源管理」部分添加的。数据源的详细配置信息只有管理员可见。

SQL模型

Sugar中的SQL模型是指在数据源的基础上建模的SQL查询模型,主要包含SQL语句以及建模信息(包括字段名称、字段数据类型等),当然SQL语句可以是简单的单表查询,也可以是复杂的多表join操作。

建立SQL模型非常简单,在需要绑定SQL模型的「图表」或「过滤条件」的控制面板中选择新建SQL模型:

图片

在下图中,我们选择了一个「数据源」,然后编辑了一条简单的SQL语句:从card表中查询id、to_id两个字段,最后我们对两个字段分别进行了建模描述,录入了它们的中文名称和数据类型。

图片

编辑SQL的字段模型支持拖动排序和自动从SQL语句中提取字段名称。

SQL模型中使用表达式

SQL模型中我们允许使用表达式(只支持加减乘除取模计算,因此在表达式中只允许出现以下字符:+-*/%()),例如下图中我们新建了两个表达式(表达式中使用到的字段需要使用{}包围,并且需要保证使用到的字段必须是数值类型),这样在之后的图表中,我们就可以直接使用了「人均PV」这个全新的字段了:

图片

SQL模型绑定数据值映射

有时数据库中保存的可能是对用户不友好的代号值,数据值映射允许您配置一对一的映射,将这些不友好的值映射为可以展示给用户的值。

比如库里存的数据是:

图片

但是我想展示的数据是:

图片

通过配置数据值映射就可以做到将数据中需要映射的值进行转换。

新建和管理数据值映射需要在空间管理中的「数据值映射管理」中进行。

在SQL模型中,对于需要数据值映射的字段,可以在编辑字段模型时进行选择:

图片

图表中禁用数据值映射

如果有这样的需求:在一个图表中,既需要映射前的数据做展示,也需要映射后的字段做展示,或者想套用一个已经配置好了映射的SQL模型,但是展示的时候就是希望只展示原始值,这时候就可以使用禁用数据值映射功能。

禁用数据值映射会在具体的图表的「控制面板」中配置,例如表格的控制面板的数据列配置最大化后如下:

图片

这样就可以同时展示type字段映射前和映射后的值了:

图片

数据值映射的下钻兼容

由于使用数据值映射后,图表展示的就不再是原始的数据值了,那么下钻后向下层图表传递的下钻参数会不会受到影响呢?

对于使用了数据值映射的数据,Sugar会在「下钻参数」中多加入对应的原始值数据,例如下图:

图片

用户只需要在下钻参数信息中获取对应的 xxx_sugar_origin 字段即可获取重命名前的原始值。

SQL模型中的行转列

什么是行转列?首先看一个简单明了的例子:

数据库中存储的数据格式是这样的:

图片

但是想展示的数据是这样的:

图片

上面的例子就是典型的行转列,我们把 name 字段中的每种取值都转换成了一个列来展示,并且将 val 字段的取值作为了转换后新列的取值。

当然,如果您对SQL语言比较了解,其实通过SQL语句就可以实现这样的行列转换,但是这样的SQL语句会变得很复杂,很不利于理解,因此Sugar提供了SQL模型的行转列功能。

下面就基于上面的简单例子来说明如何使用Sugar的行转列功能:

开启行转列

在SQL建模时有个开关可以开启,并且需要填入行转列的名称字段和取值字段,如下图建模时,我们不仅对的date字段做了描述,我们还对行转列之后的新列pv、uv、post做了描述,但并没有对nameval做建模,因为行转列之后就不存在这两个字段了。

特别需要注意的是:行转列时,SQL语句中select的字段需要谨慎填写,Sugar目前只允许您select三个字段,即除了名称和取值字段以外,只能额外select一个维度字段,大部分情况下都是日期、时间等。

图片

绑定行转列模型到图表

将模型绑定到图表时与和普通的非行转列的模型一样,因为我们已经将数据行转列了,在绑定图表数据时就可以直接使用转换后的各个列了,如下图:

图片

绑定时还可以选择「绑定所有行转列」来避免手动在图表中绑定太多列。

行转列的累计、均值

在使用行转列功能时,Sugar默认在数据中自动添加了两个新列: sugar_row2col_totalsugar_row2col_avg,分别计算了行转换后的各个新列的累加值均值

在上面的例子中,sugar_row2col_total 表示 pv、uv、post这三个行转换后新列的累加值,sugar_row2col_avg 也是同理):

因此,报表编辑者就可以对这两列进行数据建模,并且同样可以将其绑定到图表上进行展示。

对这两列进行建模:

图片

行转列配置字段名称映射

在使用行转列的过程中,可能会出现这样的使用场景:行转列得到的列名只是一个可读性很差的编号,虽然我们可以在绑定数据或建模的时候给它配置展示名称,但如果行转列的数据很多,岂不累死宝宝们了。所以当在图表中配置了「绑定所有的行转列」功能时,Sugar支持利用「数据值映射」自动将列名映射为可读性较好的值。

比如下面这个例子,type字段是行转列后即将作为名称的字段,数据库里保存的是拼音:

图片

直接进行行转列结果如下,可以看到这个拼音虽然可以给用户展示,但用户看到的结果并不直观:

图片

此时可以我们配置这样一个重命名映射:

图片

并在SQL模型中进行配置:

图片

就可以完成列名的映射了:

图片

当然,如果有几个特殊的列想在字段名称映射的同时进行特殊的配置,可以在SQL模型中单独添加字段并配置显示名称。 下图中对xiaoshou这列的展示名称进行了单独配置,还可以注意到图中的右侧红框中,对行转列结果中xiaoshou这一列的「取值」也配置了数据值映射:

图片

结果如下:

图片

SQL模型的共用

Sugar中一个SQL模型可以供多个图表共用,因此在绑定图表的数据时可以从现有的SQL模型中进行选择,如下图(当然,您也可以直接新建一个SQL模型,或者修改选中的SQL模型,如下图红框中的操作按钮):

图片

需要注意的是,修改SQL模型会影响到所有使用本模型的图表或过滤条件。

关于SQL中自动添加limit的说明

在Sugar中,为了防止SQL语句查询的结果太大,我们会默认在SQL语句的最后添加上limit 0, 5000这样的语句来限制查询结果的行数(limit 0, 5000是MySQL的语法,不同类型的数据库,默认添加的语法会不一样),如下图:

图片

当然,你可以自己添加limit,如果您自己添加了limit,我们就不会再添加limit语句了,如下图:

图片

再者,如果您使用的表格来展示数据,如果数据行数很多,可以配置后端分页来使用limit语法,详见『表格的后端分页

SQL语句中关联过滤条件

在实际的使用场景中,我们经常需要在SQL语句中嵌入一些where条件,并且这些where条件是根据用户的交互动态生成的。基于此,在Sugar中,我们已经支持了多种常用的「过滤条件」(日期、单选、多选等等),并且支持将这些过滤条件的取值动态嵌入到SQL模型的语句中,例如:

图片

关联过滤条件的语法

Sugar中关联过滤条件需要按照特定的语法格式来书写,格式为 {field = [conditions.key]}

  • 其中field是SQL中的字段名(可以随意,和具体SQL有关);
  • =号是SQL判断逻辑词,可以支持不写判断逻辑,Sugar会根据不同的过滤条件类型自动补全;
  • 过滤条件必须要使用[]包围,并且必须输入conditions关键词,key是指过滤条件的「查询key值

按照这样的规则就可以将过滤条件嵌入到SQL模型的伪SQL语句中,Sugar在运行时会自动的将相应的部分替换成当前的过滤条件取值。值得注意的一点时,如果SQL语句中嵌入了这样的语法,但是过滤条件中并没有传递该参数,Sugar会将嵌入的部分自动替换为1=1的恒等式。 如下图中我们传递了date过滤条件,但没传递name过滤条件:

图片

不同类型的过滤条件在替换伪SQL语法时有细微的差别,下面就一一描述在SQL中嵌入各种类型的过滤条件(下面的各个截图都是图表数据的『调试』时所展示的,左侧是原始的伪SQL,右侧是关联了过滤条件之后生成的真正要在数据库上执行的SQL语句):

日期

  • 如果没有判断逻辑,会自动补全为 =
  • 如果日期上没加单引号,会自动加上单引号,当然,用户也可以加数据库所支持的双引号
  • 支持扩充语法(number),可以将日期转化为Ymd的格式
  • 支持扩充语法(+/-N),可在日期的取值上加减天数,如 (-2) (+1)
  • 支持扩充语法(year)(month)(day)分别获取年月日
  • 扩充语法可联合使用,如 (-2.number)(+30.month)(+365.year)
  • 注意:下图中的 date 只是示例,在具体使用时,需要替换为过滤条件的「查询key值

图片

日期范围

  • 如果没有判断逻辑,会自动补全为 between and
  • 使用日期范围中两个值时不需要加单引号
  • 同样支持扩充语法(number)
  • 支持取日期范围中的单个日期值,可以使用(0)、(1),也可以使用(first)、(last)
  • 单个日期值,如果没有判断逻辑,会自动补全为 =,并且会自动补全单引号
  • 单个日期值也支持(number)语法,如:(0.number)
  • 单个日期也支持(+/-N)语法,如:(first.-1),当然也支持如:(last.+1.number)
  • 注意:下图中的 dateRange 只是示例,在具体使用时,需要替换为过滤条件的「查询key值

图片

时间

  • 如果没有判断逻辑,会自动补全为 =
  • 如果时间上没加单引号,会自动加上单引号
  • 支持扩展语法获取时间中的 日期时间 部分
  • 通过(date)获取的日期部分,还支持(+/-N)语法来对日期做加减
  • 对于年月日时分秒,支持 number 语法将 01 转化为 1,并且除掉默认的单引号
  • 注意:下图中的 dateTime 只是示例,在具体使用时,需要替换为过滤条件的「查询key值

图片

时间范围

  • 如果没有判断逻辑,会自动补全为 between and
  • 使用时间范围中两个值时不需要加单引号
  • 支持取时间范围中的单个时间值,可以使用(0)、(1),也可以使用(first)、(last)
  • 单个时间值,如果没有判断逻辑,会自动补全为 =,并且会自动补全单引号
  • 获取到单个时间之后,也可以继续获取日期部分和时间部分,并支持进一步的扩充语法,可见上面章节
  • 注意:下图中的 dtr 只是示例,在具体使用时,需要替换为过滤条件的「查询key值

图片

输入框

  • 如果没有判断逻辑,会自动补全为 =
  • 如果没加单引号,会自动加上单引号
  • 支持扩充语法(number),将内容转换为数字
  • 支持扩充语法(splitComma),可以将输入值按照英文逗号进行分割,从而支持SQL中的In逻辑
  • 注意:下图中的 texttext1 只是示例,在具体使用时,需要替换为过滤条件的「查询key值

图片

单选列表、下拉单选

  • 如果没有判断逻辑,会自动补全为 =
  • 如果没加单引号,会自动加上单引号
  • 支持扩充语法(number),将内容转换为数字(当然,取值必须能转化成数字才行)
  • 支持扩充语法(splitComma),可以将取值按照英文逗号进行分割,从而支持SQL中的In逻辑
  • 注意:下图中的 select、list、select1 只是示例,在具体使用时,需要替换为过滤条件的「查询key值

图片

多选列表、下拉多选

  • 如果没有判断逻辑,会自动补全为 in
  • 不需要加单引号
  • 支持扩充语法(number),当然只有传入的值真的是数值才会生效
  • 判断逻辑是like时,会自动生成多个or...like模式,见下图
  • 支持扩充语法(raw),一般用于过滤条件的硬嵌入,见下一大章节
  • 注意:下图中的 multiSelect 只是示例,在具体使用时,需要替换为过滤条件的「查询key值

图片

树形选择

  • 如果没有判断逻辑,会自动补全为 in
  • 不需要加单引号
  • 支持扩充语法(number),当然只有传入的值真的是数值才会生效
  • 判断逻辑是like时,会自动生成多个or...like模式,见下图
  • 支持扩充语法(raw),一般用于硬嵌入
  • 注意:下图中的 _selectTree 只是示例,在具体使用时,需要替换为过滤条件的「查询key值

图片

多重逻辑

  • 多重逻辑因为本身就具有判断逻辑,因此不允许添加任何=等判断逻辑词
  • 支持扩充语法(number)
  • 注意:下图中的 _logic、_logic1、_logic2 只是示例,在具体使用时,需要替换为过滤条件的「查询key值

图片

SQL语句中硬嵌入过滤条件

和上一节描述的SQL语句中关联过滤条件有所不同,Sugar还支持将过滤条件的取值直接嵌入到SQL语句中,不仅是where条件语句中,还可以将过滤条件的取值嵌入到SQL语句的任何地方(如select中,以及表名等)。

硬嵌入过滤条件的语法是 {conditions.key} :

  • key是指过滤条件的「查询key值
  • 不同类型的过滤条件,和上一节相同,都支持扩充语法,如日期类过滤条件的 conditions.date(+1.number),每种具体的过滤条件语法可参见上一节
  • 和上一节不同,如果SQL语句中有硬嵌入的语法,但是过滤条件并没有传递相应的值,那么该硬嵌入的语法会被替换为空字符串,而不是上节中的1=1
  • 另外,硬嵌入查询条件其实本质就是字符串替换,所以并不会像上节中那样会自动给字符串取值加上单引号之类,具体可见下图的第7行,我们需要手动加上单引号

示例如下图(过滤条件中:multiSelect是一个多选,选中了col1和col2;date是日期过滤条件,取值为2018-08-07;但是并没有传递key值为text的过滤条件):

图片

过滤条件的豁免

前面我们大篇幅的说过,伪SQL语句中可以嵌入过滤条件,如果伪SQL的语法中写了但是过滤条件没传递对应的值,那么我们会自动在伪SQL中替换为 1=1 的恒等或空字符串;那么反过来,如果过滤条件传递了值,但是伪SQL中却没有用到,会怎么样?

这种情况下,Sugar会报错提示过滤条件传递了但是SQL中没使用,这样做是有原因的,因为如果用户添加了一个新的过滤条件,但是在图表中却忘记了修改相应的伪SQL语句,这时SQL并没有任何的语法错误,会照样查询到数据,但是这时的数据结果可能是不正确的,因为忽略了一个过滤条件。所以Sugar不允许这样的情况出现,我们会主动报错,提醒用户修改SQL语句,此时用户除了修改SQL语句外,还有另外一个选择,那就是豁免该过滤条件对当前图表的影响,如下图在绑定图表的数据时可以选择要豁免的条件。

图片

SQL语句中关联下钻参数

有关图表如何配置下钻功能,详见图表的下钻设置

在绑定了图表的下钻功能之后,Sugar在请求下钻弹出图表的数据时会额外附加上一些下钻的具体信息,例如,一个饼图有三个扇形区域,点击每个扇形区域时,我们在拉取弹出图表的数据时会加上drillDowns参数用来描述用户到底是点击了哪一区域。并且Sugar支持在伪SQL语句中嵌入这些下钻的参数,从而达到点击不同的区域弹出的图表的数据不同。

后端接受到的drillDowns参数的格式如下(由于Sugar支持多层下钻,因此drillDowns参数是个数组,数组的每项分别表示每级下钻的信息):

"drillDowns": [
    { // 第一层下钻
        "item": {
            "type_sugar_origin": "zhuanjia",
            "type": "专家",
            "id": "1",
            "link": "www.baidu.com",
            "type_rowspan": 1,
            "id_rowspan": 1,
            "link_rowspan": 1,
            "type_sugar_origin_rowspan": 1
        },
        "fireKey": "type"
    },
    { // 第二层下钻
        "item": {
            "name": "数据1",
            "value": [
                1218,
                1461
            ],
            "category": "点1"
        },
        "fireKey": ""
    }
]

和查询条件类似,伪SQL语句中支持嵌入下钻的一些参数,格式为 {field = [drillDowns(last).key]}

  • 其中field是SQL中的字段名(可以随意,和具体SQL有关);
  • =号是SQL判断逻辑词,可以支持不写判断逻辑,Sugar会自动补全为=
  • 下钻参数需要使用[]包围,并且必须输入drillDowns关键词;
  • 由于支持多层下钻,(last)是指最后一层下钻的参数,当然我们支持不传(即 [drillDowns.key])默认就是最后一层,Sugar支持(0)、(1)...等数字取不同层,同样也支持(first)、(last)取第一层和最后一层;key是映射到上面代码示例的item中的字段名;
  • 支持扩充语法(number)(raw);
  • 下钻的参数item中的字段有可能是个数组,Sugar允许你嵌入该数组的任意一个元素,语法为: [drillDowns(0).value(1)],其中的1表示数组的index号,他也支持扩充语法(number),格式为[drillDowns(0).value(1,number)];
  • 可以通过{field = [drillDowns(0).sugar_fireKey]}的方式取到某层的触发ID,比如表格就可以判断是点击了哪列触发的下钻;
  • 如果SQL中要取的值在下钻参数中没有找到,则会用1=1替换,保证SQL的正常运行

针对上面代码示例,我们可以这样取其中的参数:

图片

每种图表在点击下钻时所传递到下层图表的参数格式不尽相同(例如父图表也是使用SQL方式绑定的数据,Sugar在一些情况下会额外增加一些参数的,如数据使用了数据值映射,Sugar会自动将重命名之前的原始值也附加上,这样在展示时是使用的重命名的中文,而在下钻时有可以将原始的英文或编码传递到后端),一定要善用「图表的调试」,通过弹出图表的“控制面板”中的“调试”按钮来查看此时下钻的参数详情,从而可以很清晰的看到有哪些参数可以嵌入到自己的SQL语句中。

SQL语句中硬嵌入下钻参数

如果您对硬嵌入的概念还不太了解,请先参考文档SQL语句中硬嵌入过滤条件

通常情况下,我们可以通过「上一节」的内容将下钻参数与SQL的过滤条件绑定在一起,例如{field = [drillDowns(last).key]}

如果我们希望下钻的参数的值不与其它内容挂钩,直接嵌入到SQL语句中,我们可以使用SQL语句中硬嵌入下钻参数,语法如下:

  • {drillDowns.key}
  • {drillDowns(0).key}
  • {drillDowns(first).key}
  • {drillDowns(first).key(1)}
  • {drillDowns(first).sugar_fireKey}

大家会发现和之前嵌入过滤条件的用法很类似,下面分别解释一下:

  • 第1种:最常用的语法,等同于{drillDowns(last).key}
  • 第2种:由于Sugar支持多层下钻,因此drillDowns参数是个数组, 所以 0 表示第1层下钻的,你可以修改这个数字
  • 第3种:first值也可以写为last,分别表示第1层和最后1层下钻的参数
  • 第4种:对于下钻的数据如果是一个数组,比如上一节中的散点图下钻, key(1) 中的1就是表示下钻的数据的index
  • 第5种:可以通过这种方式取到某层的触发ID,比如表格就可以判断是点击了哪列触发的下钻

以上一节的下钻参数为例:

图片

SQL语句中关联联动参数

有关图表如何配置联动功能,详见图表的联动设置

如果图表被某个上级图表设置为了联动的下级图表,当上级图表触发联动时,Sugar在请求下级图表的数据API中会会额外附加上一些联动的具体信息。例如,如果图表的上级图表是一个饼图,点击每个扇形区域时,我们在拉取弹出图表的数据时会加上dependence参数用来描述用户到底是点击了哪一区域。并且Sugar支持在伪SQL语句中嵌入这些联动的参数,从而使得下级图表的数据根据点击区域的不同进行刷新。

下级图表接受到的dependence参数格式如下:

"dependence": {
    "item": {
        "name": "数据1",
        "value": [
            560,
            1354
        ],
        "category": "点4"
    },
    "fireKey": ""
}

在伪SQL语句中嵌入联动参数的格式为 {field = [dependence.key || default]}

  • 其中field是SQL中的字段名(可以随意,和具体SQL有关);
  • =号部分是SQL判断逻辑词,支持的逻辑词有:=, !=, <>, >=, <=, >, <, in, like, between, regexp等;
  • 可以支持不写判断逻辑词,Sugar会自动补全为=
  • 联动参数需要使用[]包围,并且必须输入dependence关键词;
  • 支持扩充语法(number)(raw)
  • key为要取的数据在item中的字段名;
  • 联动参数item中的字段有可能是个数组,Sugar允许你嵌入该数组的任意一个元素,语法为: [dependence.key(1)],其中的1表示数组的index号,他也支持扩充语法(number),格式为[dependence.key(1,number)];
  • 可以通过[dependence.sugar_fireKey]的方式取到联动的触发ID,比如表格就可以判断是点击了哪列触发的联动;
  • default为默认值,当联动参数不存在,或者在联动参数中找不到key配置的字段时,可以配置默认值让sql拉取默认数据;
  • 如果联动参数不存在且默认值也未配置时,则会用1=1替换整个表达式,保证SQL的正常运行;

针对上面代码示例,我们可以这样取其中的参数:

图片

当联动参数不存在时,看一下有默认值与没有默认值的对比:

图片

每种图表在触发联动时传递到下级图表的参数格式不尽相同(例如上级图表也是使用SQL方式绑定的数据,Sugar在一些情况下会额外增加一些参数的,如数据使用了数据值映射,Sugar会自动将重命名之前的原始值也附加上,这样在展示时是使用的重命名的中文,而在联动时又可以将原始的英文或编码传递到后端)。

一定要善用「图表的调试」,在上级图表的联动触发时,通过点击下级图表“控制面板”中的“调试”按钮来查看此时联动参数的详情,从而可以很清晰的看到有哪些参数可以嵌入到自己的SQL语句中。

SQL语句中硬嵌入联动参数

如果您对硬嵌入的概念还不太了解,请先参考文档SQL语句中硬嵌入过滤条件

通常情况下,我们可以通过「上一节」的内容将联动参数与SQL的过滤条件绑定在一起,例如{field = [dependence.key || default]}

如果我们希望联动的参数的值不与其它内容挂钩,直接嵌入到SQL语句中,我们可以使用SQL语句中硬嵌入联动参数,语法如下:

  • {dependence.key || default}
  • {dependence.key(1) || default}
  • {dependence.sugar_fireKey}
  • 必须输入dependence关键词并使用{}包裹表达式;
  • key为要取的数据在item中的字段名;
  • default为默认值,当联动参数不存在,或者在联动参数中找不到key配置的字段时,可以配置默认值让sql正常运行并拉取默认数据;
  • 联动参数item中的字段有可能是个数组,Sugar允许你嵌入该数组的任意一个元素,语法为: {dependence.key(1)},其中的1表示数组的index号
  • 可以通过{dependence.sugar_fireKey}的方式取到联动的触发ID,比如表格就可以判断是点击了哪列触发的联动;
  • 如果联动参数不存在且默认值也未配置时,则会用空字符串替换整个表达式;

以上一节的联动参数为例:

图片

联动参数不存在的情况:

图片

SQL中关联用户邮箱

Sugar中支持在SQL语句中嵌入当前登录的用户的邮箱,如下语法:

图片

SQL中嵌入日期宏定义

Sugar中支持在伪SQL中嵌入一些固定的日期宏定义,主要包含:

  • {YEAR}表示当前年
  • {MONTH}表示当前月
  • {DAY}表示当前日
  • {HOUR}表示当前小时
  • {MONTH}{DAY}{HOUR}支持(number)语法,将01转换成1
  • {DATE}表示当前日期 格式如:2018-04-22
  • {DATE}支持+/-N语法,并且支持(number)语法

图片

SQL中嵌入URL参数

在报表或大屏的URL中,您可以加入额外自定义的查询参数,并将其嵌入至图表或过滤条件的SQL语句中

例如,您的报表URL本来是:

图片

您可以在其中加入:「&table=users&column=name&year=2018」:

图片

在图表或过滤条件的SQL模型中可以将URL参数的取值嵌入到SQL语句的任何地方(如select中,表名,where条件等)。

SQL中嵌入URL参数的格式为{qureys.key},其中key就是URL中参数的名称,例如上面URL例子中的tablecolumn

如果您想在URL中某个key未传值的情况下指定一个默认值,那么嵌入URL参数的格式为{qureys.key || default_value},将default_value替换为默认值即可。

当URL如上例所示,其中table,column,year全部有值时SQL转换示例如下图:

图片

table,column,year全部无值时SQL转换示例如下图,此时columntable的值都替换为了默认值,year由于没有默认值也未传值被替换为了空字符串:

图片

本页内容