本文为您介绍如何修改不兼容SQL。

背景信息

MaxCompute 2.0完全拥抱开源生态,支持更多的语言功能,拥有更快的运行速度。但是MaxCompute 2.0会执行更严格的语法检测,一些在旧版本编译器下正常执行的不严谨的语法在MaxCompute 2.0下执行会报错。

为了使MaxCompute 2.0灰度升级更加平滑,MaxCompute框架支持回退机制,如果MaxCompute 2.0作业失败,会回退到MaxCompute 1.0执行。回退本身会增加作业时延。建议您在提交作业之前,手动关闭回退开关set odps.sql.planner.mode=lot;,以避免MaxCompute框架回退策略修改造成的影响。

根据线上回退情况,MaxCompute会通过邮件、钉钉通知问题作业的责任人尽快完成SQL作业的修改,否则会导致作业失败。

group.by.with.star

说明:即select * …group by…语句。
  • MaxCompute 2.0版本中,要求Group By列表是源表中所有的列,否则执行报错。
  • 旧版MaxCompute中,即使Group By列表不覆盖源表中所有的列,也支持select * from group by key语法。
示例
  • 场景1:Group By Key中不包含所有列。
    • 错误写法
      select * from t group by key;
    • 报错信息
      FAILED: ODPS-0130071:[1,8] Semantic analysis exception - column reference t.value should appear in GROUP BY key
    • 正确写法
      select distinct key from t;
  • 场景2:group by key包含所有列。
    • 如下写法不推荐。
      select * from t group by key, value; -- t has columns key and value
    • 虽然MaxCompute2.0不会报错,但推荐改为如下。
      select distinct key, value from t;

bad.escape

说明:错误的escape序列问题。

按照MaxCompute规定,在String literal中应该用反斜线加三位8进制数字表示从0到127的ASCII字符。例如:使用“\001”、“\002”表示0、1。但\01、\0001也被当作\001处理了。

这种方式会给新用户带来困扰,比如需要用“\0001”表示“\000”+“1”,便没有办法实现。同时对于从其他系统迁移而来的用户而言,会导致正确性错误。
说明 \000后面再加数字,如\0001 - \0009\00001的写法可能会返回错误。
MaxCompute 2.0会解决此问题,对脚本中错误的序列进行修改。
  • 错误写法
    select split(key, "\01"), value like "\0001" from t;
  • 报错信息
    FAILED: ODPS-0130161:[1,19] Parse exception - unexpected escape sequence: 01
    ODPS-0130161:[1,38] Parse exception - unexpected escape sequence: 0001
  • 正确改法
    select split(key, "\001"), value like "\001" from t;

column.repeated.in.creation

说明:如果创建表时列名重复,MaxCompute 2.0将会报错。

示例
  • 错误写法
    create table t (a BIGINT, b BIGINT, a BIGINT);
  • 报错信息
    FAILED: ODPS-0130071:[1,37] Semantic analysis exception - column repeated in creation: a
  • 正确写法
    create table t (a BIGINT, b BIGINT);

string.join.double

说明:写JOIN条件时,等号的左右两边分别是STRING和DOUBLE类型。
  • 旧版MaxCompute会把两边都转成BIGINT类型,会导致严重的精度损失问题,例如:1.1=“1”在连接条件中会被认为是相等的。
  • MaxCompute 2.0会与Hive兼容转为DOUBLE类型。
示例
  • 不推荐写法
    select * from t1 join t2 on t1.double_value = t2.string_value;
  • Warning信息
    WARNING:[1,48]  implicit conversion from STRING to DOUBLE, potential data loss, use CAST function to suppress
  • 推荐改法
    select * from t1 join t2 on t.double_value = cast(t2.string_value as double);

window.ref.prev.window.alias

说明:Window Function引用同级select List中的其他Window Function Alias的问题。

示例
  • 如果rn在t1中不存在,错误写法如下。
    select row_number() over (partition by c1 order by c1) rn,
    row_number() over (partition by c1 order by rn) rn2
    from t1;
  • 报错信息
    FAILED: ODPS-0130071:[2,45] Semantic analysis exception - column rn cannot be resolved
  • 正确改法
    select row_number() over (partition by c1 order by rn) rn2
    from
    (select c1, row_number() over (partition by c1 order by c1) rn
    from t1
    ) tmp;

select.invalid.token.after.star

说明:select列表里面允许用户使用星号(*)代表选择某张表的全部列,但星号(*)后面不允许加alias,即使星号(*)展开之后只有一列也不允许,新一代编译器将会对类似语法进行报错。

示例
  • 错误写法
    select * as alias from table_test;
  • 报错信息
    FAILED: ODPS-0130161:[1,10] Parse exception - invalid token 'as'
  • 正确改法