日期:2014-05-16  浏览次数:20827 次

关于SQL的执行顺序问题,求指点
我的数据库中有一个表 两个字段
CREATE TABLE [dbo].[Test](
[ID] [int] NOT NULL,
[Time] [varchar](50) NOT NULL

测试数据:
INSERT [dbo].[Test] ([ID], [Time]) VALUES (1, N'标题11')
INSERT [dbo].[Test] ([ID], [Time]) VALUES (2, N'标题22')
INSERT [dbo].[Test] ([ID], [Time]) VALUES (3, N'标题33')
INSERT [dbo].[Test] ([ID], [Time]) VALUES (4, N'2014-02-25 15:40:32')
INSERT [dbo].[Test] ([ID], [Time]) VALUES (5, N'2014-02-25 15:40:49')
INSERT [dbo].[Test] ([ID], [Time]) VALUES (6, N'2014-02-25 15:40:56')

我的查询语句:
SELECT ID,TIMES 
FROM (SELECT ID,TIME FROM Test 
WHERE ISDATE(Time)=1) AS T(ID,TIMES)
WHERE DATEDIFF(YYYY, convert(date,TIMES), GETDATE()) = 0 

我将FROM后的子查询放在临时表中,select临时表where datediff(..)没有问题
但整个语句执行的时候就会报错:

消息 241,级别 16,状态 1,第 1 行
从字符串转换日期和/或时间时,转换失败。


我查了一下SQL的执行顺序,先执行的FROM,然后执行where,既然我的FROM已经将非日期的数据过滤掉了,在WHERE的时候判断为什么还会报转换失败的错误,求大侠指点迷津..
------解决方案--------------------
修改成这样试试:
--drop table test

CREATE TABLE [dbo].[Test](
[ID] [int] NOT NULL,
[Time] [varchar](50) NOT NULL


INSERT [dbo].[Test] ([ID], [Time]) VALUES (1, N'标题11')
INSERT [dbo].[Test] ([ID], [Time]) VALUES (2, N'标题22')
INSERT [dbo].[Test] ([ID], [Time]) VALUES (3, N'标题33')
INSERT [dbo].[Test] ([ID], [Time]) VALUES (4, N'2014-02-25 15:40:32')
INSERT [dbo].[Test] ([ID], [Time]) VALUES (5, N'2014-02-25 15:40:49')
INSERT [dbo].[Test] ([ID], [Time]) VALUES (6, N'2014-02-25 15:40:56')
go


SELECT ID,TIMES 
FROM (SELECT ID,TIME FROM Test 
WHERE ISDATE(Time)=1) AS T(ID,TIMES)
WHERE left(TIMES,4)= DATENAME(YYYY,GETDATE()) 
/*
ID TIMES
4 2014-02-25 15:40:32
5 2014-02-25 15:40:49
6 2014-02-25 15:40:56
*/

------解决方案--------------------
SQL 的语法并不按照语法顺序执行

SQL 语句有一个让大部分人都感到困惑的特性,就是:SQL 语句的执行顺序跟其语句的语法顺序并不一致。SQL 语句的语法顺序是:

SELECT[DISTINCT]
FROM
WHERE
GROUP BY
HAVING
UNION
ORDER BY
为了方便理解,上面并没有把所有的 SQL 语法结构都列出来,但是已经足以说明 SQL 语句的语法顺序和其执行顺序完全不一样,就以上述语句为例,其执行顺序为:

FROM
WHERE
GROUP BY
HAVING
SELECT
DISTINCT
UNION
ORDER BY
关于 SQL 语句的执行顺序,有三个值得我们注意的地方:

1、 FROM 才是 SQL 语句执行的第一步,并非 SELECT 。数据库在执行 SQL 语句的第一步是将数据从硬盘加载到数据缓冲区中,以便对这些数据进行操作。(译者注:原文为“The first thing that happens is loading data from the disk into memory, in order to operate on such data.”,但是并非如此,以 Oracle 等常用数据库为例,数据是从硬盘中抽取到数据缓冲区中进行操作。)

2、 SELECT 是在大部分语句执行了之后才执行的,严格的说是在 FROM 和 GROUP BY 之后执行的。理解这一点是非常重要的,这就是你不能在 WHERE 中使用在 SELECT 中设定别名的字段作为判断条件的原因。

1
2
3
SELECT A.x + A.y AS z
FROM A
WHERE z = 10 --