在SQL Server 2005中"select*from table"vs"select colA,colB,etc from table"

kri*_*tof 14 sql t-sql sql-server sql-server-2005 views

为一篇冗长的帖子道歉,但我需要发布一些代码来说明问题.

灵感来自问题*什么是不使用选择的原因,我决定指出一些我之前注意到的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
Run Code Online (Sandbox Code Playgroud)

如果执行以下查询并查看最后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
Run Code Online (Sandbox Code Playgroud)

正如您在dbo.vStartest选择a,b,c的结果中所看到的,列c的数据已被colum d中的数据替换.

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

我想我会发布它作为警告,让人们在SQL中使用select*并遇到意外行为.

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

gbn*_*gbn 16

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

如果未使用SCHEMABINDING子句创建视图,则应在对视图下方影响视图定义的对象进行更改时运行sp_refreshview.否则,查询时视图可能会产生意外结果.