2008-11-26 108 views
14

對於冗長的帖子,道歉但我需要張貼一些代碼來說明問題。「select * from table」vs「select colA,colB,etc. from table」SQL Server 2005中有趣的行爲

受問題* What is the reason not to use 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 

正如你可以在的結果中看到的選擇列c的數據已經被替換爲從科拉姆d中的數據A,b,從dbo.vStartest℃。

我認爲這與視圖的編譯方式有關,我的理解是列是由列索引(1,2,3,4)映射的,而不是名稱。

我以爲我會發布它作爲警告人們在他們的SQL中使用select *並且遇到意外的行爲。

注意:如果重建每次修改表後使用select *的視圖,它將按預期工作。

+1

我不明白,示例代碼中的任何地方都沒有D列。 – Hogan 2010-01-22 14:02:02

+1

@Hogan你需要向下滾動代碼示例,表starTest被刪除並重新創建,這次有4列:A,B,D,C – kristof 2010-01-25 17:03:26

回答

15

sp_refreshview固定視圖,或在視圖定義

如果視圖是不與 SCHEMABINDING子句創建WITH SCHEMABINDING使用,sp_refreshview 應更改時 的基礎的對象進行運行認爲 影響視圖的定義。 否則,查詢時查看可能會產生意想不到的結果 。

2

下意見非常標準的行爲有任何 RDBMS,不僅僅是MSSQL,爲什麼的意見,包括使用「選擇*」的原因,必須謹慎對待。

SQL引擎將編譯每個視圖 - 這基本上是詞典/解析步驟並存儲結果。如果您因此更改了基礎表,則總是需要顯式重新編譯,除非數據庫有一些標記視圖的方法以便在這種情況下進行檢查。

問題可能(也)也適用於存儲過程和類似的數據庫對象。

相關問題