MySQL 函数的一个小tip

2023-03-08 19:29:16 浏览数 (1)

MySQL 函数的一个小tip

今天上班的时候,同事问了一个问题,关于MySQL函数的。说实话,这方面积累确实比较少,主要原因是函数和存储过程都偏向于业务逻辑,在线上环境一般不建议使用,开发人员应该尽可能将这些业务逻辑写在业务代码里面,而不是让数据库去操作。数据库应该去做它擅长的事情,例如数据的增删改查之类的。

但是,这也不是说线上环境,就不允许使用函数和存储过程,有些存量的历史业务,可能改造起来成本过高,收益和成本不成正比,所以数据库里面还是有这些数据形态存在。

01

问题介绍

这个具体的函数问题,可以拆分为以下几个:

1、如何查看MySQL函数的详细信息?

这个问题其实还好,在MySQL5.7和MySQL8.0里面,我们都可以通过information_schema.routines和information_schema.parameters来查看函数的相关信息。

其中routines表显示的是函数的创建信息;parameters表显示的是函数的参数信息。

来看下面例子:

创建一个简单的函数:

代码语言:javascript复制
mysql> create function myf1 (param1 int) returns int 
mysql> no sql  
mysql> begin 
mysql> return (select 2); 
mysql> end//
Query OK, 0 rows affected (0.02 sec)

简单解释下这个SQL吧:

param1 int代表我们的输入参数是一个整数;

returns int代表函数返回值是个整数;

no sql表示函数体不包含SQL语句;

return (select 2)是真正的函数体。

函数的创建信息:

代码语言:javascript复制
mysql> select * from information_schema.routines where routine_schema='test' G
*************************** 1. row ***************************
           SPECIFIC_NAME: myf1
         ROUTINE_CATALOG: def
          ROUTINE_SCHEMA: test
            ROUTINE_NAME: myf1
            ROUTINE_TYPE: FUNCTION
               DATA_TYPE: int
CHARACTER_MAXIMUM_LENGTH: NULL
  CHARACTER_OCTET_LENGTH: NULL
       NUMERIC_PRECISION: 10
           NUMERIC_SCALE: 0
      DATETIME_PRECISION: NULL
      CHARACTER_SET_NAME: NULL
          COLLATION_NAME: NULL
          DTD_IDENTIFIER: int
            ROUTINE_BODY: SQL
      ROUTINE_DEFINITION: begin return (select 2); end
           EXTERNAL_NAME: NULL
       EXTERNAL_LANGUAGE: SQL
         PARAMETER_STYLE: SQL
        IS_DETERMINISTIC: NO
         SQL_DATA_ACCESS: NO SQL
                SQL_PATH: NULL
           SECURITY_TYPE: DEFINER
                 CREATED: 2023-01-09 06:26:05
            LAST_ALTERED: 2023-01-09 06:26:05
                SQL_MODE: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
         ROUTINE_COMMENT:
                 DEFINER: root@%
    CHARACTER_SET_CLIENT: utf8mb4
    COLLATION_CONNECTION: utf8mb4_0900_ai_ci
      DATABASE_COLLATION: utf8mb4_0900_ai_ci

函数的参数信息:

代码语言:javascript复制
mysql> select * from information_schema.parameters where specific_schema='test'G
*************************** 1. row ***************************
        SPECIFIC_CATALOG: def
         SPECIFIC_SCHEMA: test
           SPECIFIC_NAME: myf1
        ORDINAL_POSITION: 0
          PARAMETER_MODE: NULL
          PARAMETER_NAME: NULL
               DATA_TYPE: int
CHARACTER_MAXIMUM_LENGTH: NULL
  CHARACTER_OCTET_LENGTH: NULL
       NUMERIC_PRECISION: 10
           NUMERIC_SCALE: 0
      DATETIME_PRECISION: NULL
      CHARACTER_SET_NAME: NULL
          COLLATION_NAME: NULL
          DTD_IDENTIFIER: int
            ROUTINE_TYPE: FUNCTION
*************************** 2. row ***************************
        SPECIFIC_CATALOG: def
         SPECIFIC_SCHEMA: test
           SPECIFIC_NAME: myf1
        ORDINAL_POSITION: 1
          PARAMETER_MODE: IN
          PARAMETER_NAME: param1
               DATA_TYPE: int
CHARACTER_MAXIMUM_LENGTH: NULL
  CHARACTER_OCTET_LENGTH: NULL
       NUMERIC_PRECISION: 10
           NUMERIC_SCALE: 0
      DATETIME_PRECISION: NULL
      CHARACTER_SET_NAME: NULL
          COLLATION_NAME: NULL
          DTD_IDENTIFIER: int
            ROUTINE_TYPE: FUNCTION

注意红色的部分,就是问题所在。

第二行好理解,就是我们传入的参数param1,它的mode是IN,类型为int。

第一行包含参数名为Null的参数,它的mode也是Null,类型是int

2、为什么输入参数只有1个,单数parameter里面还有一行PARAMETER_MODE=Null,PARAMETER_NAME=Null 的记录?

这个问题当时确实比较模糊,主要是对于Null值不太清楚,查了查官方文档,找到了结果。

  • PARAMETER_MODE The mode of the parameter. This value is one of IN, OUT, or INOUT. For a stored function return value, this value is NULL.
  • PARAMETER_NAME The name of the parameter. For a stored function return value, this value is NULL.
  • DATA_TYPE The parameter data type. The DATA_TYPE value is the type name only with no other information. The DTD_IDENTIFIER value contains the type name and possibly other information such as the precision or length.

简单翻译一下:

对于PARAMETER_MODE字段,正常取值是in,out或者inout,但是对于函数返回值,这个值是NULL;我们没有定义param1参数的取值,原因在官方文档中也有体现:

Specifying a parameter as IN, OUT, or INOUT is valid only for a PROCEDURE. For a FUNCTION, parameters are always regarded as IN parameters.(对于函数,参数总是被视作in类型)

对于PARAMETER_NAME字段,正常取值是参数名字,对于函数返回值,这个值是NULL;

对于DATA_TYPE字段,这个字段只返回类型名字,而不包含其他信息,例如类型长度。也就意味着如果函数返回值是varchar(10),这个字段也会只显示varchar,而没有长度信息。长度信息需要在另外一个字段DTD_IDENTIFIER上去获取。

到这里,这个小问题就解决了。相信不长使用函数的小伙伴,肯定也有收获。

最近很少搞MySQL相关的东西,抽空水一篇,今天就到这里吧。晚安。

0 人点赞