在观看troy hunt关于sqli的精彩课程时,我注意到他最终使用了以下策略来查看表是否有特定的列:
select * from TableA order by (select top 1 some_column from TableB) desc
这个表达式将由SQLServer执行,但是它将对ORDERBY子句做什么呢?我见过表达式与order by before(case-when-then-else-end)一起使用,但我很想了解sql如何处理前面的查询而不出现任何错误。。。
编辑:提供更多信息,因为我最初的帖子似乎不够清晰:
我知道这不是获取表名或列名的最佳策略,尽管sqli(这不是我要问的)
我不想知道如何防范这种情况(我已经知道怎么做了)
我知道按常量值排序没有意义(尽管它允许您运行这些类型的“布尔查询”)
我真正想知道的是它为什么起作用。
所以,回到医生那里 order by
子句需要order\ by\表达式,该表达式描述为:
指定要对查询结果集进行排序的列或表达式。排序列可以指定为名称或列别名,也可以指定为表示列在选择列表中位置的非负整数。
根据文档,一个表达式是:
是符号和运算符的组合,sql server数据库引擎对其求值以获得单个数据值。简单表达式可以是单个常量、变量、列或标量函数。运算符可用于将两个或多个简单表达式联接为复杂表达式。
正如@smor所演示的,如果用简单的 select 'A'
:
select * from TableA order by (select 'A') desc
但这不起作用:
select * from TableA order by 'A' desc
所以,问题是:为什么 select 'A'
在order by子句中被sql server接受?它不也产生一个常数吗?因为常数是一个表达式,并且考虑到 order by
子句,它不应该在这两种情况下都抛出错误吗?
谢谢。
1条答案
按热度按时间cunj1qz11#
使用
(select top 1 some_column from TableB)
是标量子查询的示例。这是一个子查询,只返回一列,最多返回一行。它可以在任何可以使用文本值的地方使用——也许在其他一些地方也可以。显然,它可以用在order by
,即使sql server不允许order by
.最常见的标量子查询类型是相关子查询,它具有
where
连接子查询和外部查询的子句。这不是标量子查询的示例。事实上,就我所知,这并不是一个有用的例子。它有一个主要缺点,那就是使用
top
没有order by
. 子查询返回的值不确定。这似乎是一个糟糕的做法,尤其是当你试图教人们sql时。而且,它可能会被评估一次。因此子查询将返回一个常量值,对有意义的排序没有多大贡献。