1

请查看此数据库架构:

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 行(只有两个元素)。

但是,我希望[group].description = 'TestGroup'过滤掉记录三。情况似乎并非如此。就好像该order by子句在该子句之前运行where。如果order by从查询中排除子句,则查询运行。

为什么是这样?

4

3 回答 3

0

SQL 中的求值顺序有很弱的保证。可能首先执行排序,然后执行流聚合。这本身并没有错。

一般来说,您不能依赖执行顺序。除非在 case 表达式中,您可以使用它来创建一个虚拟值,就像NULL您的订单一样,如果输入为SUBSTRING无效。案例是执行评估顺序的唯一方法。

于 2012-05-23T17:11:47.550 回答
0

这个 ORDER BY 是相当残酷的。我建议使用临时表或表子表达式将其分解为几个查询,这样您就可以先进行过滤,和/或创建一个包含要排序的数据的列。

于 2012-05-23T17:25:48.847 回答
0

请记住,SQL 是一种声明性语言,而不是一种过程性语言。也就是说,您描述了您想要的结果集。您依赖 SQL 编译器/优化器来设置执行计划。

非常典型地,SQL 引擎将有一个组件从表中读取数据并执行该数据所需的所有计算。当然,这包括 SELECT 子句中的计算,还包括“ON”子句、“WHERE”子句和“ORDER BY”子句中的计算。

然后引擎可以在读取数据后进行过滤。这使引擎能够轻松地使用计算值进行过滤。

我并不是说所有数据库都以这种方式工作。我要说的是,不能保证 SQL 语句中的操作顺序。这种情况是按错误顺序执行操作导致错误的情况之一,这会阻止 SQL 完成。您是否需要帮助重写查询以使其不会出现错误?

于 2012-05-23T17:45:11.217 回答