【问题标题】:On Data migration, getting error: operator does not exist: boolean = integer Hint: No operator matches the given name and argument types在数据迁移时,出现错误:运算符不存在:布尔 = 整数提示:没有运算符与给定的名称和参数类型匹配
【发布时间】:2021-05-11 03:09:34
【问题描述】:

将数据库 mysql v5 迁移到 postgres v12 后,Java Spring 应用程序显示以下错误: 错误:运算符不存在:布尔 = 整数 提示:没有运算符匹配给定的名称和参数类型。您可能需要添加显式类型转换。

【问题讨论】:

    标签: java mysql postgresql spring-boot jpa


    【解决方案1】:

    发生这种情况是因为您在 PostgreSQL 表中创建了 boolean 类型的列。在 MySQL 中,布尔值表示为整数值(通常为 bit,以节省空间),并且在 PostgreSQL 中没有隐式转换:

    psql (12.4)
    Type "help" for help.
    
    postgres=# select true = 1;
    ERROR:  operator does not exist: boolean = integer
    LINE 1: select true = 1;
                        ^
    HINT:  No operator matches the given name and argument types. You might need to add explicit type casts.
    postgres=# 
    

    您可以编写一个将位转换为布尔值的函数(反之亦然),然后创建一个隐式转换:

    -- you'll need to write your own `bit_to_boolean()` function
    CREATE CAST (BIT AS BOOLEAN)
      WITH FUNCTION bit_to_boolean(BIT)
      AS IMPLICIT;
    

    这可能工作量太大了。您最好在 Java 中将 int 转换为 String,然后以这种方式进行比较;

    postgres=# select true = 1;
    ERROR:  operator does not exist: boolean = integer
    LINE 1: select true = 1;
                        ^
    HINT:  No operator matches the given name and argument types. You might need to add explicit type casts.
    postgres=# select true = '1';
     ?column? 
    ----------
     t
    (1 row)
    
    postgres=# select true = 't';
     ?column? 
    ----------
     t
    (1 row)
    
    postgres=# select true = 'f';
     ?column? 
    ----------
     f
    (1 row)
    
    postgres=# select true = '0';
     ?column? 
    ----------
     f
    (1 row)
    

    另一种可能解决您看到的问题的方法是编辑您的 Java 代码以比较真/假关键字而不是整数:

    -- do this
    SELECT * FROM table WHERE bool_col = <true/false>;
    
    -- instead of this
    SELECT * FROM table WHERE bool_col = <val>;
    

    【讨论】:

      【解决方案2】:

      布尔类型检查因数据库而异(即从 mysql 到 postgres)。考虑下面我所经历的例子。 基础实体类 BaseEnity {} 有一个 active 布尔类型的列,Order {} 实体类扩展了该类。要选择所有活动订单,mysql 查询是:

      select * from Order where active = 1
      

      但是当将数据库迁移到 postgres 时它不起作用。在 postgres 中,它显示错误 operator does not exist: boolean = integer。正如 postgres 所期望的那样:

      select * from Order where active = true
      

      由于 postgres 需要布尔值 true/false,但在 SQL 查询中,该值被设置为整数类型 1,我们遇到了提示错误。

      【讨论】:

        【解决方案3】:

        这个怎么样?

        CREATE OR REPLACE FUNCTION equal_int_bool(x int, y bool) 
        RETURNS BOOLEAN AS $$ 
        begin
            return x = y::int;
        end;
        $$ LANGUAGE PLPGSQL IMMUTABLE STRICT;
        
        CREATE OPERATOR = ( 
          leftarg = INTEGER, 
          rightarg = BOOLEAN,
          procedure = equal_int_bool);
        
        CREATE OR REPLACE FUNCTION equal_bool_int(x bool, y int) 
        RETURNS BOOLEAN AS $$ 
        begin
            return x::int = y;
        end;
        $$ LANGUAGE PLPGSQL IMMUTABLE STRICT;
        
        CREATE OPERATOR = ( 
          leftarg = BOOLEAN, 
          rightarg = INTEGER,
          procedure = equal_bool_int);
        

        例如事实:

        > select 0=false a, false=0 b, 1=true c, true=1 d;
         a | b | c | d
        ---+---+---+---
         t | t | t | t
        

        所有其他比较都期望为 false:

         > select 1=false a, 0=true b, 2=true c, -1=true d, true=-1 e;
         a | b | c | d | e
        ---+---+---+---+---
         f | f | f | f | f
        

        注意:我是 Postgresql 的相对新手,我不建议您在数据库中创建大量随机隐式转换,但我认为这是可能的,这很有趣。随时警告危险。

        附:我正在考虑是否更好的语义是 0=false,非零=true。取决于您的用例。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-01-20
          • 1970-01-01
          • 2021-02-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多