2009-01-05 24 views
41

¿Hay algún RDBMS que implemente algo como SELECT * EXCEPT? Lo que busco es obtener todos los campos, excepto un campo TEXTO/BLOB específico, y me gustaría simplemente seleccionar todo lo demás.SELECCIONAR * EXCEPTO

Casi a diario me quejo con mis compañeros de trabajo de que alguien debería implementar esto ... Es terriblemente molesto que no exista.

Edit: Entiendo la preocupación de todos por SELECT *. Conozco los riesgos asociados con SELECT *. Sin embargo, esto, al menos en mi situación, no se usaría para ningún código de nivel de producción, o incluso código de nivel de desarrollo; estrictamente para la depuración, cuando necesito ver todos los valores fácilmente.

Como he indicado en algunos de los comentarios, donde trabajo es estrictamente una tienda de línea de comandos, haciendo todo a través de ssh. Esto dificulta el uso de cualquier herramienta GUI (no se permiten conexiones externas a la base de datos), etc. etc.

Gracias por las sugerencias.

+0

La palabra clave EXCEPT existe en SQL Server, aunque no está destinada a usarse como le gustaría en su pregunta. Realiza una UNIÓN DE DIFERENCIA entre dos conjuntos de resultados para proporcionarle un conjunto de resultados de "registros" que existen en el primer conjunto de resultados pero que no existen en el segundo conjunto de resultados –

+3

. Apesta que esto no exista. – VISQL

+1

posible duplicado de [SQL excluye una columna usando SELECT \ * \ [excepto columnA \] FROM tableA?] (Http://stackoverflow.com/questions/729197/sql-exclude-a-column-using-select-except- columna-from-tablea) – billinkc

Respuesta

25

Como otros han dicho, no es una buena idea hacer esto en una consulta porque es propenso a problemas cuando alguien cambia la estructura de la tabla en el futuro. Sin embargo, hay una manera de hacer esto ... y no puedo creer que realmente esté sugiriendo esto, pero en el espíritu de responder la pregunta REAL ...

Hazlo con SQL dinámico ... esto hace todas las columnas excepto la columna "descripción". Podría convertir esto fácilmente en una función o proceso almacenado.

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 
+9

Y con el espíritu de responder la pregunta real, ganas el premio. –

+1

De hecho, puedo pensar en varias razones por las que podría necesitar hacer esto sin volverse loco. Además, fue una pregunta interesante, independientemente de los problemas, fue divertido de averiguar :) – Jasmine

+1

En primer lugar, gracias por responder la pregunta en lugar de opinar sobre si la persona debería estar haciendo la cosa o no. Un escenario principal para hacer esto sería crear una vista, que desea tener para recoger las columnas de la tabla subyacente si cambian, y se utilizará en otras declaraciones de selección que eligen columnas específicas. –

5

Aléjate de SELECT *, te estás preparando para problemas. Siempre especifique exactamente qué columnas desea. De hecho, es bastante refrescante que la "característica" que está solicitando no exista.

+0

Afortunadamente, nuestras tablas casi nunca cambian. Estoy pensando en esto específicamente para problemas de depuración, donde necesito todos los demás campos, excepto el BLOB. –

+0

en ese caso específico, estoy de acuerdo en que sería bueno tenerlo. –

+0

La palabra de operación aquí es * casi *. Además, cualquier buena herramienta SQL le permitirá hacer clic y elegir lo que desee sin contaminar el idioma con dicho artilugio. –

2

Creo que la razón por la que no existe es que el autor de una consulta debe (solo por razones de rendimiento) solicitar lo que van a ver/necesitar (y por lo tanto saber qué columnas especificar) - si alguien agrega un par de blobs más en el futuro, estarás retirando campos potencialmente grandes que no vas a necesitar.

1

Como otros dicen: SELECCIONAR * es una mala idea.

