SELECCIONAR * EXCEPTO

Há algum RDBMS que implemente algo do género? O que eu estou procurando é obter todos os campos, exceto um campo de texto/BLOB específico, e eu gostaria de apenas selecionar tudo o resto.

Quase todos os dias queixo-me aos meus colegas de trabalho que alguém devia implementar isto... É muito irritante que não exista.

Edit: entendo a preocupação de todos com SELECT *. Conheço os riscos associados a SELECT *. No entanto, isto, pelo menos na minha situação, não seria usado para qualquer código de Nível de produção, ou mesmo código de Nível de desenvolvimento; estritamente para depuração, quando eu preciso ver todos os valores facilmente.

Como já afirmei em alguns dos comentários, onde trabalho é estritamente uma loja de linha de comando, a fazer tudo por cima do ssh. Isso torna difícil o uso de qualquer ferramenta gui (conexões externas à base de dados não são permitidas), etc.

Obrigado pelas sugestões.

 45
sql
Author: Lukasz Szozda, 2009-01-05

14 answers

{[[2]} como outros já disseram, não é uma boa idéia fazer isso em uma consulta porque é propenso a problemas quando alguém muda a estrutura da tabela no futuro. No entanto, há uma forma de o fazer... Não acredito que estou a sugerir isto, mas no espírito de responder à pergunta... Fá-lo com SQL dinâmico... isto faz todas as colunas, exceto a coluna "Descrição". Você pode facilmente transformar isso em uma função ou proc armazenado.
declare @sql varchar(8000),
    @table_id int,
    @col_id int

set @sql = 'select '

select @table_id = id from sysobjects where name = 'MY_Table'

select @col_id = min(colid) from syscolumns where id = @table_id and name <> 'description'
while (@col_id is not null) begin
    select @sql = @sql + name from syscolumns where id = @table_id and colid = @col_id

    select @col_id = min(colid) from syscolumns where id = @table_id and colid > @col_id and name <> 'description'
    if (@col_id is not null) set @sql = @sql + ','
    print @sql
end

set @sql = @sql + ' from MY_table'

exec @sql
 30
Author: Jasmine, 2009-01-05 17:39:08

Crie uma vista na tabela que não inclua as colunas blob

 23
Author: Paul Dixon, 2009-01-05 17:22:16

O DB2 permite isto. As colunas têm um atributo / especificador de Hidden.

Da documentação do syscolumns

Escondido
CHAR (1) NÃO NULO COM O VALOR POR OMISSÃO ' N '
Indica se a coluna está implicitamente escondida:

Parcialmente escondido. A coluna está implicitamente escondida De SELECT *.

Não está escondido. A coluna é visível para todas as declarações SQL.

Criar a documentação da tabela como parte da criação na sua coluna, iria indicar o modificador IMPLICITLY HIDDEN

Um exemplo DDL de colunas implicitamente escondidas segue

CREATE TABLE T1
(C1 SMALLINT NOT NULL,
C2 CHAR(10) IMPLICITLY HIDDEN,
C3 TIMESTAMP)
IN DB.TS;

Se esta capacidade é tão importante para conduzir a adopção do DB2 é deixada como um exercício para futuros leitores.

 9
Author: billinkc, 2013-08-09 21:58:38

Existe algum RDBMS que implemente algo como seleccionar * excepto

Sim! A linguagem verdadeiramente relacional Tutorial D permite que a projeção seja expressa em termos dos atributos a serem removidos em vez dos que devem ser mantidos, por exemplo
my_relvar { ALL BUT description }

De facto, o seu equivalente a SELECT * SQL é { ALL BUT }.

A sua proposta de SQL é meritória, mas ouvi dizer que já foi apresentada ao Comité da norma SQL pelo grupo de utilizadores e rejeitada pelo grupo de utilizadores. grupo do fabricante: (

Também foi pedido explicitamente para o servidor SQL , mas o pedido foi fechado como 'não vai corrigir'.

 5
Author: onedaywhen, 2012-03-06 08:31:53

Há algum RDBMS que implemente algo como seleccionar * excepto?

SIM, o Google Big Query implements selecciona * excepto:

Uma instrução SELECT * EXCEPT especifica os nomes de uma ou mais colunas para excluir do resultado. Todos os nomes das colunas correspondentes são omitidos do resultado.

WITH orders AS(
  SELECT 5 as order_id,
  "sprocket" as item_name,
  200 as quantity
)
SELECT * EXCEPT (order_id)
FROM orders;

Resultado:

+-----------+----------+
| item_name | quantity |
+-----------+----------+
| sprocket  | 200      |
+-----------+----------+
 4
Author: Lukasz Szozda, 2018-04-10 17:52:44

Afasta-te da selecção *, estás a preparar-te para problemas. indique sempre exactamente quais as colunas que deseja. É de fato bastante refrescante que o "recurso" que você está pedindo não existe.

 3
Author: Otávio Décio, 2009-01-05 17:17:49

Eu acredito que a lógica para que não exista é que o autor de uma consulta deve (para o bem do desempenho) apenas pedir o que eles vão olhar/precisar (e, portanto, saber que colunas especificar) -- se alguém adiciona mais algumas bolhas no futuro, você estaria puxando para trás campos potencialmente grandes que você não vai precisar.

 2
Author: Rowland Shaw, 2009-01-05 17:19:10

Sim, finalmente há:) a norma SQL 2016 define funções de tabela polimórficas

O SQL: 2016 introduz funções de tabela polimórficas (PTF) que não precisam especificar o tipo de resultado antecipadamente. Em vez disso, eles podem fornecer um procedimento de componente de descrição que determina o tipo de retorno no tempo de execução. Nem o autor do PTF nem o usuário do PTF precisam declarar as colunas retornadas com antecedência.

Os PTFs descritos pelo SQL: 2016 não são ainda disponível em qualquer banco de dados testado.10 os leitores interessados podem referir-se ao relatório técnico gratuito "Polymorphic table functions in SQL" lançado pela ISO. A seguir, alguns dos exemplos discutidos no relatório:

  • CSVreader, que lê a linha de cabeçalho de um arquivo CVS para determinar o número e os nomes das colunas de retorno

  • Pivot (na verdade, unpivot), que transforma grupos de colunas em linhas (exemplo: fonetype, phonenumber) -- me: acabou-se cordas revestidas de ferro ou aço:)

  • TopNplus, que passa por N linhas por partição e uma linha extra com os totais das restantes linhas


