【问题标题】:What is the type casting hierarchy in mysql?mysql中的类型转换层次结构是什么?
【发布时间】:2020-12-06 07:31:57
【问题描述】:

举个例子:

WITH tbl as (
    select 1, 1e2, 1.2e-4, 1.235, null, 0b01, if(1=1, 1, 2) union
    select 1, 1e2, 1.2e-4, 1.235, null, 0b01, if(1=1, 1, 2.4) union
    select 1, 1e2, 1.2e-4, 1.235, null, 0b01, if(1=1, 1, 'a')
)
select * from tbl

如果我只在cte 中包含第一个select 语句,则类型将为int。如果我包含第一个和第二个,则类型将为DECIMAL,如果我包含所有三个,则类型将转换为VARCHAR(无论三个语句的位置如何)。

mysql 如何确定将其转换为哪种类型——我在哪里可以找到“类型层次结构”?大多数其他 DBMS 是否同样处理这个问题,还是每个 DBMS 都不同?

【问题讨论】:

标签: mysql sql casting union


【解决方案1】:

首先,要问关于其他数据库的问题,您需要使用标准 SQL 来表达 SQL——即使用 case 表达式而不是 if

with tbl as (
    select 1, 1e2, 1.2e-4, 1.235, null, 0b01, (case when 1=1 then 1 else 2 end) union
    select 1, 1e2, 1.2e-4, 1.235, null, 0b01, (case when 1=1 then 1 else 2.4 end) union
    select 1, 1e2, 1.2e-4, 1.235, null, 0b01, (case when 1=1 then 1 else 'a' end)
)
select * from tbl;

几乎在任何数据库中,第三行都会产生错误。 case 表达式有两条路径,一条返回int,一条返回字符串。根据标准 SQL 的规则,case 表达式的类型是 int,并且会出现类型转换错误。表达式的类型与返回的值无关。

然而,MySQL 偏离了标准。在这种情况下,它允许类型为字符串。

union 也会发生类似的情况。它验证类型是否兼容并确定适当的类型。由于大多数数据库对第三个子查询返回错误,因此在这种情况下类型转换是无关紧要的。

但是,当您考虑前两个时,它是相关的。前两个中的类型不同(int 与 numeric/decimal)。这些通常是兼容的,所以 numeric/decimal 是联合返回的类型——并且没有错误。

我应该注意到一些数据库会耍花招。例如,SQL Server 将允许您的代码,但它会返回一个小数。为什么?它在 解析 阶段消除了case 表达式,因此它从不考虑返回字符串。也就是说,如果您使用1=0,则会产生错误。

【讨论】:

    【解决方案2】:

    union all 查询的所有成员必须具有匹配的列数据类型:按照您编写查询的方式,数据表需要决定最后一列应使用哪种数据类型。

    mysql 如何确定将其转换为哪种类型——我在哪里可以找到“typer hierarchy”?

    当被要求比较不同数据类型的值时,MySQL 会通过 juergen d 评论的启发式算法 described in the documentation。简而言之,如果您混合数字和字符串,它们最终会作为(浮点)数字进行比较。这是列表中的最后一个要点,有点笼统:

    • 在所有其他情况下,参数将作为浮点(实数)数进行比较。例如,字符串和数字操作数的比较是作为浮点数的比较进行的。

    你还问过:

    大多数其他 DBMS 是否同样处理这个问题,或者每个 DBMS 的处理方式不同?

    并非所有数据库都有相同的决策树。还有一些数据库由于数据类型不一致(Postgres 就是一个例子),您的语句会简单地失败。

    带走:不要依赖隐式转换(分开、简单、明确的情况)。了解您的数据类型,并在需要时对正确的数据类型执行显式转换。这使得查询更明确地知道它应该做什么,并且为您(以及您的代码的未来读者和维护者)节省了记住数据库隐式转换规则的负担。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-12
      • 1970-01-01
      • 1970-01-01
      • 2021-05-19
      • 1970-01-01
      • 2020-08-30
      • 2011-05-26
      相关资源
      最近更新 更多