Algunas razones:

  1. Obtener sólo lo que necesita (nada más es un desperdicio)
  2. de indexación (índice de lo que necesita y lo puede conseguir más rápidamente Si pide un montón de no. -indexed columnas, también, sus planes de consulta se verá afectada.
+0

No estoy de acuerdo con su punto de segundos, porque buscar columnas no tiene, en primer lugar, nada que ver con los planes de indexación ni de ejecución. Agregue un índice a una columna, si desea unir tablas por columnas o desea restringir los datos en columnas (DONDE) en un momento elegible. Cuando simplemente selecciona cinco tablas al unirlas, realmente no importa si selecciona una o 200 columnas (esto es solo cuestión de obtener los datos). – bobbel

+1

@bobbel Debo insistir en que los índices pueden mejorar absolutamente la recuperación más allá de solo encontrar los registros deseados, * si * cubren las columnas solicitadas. Los índices de cobertura pueden producir una mejora masiva del rendimiento respondiendo a la consulta/unión completa/etc. desde el índice en sí, sin ir a los datos subyacentes que generaron el índice. –

23

crear una vista en la mesa, que no incluye las columnas blob

+1

+1: esto es bastante razonable, y no SELECT * permitido aquí también. –

+1

Requiere modificar la vista si la tabla fuente cambia. Si va a usar SELECT * en eso, también podría seleccionar las columnas con las que realmente desea comenzar. –

+1

Sin embargo, le evita escribir esas columnas una y otra vez. Para el uso de un desarrollador en la depuración, no es una mala idea. –

0
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); 
5

¿Hay alguna RDBMS que implementa algo así como SELECT * excepto

Sí! El lenguaje verdaderamente relacional Tutorial D permite que la proyección se exprese en términos de los atributos que se eliminarán en lugar de los que deben conservarse, p.

my_relvar { ALL BUT description } 

De hecho, su equivalente a SELECT * de SQL es { ALL BUT }.

Su propuesta de SQL es un digno pero he oído que ya ha sido puesto a la comisión del estándar SQL por el grupo de usuarios y rechazado por el grupo del proveedor :(

También ha sido explicitly requested for SQL Server pero la solicitud se cerró como 'no va a arreglar'.

9

DB2 permite esto. Columnas tienen un atributo/especificador de Hidden.

Desde el syscolumns documentation

HIDDEN
CHAR (1) NOT NULL WITH DEFAULT 'N'
Indica si la columna está oculta implícitamente:

P parcialmente oculta. La columna está implícitamente oculta de SELECT *.

N No oculto. La columna es visible para todas las declaraciones SQL.

Create table documentation Como parte de la creación de su columna, debe especificar el modificador IMPLICITLY HIDDEN

Un ejemplo DDL de Implicitly Hidden Columns sigue

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

Si esta capacidad es un fabricante de tal acuerdo para impulsar la adopción de DB2 se deja como un ejercicio para los lectores futuros.

0

Es una vieja pregunta, pero espero que esto todavía pueda 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 

procedimiento almacenado:

'tblname' usp_SelectAllExcept, 'nomCol'

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

necesitaba algo parecido a lo que pide @Glen para aliviar mi vida con HASHBYTES().

Mi inspiración fueron las respuestas de @Jasmine y @Zerubbabel. En mi caso, tengo diferentes esquemas, por lo que el mismo nombre de tabla aparece más de una vez en sys.objects. Ya que esto puede ayudar a alguien con el mismo escenario, aquí va:

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

opción de tabla temporal aquí, simplemente introduce las columnas que no sean necesarios y seleccionar * de la tabla temporal 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

En aras de la exhaustividad, esto es posible en DremelSQL dialecto, haciendo 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 | +-----------+----------+

También parece ser otra manera de hacerlo here sin Dremel.

1

Sí, finalmente hay :) estándar SQL 2016 define Polymorphic Table Functions

SQL: 2016 introduce funciones de tabla polimórficos (PTF) que no necesitan especificar el tipo de resultado por adelantado. En cambio, pueden proporcionar un procedimiento de componente de descripción que determina el tipo de devolución en tiempo de ejecución. Ni el autor del PTF ni el usuario del PTF necesitan declarar las columnas devueltas por adelantado.

Los PTF descritos por SQL: 2016 aún no están disponibles en ninguna base de datos probada.10 Los lectores interesados ​​pueden consultar el informe técnico gratuito "Funciones de tabla polimórficas en SQL" publicado por ISO. Los siguientes son algunos de los ejemplos analizados en el informe:

  • CSVReader, que lee el encabezamiento de un archivo CVS para determinar el número y los nombres de las columnas de retorno

  • pivote (en realidad UNPIVOT) , que convierte los grupos de columnas en filas (ejemplo: phonetype, del número de teléfono) - me: no hay cuerdas más harcoded :)

  • TopNplus, que pasa a través de N filas por partición y una fila adicional con los totales de las filas restantes


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

Este ejemplo muestra cómo omitir los datos en función del nombre/tipo de datos específico:

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; 

y cuerpo:

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; 

Y muestra de uso:

-- 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; 

I recomiendo leer todo el ejemplo (creando una función independiente) iones en lugar de llamadas de paquete).

Podría sobrecargar fácilmente el método de omisión, por ejemplo: omita las columnas que no comienzan/finalizan con un prefijo/sufijo específico.

Cuestiones relacionadas