Pergunta

Por que está usando '*' para construir um mau ponto de vista?

Suponha que você tenha se juntar a um complexo e todos os campos podem estar em algum lugar usado.

Então você só tem que escolher campos necessários.

SELECT field1, field2 FROM aview WHERE ...

O "aview" visão poderia ser SELECT table1.*, table2.* ... FROM table1 INNER JOIN table2 ...

Nós temos um problema se 2 campos têm o mesmo nome em tabela1 e tabela2.

É este somente a razão por que usar '*' em uma exibição é ruim?

Com '*', você pode usar a exibição em um contexto diferente, porque a informação está lá.

O que eu estou ausente?

Saudações

Foi útil?

Solução

Eu não acho que há muito em software que é "apenas ruim", mas há uma abundância de coisas que é mal utilizado de maneiras ruins: -)

O exemplo que você dá uma razão pela qual * não poderia lhe dar o que você espera, e eu acho que há outros. Por exemplo, se as tabelas subjacentes mudar, talvez colunas são adicionados ou removidos, uma visão que usos * continuará a ser válido, mas pode quebrar todas as aplicações que utilizam. Se a sua visão tinha chamado as colunas explicitamente, em seguida, havia mais chance de que alguém iria detectar o problema ao fazer a mudança de esquema.

Por outro lado, você pode realmente deseja a sua opinião sobre blithely aceitar todas as alterações às tabelas subjacentes, caso em que a * faria ser apenas o que você quer.

Atualização: Eu não sei se o OP teve um fornecedor de banco de dados específico em mente, mas agora está claro que o meu último comentário não é verdadeiro para todos os tipos. Estou em dívida com user12861 e Jonny Leeds para apontar isto, e triste, isso é levado ao longo de 6 anos para eu editar minha resposta.

Outras dicas

Embora muitos dos comentários aqui são muito bons e referência um problema comum de usar curingas em consultas, tais como causando erros ou resultados diferentes se a mudança tabelas subjacentes, outra questão que não foi coberta é otimização. Uma consulta que puxa todas as colunas de uma tabela tende a não ser tão eficiente quanto uma consulta que puxa apenas as colunas que você realmente precisa. Concedido, há aqueles momentos em que você precisa de cada coluna e é um PIA importante ter que fazer referência a todos, especialmente em uma grande mesa, mas se você só precisa de um subconjunto, por atolar sua consulta com mais colunas do que você precisa.

Outra razão pela qual "*" é arriscado, não só nas vistas, mas em consultas, é que as colunas pode alterar o nome ou mudar de posição nas tabelas subjacentes. Através de um meio curinga que a sua visão acomoda tais mudanças facilmente sem a necessidade de ser mudado. Mas se suas referências de aplicação colunas por posição no conjunto de resultados, ou se você usar uma linguagem dinâmica que retorna conjuntos de resultados digitados pelo nome da coluna, você pode ter problemas que são difíceis de depuração.

I evitar o uso do curinga em todos os momentos. Dessa forma, se uma coluna muda o nome, eu recebo um erro na exibição ou consulta imediatamente, e eu sei onde para corrigi-lo. Se uma coluna muda de posição na tabela subjacente, especificando a ordem das colunas na exibição ou consulta compensa isso.

Estas outras respostas têm bons pontos, mas no servidor SQL, pelo menos, eles também têm alguns pontos erradas. Tente isto:

create table temp (i int, j int)
go
create view vtemp as select * from temp
go
insert temp select 1, 1
go
alter table temp add k int
go
insert temp select 1, 1, 1
go
select * from vtemp

SQL Server não aprender sobre a coluna "novo" quando ele é adicionado. Dependendo do que você deseja que esta poderia ser uma coisa boa ou uma coisa má, mas de qualquer forma ele provavelmente não é bom depender dele. Evitando assim parece apenas como uma boa idéia.

Para mim esse comportamento estranho é a razão mais atraente para evitar select * em vista.

Os comentários me ensinaram que o MySQL tem um comportamento semelhante e Oracle não (ele vai aprender sobre alterações na tabela). Esta inconsistência para mim é mais uma razão para não usar select * em vista.

Usando o '*' para a produção de qualquer coisa é ruim. É ótimo para one-off consultas, mas no código de produção você deve sempre ser tão explícito quanto possível.

Para vistas em particular, se as tabelas subjacentes têm colunas adicionadas ou removidas, a visão será ou errado ou quebrado até que seja recompilado.

Usando SELECT * dentro da visão não incorre em muito de um desempenho sobrecarga se colunas não são usados ??fora da vista - o otimizador irá otimizá-los para fora; SELECT * FROM TheView talvez possa desperdiçar largura de banda, assim como qualquer vez que você puxa mais colunas através de uma conexão de rede.

Na verdade, eu descobri que as opiniões que ligam quase todas as colunas de uma série de grandes tabelas no meu datawarehouse não introduziram quaisquer problemas de desempenho em tudo, mesmo através de relativamente poucas dessas colunas são convidados de fora da vista. As alças Optimizer que bem e é capaz de empurrar os critérios de filtro externos para baixo na vista muito bem.

No entanto, por todas as razões expostas, muito raramente usam SELECT *.

I tem alguns processos de negócios onde um número de CTE são construídos em cima uns dos outros, de forma eficaz a construção de colunas derivados de colunas de derivados de colunas derivadas (que se espera um dia a ser reformulado como os racionaliza negócios e simplifica estes cálculos), e nesse caso, eu preciso de todas as colunas a cair através de cada vez, e eu uso SELECT * -. mas SELECT * não é usado na camada de base, somente no intervalo entre a primeira CTE ea última

