2008-11-26 5 views
14

Apología de un extenso post, pero necesitaba para publicar algo de código para ilustrar el problema."SELECT * FROM tabla" vs "seleccione Cola, colB, etc. de la tabla" comportamiento interesante en SQL Server 2005

Inspirado por la pregunta * What is the reason not to use select ?, decidí señalar algunas observaciones del comportamiento de selección * que noté hace algún tiempo.

así que vamos al código hable por sí mismo:

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 

Si se ejecuta la siguiente consulta y mirar a los resultados de las últimas 2 sentencias de selección, los resultados que se pueden ver será el siguiente:

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 

Como se puede ver en los resultados de seleccionar a, b, c de dbo.vStartest los datos de la columna C se ha reemplazado con los datos de Colum d.

Creo que está relacionado con la forma en que las vistas son compilados, mi entendimiento es que las columnas se asignan por los índices de columna (1,2,3,4) en lugar de nombres.

pensé que iba a publicar como una advertencia para las personas que utilizan select * en su SQL y que experimentan un comportamiento inesperado.

Nota: Si vuelve a generar la vista que utiliza select * cada vez que después de modificar la tabla que va a funcionar como se espera.

+1

No lo entiendo, no hay ninguna columna D en ningún lugar del código de ejemplo. – Hogan

+1

@Hogan tiene que desplazarse hacia abajo en el ejemplo del código, la tabla starTest se colgó y se creó de nuevo, esta vez con 4 columnas: A, B, D, C – kristof

+0

gracias, no sé cómo me lo perdí. – Hogan

Respuesta

15

sp_refreshview para fijar la vista o el uso con SCHEMABINDING en la definición de vista

Si un punto de vista no se crea con la cláusula SCHEMABINDING, sp_refreshview se debe ejecutar cuando se realizan cambios en los objetos subyacentes la vista que afecta la definición de la vista. De lo contrario, la vista puede producir resultados inesperados cuando se consulta.

+0

Yo agregaría, no use SELECT * en el código de producción – kristof

+0

Buen punto. Siempre uso SCHEMABINDING que no permite esto – gbn

2

Este es un comportamiento bastante estándar para las vistas bajo cualquier RDBMS, no sólo MSSQL, y la razón por la cual el uso de puntos de vista que comprenden "SELECT * FROM" debe ser tratado con cautela.

el motor de SQL compilará cada vista - que es básicamente los pasos de análisis/lexicográficos y almacenar el resultado de eso. Si cambia las tablas subyacentes, siempre se requiere una recompilación explícita, a menos que la base de datos tenga algún método de etiquetar la vista para ser verificado en tales circunstancias.

El problema puede (se) se aplican también a los procedimientos almacenados y los objetos demasiado base de datos similar.

Cuestiones relacionadas