SQL中*是否有等价别名?如何不使用*实现全表数据查询?
SQL中*的等价别名说明
不管是标准SQL还是MySQL,都没有给*提供官方的等价别名,所有能实现返回全部列效果的写法,本质要么是*的变体用法,要么是对全字段查询逻辑的封装,不存在可以直接替换*字符、语义完全等价的其他短关键字。
很多人提到的表别名.*属于*的扩展用法,不是独立别名,如果你做字符级的*检测,这种写法本身就带*,本身就在命中范围内,不算绕开的方案。
MySQL中替代*的常用语法
- 显式枚举全字段名:这是生产环境最推荐的无
*写法,比如表user包含id、username、age、create_time四个字段,直接写SELECT id, username, age, create_time FROM user;即可,完全不涉及*,还能避免表结构变动带来的字段顺序错乱、冗余字段返回拖慢查询的问题。 - 动态生成字段列表:借助
information_schema系统表先查表结构拿到所有字段名,再拼接成完整的查询语句执行,全程不需要手写*。比如要查目标库下user表的全字段,先执行查询拿字段列表:SELECT GROUP_CONCAT(COLUMN_NAME SEPARATOR ', ') FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '当前业务库名' AND TABLE_NAME = 'user';
把查询返回的逗号分隔字段串拼到SELECT后面,就能得到不带*的全字段查询语句。 - 存储过程封装:把上面动态拼接字段的逻辑写到存储过程里,后续查询只需要传入库名、表名调用存储过程即可,调用语句里不会出现
*。
不使用
SELECT * FROM查询全量内容的实现方案 核心思路都是绕开直接写*的环节,本质还是返回全表所有行和列:
- 系统表动态拼接字段方案:执行的最终查询语句里只有显式列出的字段名,没有
*,也没有SELECT * FROM的连续片段,完全可以返回全量数据,这也是绝大多数ORM框架默认规避SELECT *的底层实现逻辑。 - 多表查询场景下指定单表全字段的变体:比如写
SELECT u.* FROM user u LEFT JOIN order o ON u.id = o.user_id;,这里没有连续的SELECT * FROM片段,但还是用到了*字符,如果你的检测规则是硬匹配SELECT * FROM字符串,这种写法会直接漏过,但如果是检测所有*字符,还是会被命中。 - 不存在所谓“隐藏关键字”可以直接无
*返回全表数据,网上提到的各类绕过方案要么是用注释拆分关键字(比如SELECT/*comment*/ * FROM、SEL/**/ECT * FR/**/OM),要么是用编码拼接关键字,本质还是SELECT *的变形,不是新的等价语法。
提醒:单纯靠检测
*字符或者匹配SELECT * FROM字符串做SQL安全防护的漏洞非常多,攻击者很容易通过注释、编码、动态SQL、存储过程等方式绕过,不能把这个规则作为唯一的防护手段,必须配合预编译语句、SQL语法树解析、数据库账号权限最小化等机制一起做防护。
内容的提问来源于stack exchange,提问作者Efried
相关产品推荐
相关产品推荐

