Por que a seleção de colunas especificadas e tudo está errado no Oracle SQL?
-
22-09-2019 - |
Pergunta
Diga que tenho uma declaração selecionada que vai ..
select * from animals
Isso fornece resultado de consulta AA de todas as colunas da tabela.
Agora, se a 42ª coluna da tabela animals
é is_parent
, e eu quero devolver isso nos meus resultados, logo depois gender
, para que eu possa ver isso mais facilmente. Mas eu também quero todas as outras colunas.
select is_parent, * from animals
Isso retorna ORA-00936: missing expression
.
A mesma afirmação funcionará bem em Sybase, e eu sei que você precisa adicionar um alias de tabela ao animals
Tabela para fazer funcionar ( select is_parent, a.* from animals ani
), mas Por quê O Oracle deve precisar de um apelido de tabela para poder descobrir a seleção?
Solução
Na verdade, é fácil resolver o problema original. Você só precisa qualificar o *.
select is_parent, animals.* from animals;
deve funcionar bem. Aliases para os nomes de tabela também funcionam.
Outras dicas
Não há mérito em fazer isso no código de produção. Deveríamos nomear explicitamente as colunas que queremos, em vez de usar o construto selecionado *.
Quanto à consulta ad hoc, obtenha um desenvolvedor IDE - SQL, Toad, PL/SQL Developer, etc - que nos permite manipular consultas e conjuntos de resultados sem precisar de extensões para o SQL.
Boa pergunta, eu sempre me perguntei isso, mas então aceitei como uma dessas coisas ...
Problema semelhante é o seguinte:
sql>select geometrie.SDO_GTYPE from ngg_basiscomponent
ORA-00904: "GEOMETRIE"."SDO_GTYPE": invalid identifier
onde geometrie é uma coluna do tipo mdsys.sdo_geometry.
Adicione um pseudônimo e a coisa funciona.
sql>select a.geometrie.SDO_GTYPE from ngg_basiscomponent a;
Muitas boas respostas até agora sobre o porquê select *
Não deve ser usado e todos eles estão perfeitamente corretos. No entanto, não pense que nenhum deles responda à pergunta original sobre por que a sintaxe específica falha.
Infelizmente, acho que o motivo é ... "porque não".
Eu não acho que tenha nada a ver com consultas de mesa única vs. multi-tabela:
Isso funciona bem:
select *
from
person p inner join user u on u.person_id = p.person_id
Mas isso falha:
select p.person_id, *
from
person p inner join user u on u.person_id = p.person_id
Enquanto isso funciona:
select p.person_id, p.*, u.*
from
person p inner join user u on u.person_id = p.person_id
Pode ser uma coisa de compatibilidade histórica com o código legado de 20 anos.
Outro para o "Compre por que !!!" balde, junto com Por que você não pode agrupar por um pseudônimo?
O caso de uso para o alias.* O formato é o seguinte
select parent.*, child.col
from parent join child on parent.parent_id = child.parent_id
Ou seja, selecionando todas as colunas de uma tabela em uma junção, mais (opcionalmente) uma ou mais colunas de outras tabelas.
O fato de você poder usá-lo para selecionar a mesma coluna duas vezes é apenas um efeito colateral. Não há nenhum ponto real para selecionar a mesma coluna duas vezes e não acho que a preguiça seja uma justificativa real.
Select *
No mundo real, só é perigoso quando se refere às colunas pelo número de índice após a recuperação, e não pelo nome, o maior problema é a ineficiência quando nem todas as colunas são necessárias no ResultSet (tráfego de rede, CPU e carga de memória). É claro que se você estiver adicionando colunas de outras tabelas (como é o caso neste exemplo, pode ser perigoso, pois essas tabelas podem ter colunas com nomes correspondentes, select *, x
Nesse caso, falharia se uma coluna X fosse adicionada à tabela que anteriormente não a tinha.
Por quê O Oracle precisa de um alias de tabela para poder descobrir a seleção
Teradata está exigindo o mesmo. Como ambos são bastante antigos (talvez melhor chame maduro :-) DBMSES Isso pode ser razões históricas.
Minha explicação usual é: um não qualificado *
significa tudo/todas as colunas e o analisador/otimizador está simplesmente confuso porque você solicita mais que tudo.