请查看此数据库架构:
create table Person (id int not null identity,
[index] varchar(30),
datecreated datetime,
groupid int)
create table [Group] (id int identity not null, description varchar(30))
示例数据:
insert into Person ([index],datecreated,groupid) values ('4,5,6','2011-01-01',1)
insert into Person ([index],datecreated,groupid) values ('1,2,3','2011-02-02',1)
insert into Person ([index],datecreated,groupid) values ('7,8','2012-02-02',2)
insert into [Group] (description) values ('TestGroup')
insert into [Group] (description) values ('TestGroup2')
请查看下面的SQL语句:
select *
from Person
inner join [Group] on Person.groupid = [group].id
where [group].description = 'TestGroup'
order by
left(substring([index], charindex(',', [index]) + 1, 200),
charindex(',', substring([index], charindex(',', [index]) + 1, 200)) - 1)
此SQL语句失败,并显示以下错误:
传递给SUBSTRING函数的长度参数无效。
导致此错误的是order by
子句,即它正在尝试查找索引列的第三个元素,但第3行不存在于第3行(只有两个元素)。
但是,我希望[group].description = 'TestGroup'
能够过滤掉记录三。情况似乎并非如此。就好像在order by
子句之前运行where
子句一样。如果从查询中排除order by
子句,则查询将运行。
这是为什么?
答案 0 :(得分:0)
SQL中的评估顺序保证很弱。可能首先执行排序,然后执行流聚合。这本身就没有错。
一般情况下,您不能依赖执行顺序。除了case-expression之外,如果NULL
的输入无效,您可以使用它来创建订单中SUBSTRING
之类的虚拟值。 案例是执行评估订单的唯一方法。
答案 1 :(得分:0)
这个ORDER BY非常残酷。我建议使用临时表或表子表达式将其分解为几个查询,这样您就可以先进行过滤,和/或创建一个包含待排序数据的列。
答案 2 :(得分:0)
请记住,SQL是一种声明性语言,而不是一种过程语言。也就是说,您描述了所需的结果集。您依赖于SQL编译器/优化器来设置执行计划。
通常,SQL引擎将有一个组件从表中读取数据并执行该数据所需的所有计算。当然,这包括SELECT子句中的计算,还包括“ON”子句,“WHERE”子句和“ORDER BY”子句中的计算。
然后引擎可以在读取数据后进行过滤。这使得引擎可以轻松地使用计算值进行过滤。
我不是说所有数据库都以这种方式工作。我所说的是,不能保证SQL语句中的操作顺序。这种情况是以错误的顺序执行操作导致错误的情况之一,这会阻止SQL完成。您是否希望帮助重写查询,以便它不会收到错误?