A situação no SQL Server é realmente ainda pior do que a resposta por @ user12861 implica: se você usar SELECT * contra várias tabelas, adicionando colunas a uma tabela de referência no início da consulta vai realmente fazer com que a sua visão para retornar os valores da nova colunas sob o disfarce das antigas colunas. Veja o exemplo abaixo:

-- create two tables
CREATE TABLE temp1 (ColumnA INT, ColumnB DATE, ColumnC DECIMAL(2,1))
CREATE TABLE temp2 (ColumnX INT, ColumnY DATE, ColumnZ DECIMAL(2,1))
GO


-- populate with dummy data
INSERT INTO temp1 (ColumnA, ColumnB, ColumnC) VALUES (1, '1/1/1900', 0.5)
INSERT INTO temp2 (ColumnX, ColumnY, ColumnZ) VALUES (1, '1/1/1900', 0.5)
GO


-- create a view with a pair of SELECT * statements
CREATE VIEW vwtemp AS 
SELECT *
FROM temp1 INNER JOIN temp2 ON 1=1
GO


-- SELECT showing the columns properly assigned
SELECT * FROM vwTemp 
GO


-- add a few columns to the first table referenced in the SELECT 
ALTER TABLE temp1 ADD ColumnD varchar(1)
ALTER TABLE temp1 ADD ColumnE varchar(1)
ALTER TABLE temp1 ADD ColumnF varchar(1)
GO


-- populate those columns with dummy data
UPDATE temp1 SET ColumnD = 'D', ColumnE = 'E', ColumnF = 'F'
GO


-- notice that the original columns have the wrong data in them now, causing any datatype-specific queries (e.g., arithmetic, dateadd, etc.) to fail
SELECT *
FROM vwtemp
GO

-- clean up
DROP VIEW vwTemp
DROP TABLE temp2
DROP TABLE temp1

É porque você não precisa sempre de todas as variáveis, e também para se certificar de que você está pensando sobre o que você especificamente precisa.

Não há nenhum ponto que começa todas as senhas com hash do banco de dados durante a criação de uma lista de usuários em seu site, por exemplo, para que um select * seria improdutivo.

Era uma vez, eu criei uma vista contra uma tabela em outro banco de dados (no mesmo servidor) com

Select * From dbname..tablename

Em seguida, um dia, uma coluna foi adicionada à tabela alvejado. A visão começou a retornar resultados totalmente incorretas até que foi reimplantado.


totalmente incorreto:. Nenhuma linha

Este foi no SQL Server 2000.

Eu especulam que isso é por causa de valores syscolumns que a visão havia capturado, embora eu usei *.

Uma consulta SQL é basicamente uma unidade funcional desenhado por um programador para uso em algum contexto. Para a estabilidade a longo prazo e de suporte (possivelmente por alguém que não seja você) tudo em uma unidade funcional deve estar lá para um propósito, e que deve ser razoavelmente evidente (ou documentados) por que está lá -. Especialmente todos os elementos de dados

Se eu fosse para vir ao longo de dois anos a partir de agora com a necessidade ou desejo de alterar a sua consulta, eu esperaria Grokar isso muito cuidadosamente antes de eu seria confiante de que eu poderia mexer com ele. O que significa que seria necessário para entender por que todas as colunas são chamados para fora. (Isto é ainda mais obviamente verdadeiro se você está tentando reutilizar a consulta em mais de um contexto. O que é problemático em geral, por razões semelhantes.) Se eu fosse para ver colunas na saída que eu não poderia se relacionar com algum propósito , eu ter certeza que eu não entendia o que ele fez, e porquê, e que as consequências seriam de mudá-lo.

Em geral, é uma má idéia para uso *. Alguns motores de certificação de código marcar este como um aviso e aconselhá-lo para se referir explicitamente apenas as colunas necessárias. O uso de * pode levar a louses de desempenho que você pode precisar apenas algumas colunas e não todos. Mas, por outro lado, existem alguns casos em que o uso de * é o ideal. Imagine que, não importa o que, usando o exemplo que você forneceu, para este ponto de vista (aview) você sempre precisa de todas as colunas dessas tabelas. No futuro, quando uma coluna é adicionada, você não precisa alterar a vista. Isso pode ser bom ou ruim dependendo o caso, você está lidando.

Eu acho que depende do idioma que você está usando. Eu prefiro usar select * quando o idioma ou driver DB retorna um dicionário (Python, Perl, etc.) ou matriz associativa (PHP) dos resultados. Não faz o seu código muito mais fácil de entender se você está se referindo às colunas por nome em vez de como um índice em uma matriz.

Ninguém mais parece ter mencionado isso, mas dentro do SQL Server também pode configurar o seu ponto de vista com o SCHEMABINDING atributo .

Isso impede que modificações para qualquer uma das tabelas de base (incluindo soltando-os) que poderiam afetar a definição da visão.

Isto pode ser útil para você para algumas situações. Eu percebo que eu não exatamente respondido à sua pergunta, mas pensei que eu gostaria de destacar que, no entanto.

E se você tiver junta usando select * significa automaticamente que você está voltando mais dados do que você precisa que os dados nos campos junção é repetido. Este é um desperdício de recursos de banco de dados e de rede.

Se você é bastante ingênuo vistas uso que chamam outros pontos de vista, usando select * pode torná-los artistas ainda piores (Esta é a técnica que é ruim para o desempenho por conta própria, chamando colunas mulitple você não precisa torna muito pior ).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top