Oracle 18c implementa este mecanismo. 18c Skip_col Polymorphic Table Function Example Oracle Live SQL and Skip_col Polymorphic Table Function Example

Este exemplo mostra como ignorar os dados com base no nome / tipo específico de Dados:

CREATE PACKAGE skip_col_pkg AS  
  -- OVERLOAD 1: Skip by name 
  FUNCTION skip_col(tab TABLE,  col columns)  
           RETURN TABLE PIPELINED ROW POLYMORPHIC USING skip_col_pkg;  

  FUNCTION describe(tab IN OUT dbms_tf.table_t,   
                    col        dbms_tf.columns_t)  
           RETURN dbms_tf.describe_t;  

  -- OVERLOAD 2: Skip by type --  
  FUNCTION skip_col(tab       TABLE,   
                    type_name VARCHAR2,  
                    flip      VARCHAR2 DEFAULT 'False')   
           RETURN TABLE PIPELINED ROW POLYMORPHIC USING skip_col_pkg;  

  FUNCTION describe(tab       IN OUT dbms_tf.table_t,   
                    type_name        VARCHAR2,   
                    flip             VARCHAR2 DEFAULT 'False')   
           RETURN dbms_tf.describe_t;  
END skip_col_pkg;

E corpo:

CREATE PACKAGE BODY skip_col_pkg AS  

/* OVERLOAD 1: Skip by name   
 * NAME:  skip_col_pkg.skip_col   
 * ALIAS: skip_col_by_name  
 *  
 * PARAMETERS:  
 * tab - The input table  
 * col - The name of the columns to drop from the output  
 *  
 * DESCRIPTION:  
 *   This PTF removes all the input columns listed in col from the output  
 *   of the PTF.  
*/   
  FUNCTION  describe(tab IN OUT dbms_tf.table_t,   
                     col        dbms_tf.columns_t)  
            RETURN dbms_tf.describe_t  
  AS   
    new_cols dbms_tf.columns_new_t;  
    col_id   PLS_INTEGER := 1;  
  BEGIN   
    FOR i IN 1 .. tab.column.count() LOOP  
      FOR j IN 1 .. col.count() LOOP  
      tab.column(i).pass_through := tab.column(i).description.name != col(j);  
        EXIT WHEN NOT tab.column(i).pass_through;  
      END LOOP;  
    END LOOP;  

    RETURN NULL;  
  END;  

 /* OVERLOAD 2: Skip by type  
 * NAME:  skip_col_pkg.skip_col   
 * ALIAS: skip_col_by_type  
 *  
 * PARAMETERS:  
 *   tab       - Input table  
 *   type_name - A string representing the type of columns to skip  
 *   flip      - 'False' [default] => Match columns with given type_name  
 *               otherwise         => Ignore columns with given type_name  
 *  
 * DESCRIPTION:  
 *   This PTF removes the given type of columns from the given table.   
*/   

  FUNCTION describe(tab       IN OUT dbms_tf.table_t,   
                    type_name        VARCHAR2,   
                    flip             VARCHAR2 DEFAULT 'False')   
           RETURN dbms_tf.describe_t   
  AS   
    typ CONSTANT VARCHAR2(1024) := upper(trim(type_name));  
  BEGIN   
    FOR i IN 1 .. tab.column.count() LOOP  
       tab.column(i).pass_through :=   
         CASE upper(substr(flip,1,1))  
           WHEN 'F' THEN dbms_tf.column_type_name(tab.column(i).description)
     !=typ  
           ELSE          dbms_tf.column_type_name(tab.column(i).description) 
     =typ  
         END /* case */;  
    END LOOP;  

    RETURN NULL;  
  END;  

