“select * from table”vs“select colA,colB,etc. from table”SQL Server 2005中有趣的行为

道歉一个冗长的职位,但我需要张贴一些代码来说明问题。

受问题启发* 不使用select的原因是什么 ,我决定指出一些我之前注意到的select *行为的一些观察。

所以让我们的代码自己说话:

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[starTest]') AND type in (N'U')) DROP TABLE [dbo].[starTest] CREATE TABLE [dbo].[starTest]( [id] [int] IDENTITY(1,1) NOT NULL, [A] [varchar](50) NULL, [B] [varchar](50) NULL, [C] [varchar](50) NULL ) ON [PRIMARY] GO insert into dbo.starTest(a,b,c) select 'a1','b1','c1' union all select 'a2','b2','c2' union all select 'a3','b3','c3' go IF EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[vStartest]')) DROP VIEW [dbo].[vStartest] go create view dbo.vStartest as select * from dbo.starTest go go IF EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[vExplicittest]')) DROP VIEW [dbo].[vExplicittest] go create view dbo.[vExplicittest] as select a,b,c from dbo.starTest go select a,b,c from dbo.vStartest select a,b,c from dbo.vExplicitTest IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[starTest]') AND type in (N'U')) DROP TABLE [dbo].[starTest] CREATE TABLE [dbo].[starTest]( [id] [int] IDENTITY(1,1) NOT NULL, [A] [varchar](50) NULL, [B] [varchar](50) NULL, [D] [varchar](50) NULL, [C] [varchar](50) NULL ) ON [PRIMARY] GO insert into dbo.starTest(a,b,d,c) select 'a1','b1','d1','c1' union all select 'a2','b2','d2','c2' union all select 'a3','b3','d3','c3' select a,b,c from dbo.vExplicittest select a,b,c from dbo.vStartest 

如果执行以下查询并查看最后2个select语句的结果,则您将看到的结果如下所示:

 select a,b,c from dbo.vExplicittest a1 b1 c1 a2 b2 c2 a3 b3 c3 select a,b,c from dbo.vStartest a1 b1 d1 a2 b2 d2 a3 b3 d3 

正如您在dbo.vStartestselecta,b,c的结果中所看到的那样,列c的数据已被列d的数据replace。

我相信这与视图的编译方式有关,我的理解是列是由列索引(1,2,3,4)映射的,而不是名称。

我以为我会把它作为一个警告,在他们的SQL中使用select *,并遇到意想不到的行为。

注意:如果重build每次修改表后使用select *的视图,它将按预期工作。

sp_refreshview来修复视图,或者在视图定义中使用WITH SCHEMABINDING

如果未使用SCHEMABINDING子句创build视图,则应对更改影响视图底层的对象时运行sp_refreshview,以影响视图的定义。 否则,查询时查看可能会产生意想不到的结果。

这在任何 RDBMS下都是非常标准的行为,不仅仅是MSSQL,而且包含“select * from”的视图的使用必须谨慎对待。

SQL引擎将编译每个视图 – 这基本上是词典/parsing步骤并存储结果。 如果您因此更改了基础表,则总是需要显式重新编译,除非数据库有一些标记视图的方法来在这种情况下进行检查。

这个问题也可能(也)也适用于存储过程和类似的数据库对象。