关于预处理语句不设置别名的列的最大数量

【 TiDB 版本】6.5

在使用mybatis时,部分 xml mapper 中的参数未指定列别名,导致出现 Duplicate column name "NULL" 错误,因为发现了 tidb 和 mysql 行为上的区别,希望了解两数据库相关的限制,不知在不为列添加别名的条件下,是否有可能绕过该错误

mysql 不允许 prepare 以下语句,但 tidb 允许

prepare stmt from
    '
    select tmp.*
    from (
        select ?, ?
        from dual
        ) tmp
    ';

但同时,tidb 又不允许 prepare 以下语句,或者使用超过两个的 ? 占位符

# 相较第一个仅去掉 from dual,并且如果 from dual 不换行写的话也无法 prepare
prepare stmt from
    '
    select tmp.*
    from (
        select ?, ?
        ) tmp
    ';

# 声名了三个无别名的占位符
prepare stmt from
    '
    select tmp.*
    from (
        select ?, ?, ?
        ) tmp
    ';

两数据库报错时均返回信息 Duplicate column name ‘?’

原先使用 oracle 中,因为预处理语句的 bind 是通过 :n 占位符提供的,似乎并不受 不为参数设置别名 这一行为限制,以下预处理语句可以正常编译和执行

declare
    sql_stmt varchar2(200);
begin
    sql_stmt := '
    select tmp.*
    from (
        select :1, :2, :3
        from dual
        ) tmp
    ';
    execute immediate sql_stmt using 'value1', 'value2';
end;

mysql支持PREPARE语句啊,也支持多个占位符 PREPARE stmt FROM ‘SELECT * FROM tt WHERE id = ? AND name = ?’;

老哥你仔细看下问题。。或者试一下那个 sql

明白你的意思了,就是mysql和tidb在使用prepare语法时对于dual虚拟表上的使用有区别,mysql给dual表的每个占位符列起的别名是一样的,而tidb应该是和oracle类似,给dual表的每个占位符列起的别名是不一样的,所以
PREPARE stmt FROM

select tmp.*
from (
select ?, ?
from dual
) tmp
';
在tidb和oracle可以执行,但是mysql不行。
prepare stmt from

select tmp.*
from (
select ?, ?
) tmp
';
在tidb和mysql都不行。

这个应该是tidb对于dual虚拟表上应该做了二次开发

1 个赞

可是如果三个占位符的话,tidb 就也不行了… 另外原来 select 1;select 1 from dual; 在 mysql 中实际是不同的?我之前以为前者是简略写法