END skip_col_pkg;  

E Utilização da amostra:

-- skip number cols
SELECT * FROM skip_col_pkg.skip_col(scott.dept, 'number'); 

-- only number cols
SELECT * FROM skip_col_pkg.skip_col(scott.dept, 'number', flip => 'True') 

-- skip defined columns
SELECT *   
FROM skip_col_pkg.skip_col(scott.emp, columns(comm, hiredate, mgr))  
WHERE deptno = 20;

Eu recomendo ler o exemplo inteiro (criando funções autônomas em vez de chamadas de pacotes).

Poderá sobrecarregar facilmente o método de ignorar, por exemplo: ignorar as colunas que não começam/terminam com prefixo/sufixo específico.

 2
Author: Lukasz Szozda, 2018-02-27 18:37:17

Como outros dizem: Seleccionar * é uma má ideia.

Algumas razões:

  1. Obter apenas o que você precisa (qualquer coisa mais é um desperdício)
  2. indexação (indexar o que você precisa e você pode obtê-lo mais rapidamente. Se você pedir um monte de colunas não indexadas, também, seus planos de consulta vai sofrer.
 0
Author: Michael Haren, 2009-01-05 17:21:26
declare @sql nvarchar(max)
        @table char(10)
set @sql = 'select '
set @table = 'table_name'

SELECT @sql = @sql + '[' + COLUMN_NAME + '],'
FROM   INFORMATION_SCHEMA.Columns
WHERE  TABLE_NAME = @table
   and COLUMN_NAME <> 'omitted_column_name'
SET    @sql = substring(@sql,1,len(@sql)-1) + ' from ' + @table

EXEC (@sql);
 0
Author: kzh, 2010-07-08 03:45:44
É uma pergunta antiga, mas espero que ainda possa ser útil.
DECLARE @SQL NVARCHAR(MAX)
SELECT @SQL = COALESCE(@SQL + ', ', ' ' ) + name FROM sys.columns WHERE name <> 'colName' AND object_id = (SELECT id FROM sysobjects WHERE name = 'tblName')
SELECT @SQL = 'SELECT ' + @SQL + ' FROM ' + 'tblName'
EXEC sp_executesql  @SQL

Procedimento Armazenado:

Usp_selectallexept 'tblname','colname'

ALTER PROCEDURE [dbo].[usp_SelectAllExcept]
(
  @tblName SYSNAME
 ,@exception VARCHAR(500)
)
AS

DECLARE @SQL NVARCHAR(MAX)

SELECT @SQL = COALESCE(@SQL + ', ', ' ' ) + name from sys.columns where name <> @exception and object_id = (Select id from sysobjects where name = @tblName)
SELECT @SQL = 'SELECT ' + @SQL + ' FROM ' + @tblName

EXEC sp_executesql @SQL
 0
Author: kakusan, 2016-08-13 00:43:33
{[[2]} eu precisava de algo como o que @Glen pede para facilitar a minha vida com HASHBYTES().

A minha inspiração foi @Jasmine e @Zerubbabel answers. No meu caso, tenho esquemas diferentes, por isso o mesmo nome de tabela aparece mais de uma vez no sys.objecto. Como isso pode ajudar alguém com o mesmo cenário, aqui vai:

ALTER PROCEDURE [dbo].[_getLineExceptCol]

@table SYSNAME,
@schema SYSNAME,
@LineId int,
@exception VARCHAR(500)

AS

DECLARE @SQL NVARCHAR(MAX)

BEGIN

SET NOCOUNT ON;

SELECT @SQL = COALESCE(@SQL + ', ', ' ' ) + name 
FROM sys.columns 
WHERE name <> @exception 
AND object_id = (SELECT object_id FROM sys.objects 
                 WHERE name LIKE @table 
                 AND schema_id = (SELECT schema_id FROM sys.schemas WHERE name LIKE @schema))   

SELECT @SQL = 'SELECT ' + @SQL + ' FROM ' + @schema + '.' + @table + ' WHERE Id = ' + CAST(@LineId AS nvarchar(50))

EXEC(@SQL)
END
GO
 0
Author: rantunes, 2017-03-24 17:41:08

A opção da tabela Temp aqui, basta largar as colunas não necessárias e seleccionar * da tabela temp alterada.

/* Get the data into a temp table */
    SELECT * INTO #TempTable
    FROM 
    table

/* Drop the columns that are not needed */
    ALTER TABLE #TempTable
    DROP COLUMN [columnname]

SELECT * from #TempTable
 0
Author: Mike, 2017-07-18 15:02:23

Por uma questão de Completude, isto é possível no dialecto DremelSQL, fazendo algo como:

WITH orders AS (SELECT 5 as order_id, "foobar12" as item_name, 800 as quantity) SELECT * EXCEPT (order_id) FROM orders;

+-----------+----------+ | item_name | quantity | +-----------+----------+ | foobar12 | 800 | +-----------+----------+

Também parece haver outra maneira de o fazer Aqui sem Dremel.

 0
Author: David Andrei Ned, 2017-08-04 18:18:44