SQL excluye una columna usando SELECT * [excepto columnA] FROM tableA?


733

Todos sabemos que para seleccionar todas las columnas de una tabla, podemos usar

SELECT * FROM tableA

¿Hay alguna manera de excluir columnas de una tabla sin especificar todas las columnas?

SELECT * [except columnA] FROM tableA

La única forma que sé es especificar manualmente todas las columnas y excluir la columna no deseada. Esto lleva mucho tiempo, por lo que estoy buscando formas de ahorrar tiempo y esfuerzo en esto, así como el mantenimiento futuro en caso de que la tabla tenga más / menos columnas.


27
Sería muy conveniente tener esta función, no para incluir el código de producción, sino para solucionar problemas. Ejemplo: Tengo una tabla que tiene varias columnas que consulto, pero quiero omitir rápidamente una o dos columnas de texto.
Micah B.

Tenía una necesidad de esto cuando trabajaba con openquery (aunque necesitaba la funcionalidad en MySQL en lugar de SQL Server). Tuve que consultar una base de datos MySQL usando SQL Server. Debido a que una tabla MySQL tenía columnas de caracteres de ancho fijo, no pude usar una SELECT *consulta (OLE DB tiene problemas para mapearlas). No podía especificar las columnas de la derecha porque no tenía acceso directo a la base de datos MySQL, SQL Server, sin embargo tuvo la amabilidad de informarme de los nombres de la anchura de las columnas CHAR fijo ...
jahu

2
Me gustaría agregar otra razón para hacer esto: a SELECT DISTINCT *excepción de que la columna clave funcione sin filas duplicadas que otra persona haya creado
elimine el

1
Estoy de acuerdo en que lleva mucho tiempo. Es por eso que generalmente hago clic derecho en la tabla, elijo "seleccionar las 1000 filas superiores" y luego elimino las columnas que no quiero.
ThomasRones

2
para no olvidar: en muchos casos, el desarrollador no conoce las columnas porque pueden cambiar. Esto es típico en los almacenes de datos. después de 6 meses, agregan una columna adicional y debe seleccionarse sin cambiar el código.

Respuestas:


447

Estoy de acuerdo con todos ... pero si fuera a hacer algo como esto, podría hacerlo de esta manera:

/* Get the data into a temp table */
SELECT * INTO #TempTable
FROM YourTable
/* Drop the columns that are not needed */
ALTER TABLE #TempTable
DROP COLUMN ColumnToDrop
/* Get results and drop temp table */
SELECT * FROM #TempTable
DROP TABLE #TempTable

222
Ineficiente ... pero muy creativo :)
Guillermo Gutiérrez

1
Hermoso. A menudo necesito incluir unir dos tablas temporales o una tabla temporal a otra tabla donde no necesito todas las columnas en la tabla temporal, especialmente porque la agrupación estará involucrada.
VISQL

2
Muy agradable. Seguro resuelve el problema de abstraer los nombres de columna.
Tostadora

1
@CeesTimmerman: si tiene una consulta que involucra nombres de columna duplicados, ese es un problema separado, SIN IMPORTAR qué enfoque está tomando. Google "cambio de nombre de columna SQL" o "alias de columna SQL". Algo así como SELECT table1.ID AS table1ID ..., IIRC.
ToolmakerSteve

3
@ToolmakerSteve La idea de esta pregunta es solo especificar columnas que no necesita. Nombrar columnas requeriría especificar todas, por ejemplo, más de 20 columnas de una tabla en particular.
Cees Timmerman

289

No.

La mejor práctica de mantenimiento ligero es especificar solo las columnas requeridas.

Al menos 2 razones:

  • Esto hace que su contrato entre el cliente y la base de datos sea estable. Misma información, siempre
  • Rendimiento, cubriendo índices

Editar (julio de 2011):

Si arrastra desde el Explorador de objetos el Columnsnodo para una tabla, coloca una lista CSV de columnas en la Ventana de consulta para usted, lo que logra uno de sus objetivos


3
Nunca supe lo de arrastrar columnas. Gracias, GBN, nuevamente has salvado el día. debe ganar mucho $$ debido a su experiencia sql
l --''''''--------- '' '' '' '' '' ''

44
Hay escenarios válidos con SELECT *, especialmente en las rutinas ETL. Creo que la mejor respuesta aquí es la que tiene SQL dinámico.
mishkin

1
Hay casos en los que desea seleccionar decir todos los datos de un estudiante para la exploración estadística, pero no
descartar

3
"especifique solo las columnas requeridas" - falta de codificación rígida
RM Haley

99
Aunque las respuestas como esta obtienen muchos votos, no tienen valor en lo que a mí respecta. Conceptualmente, ser capaz de "Seleccionar * Excepto ABC" no es más problemático que "Seleccionar *", que admite el idioma. El OP claramente está pidiendo una forma de lograr algo. La persona que responde esta pregunta no tiene forma de saber si el OP quiere usar esto en el código de producción o si simplemente tiene una necesidad inmediata de ejecutar una consulta como esta mientras está desarrollando algún código para la base de datos, por lo que la conferencia sobre buenos estándares no aporta ningún valor en absoluto.
Itsme2003

68

Si no desea escribir cada nombre de columna manualmente, puede usarlo Script Table Ashaciendo clic derecho en la tabla o ver en SSMS de esta manera:

ingrese la descripción de la imagen aquí

Luego obtendrá una consulta de selección completa en la Nueva ventana del editor de consultas y luego eliminará la columna no deseada como esta:

ingrese la descripción de la imagen aquí

Hecho


2
Esto es más fácil que seleccionar todos los nombres de columna y luego agregarle comas.
shaijut

68

La forma automatizada de hacer esto en SQL (SQL Server) es:

declare @cols varchar(max), @query varchar(max);
SELECT  @cols = STUFF
    (
        ( 
            SELECT DISTINCT '], [' + name
            FROM sys.columns
            where object_id = (
                select top 1 object_id from sys.objects
                where name = 'MyTable'
            )
            and name not in ('ColumnIDontWant1', 'ColumnIDontWant2')
            FOR XML PATH('')
        ), 1, 2, ''
    ) + ']';

SELECT @query = 'select ' + @cols + ' from MyTable';  
EXEC (@query);

¿Qué sucede si está consultando el resultado de un CTE u otra subconsulta? Un ejemplo simple: es posible que desee hacer una subconsulta que anexe el resultado de row_number()cada fila, luego realice una unión por row_number, luego seleccione todo exceptorow_number el resultado de la unión.
ely

43

Puede crear una vista que tenga las columnas que desea seleccionar, luego puede simplemente select *desde la vista ...


8
Al principio mi reacción fue "¿cómo es esto más fácil que solo especificar las columnas"? Pero luego decidí que desde una perspectiva de mantenimiento, podría ser una mejora.
ToolmakerSteve

1
Esto también admite el optimizador de consultas en lugar de contrarrestarlo con una tabla temporal o SQL dinámico.
underscore_d

30

Sí, es posible (pero no recomendado).

CREATE TABLE contact (contactid int, name varchar(100), dob datetime)
INSERT INTO contact SELECT 1, 'Joe', '1974-01-01'

DECLARE @columns varchar(8000)

SELECT @columns = ISNULL(@columns + ', ','') + QUOTENAME(column_name)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'contact' AND COLUMN_NAME <> 'dob'
ORDER BY ORDINAL_POSITION

EXEC ('SELECT ' + @columns + ' FROM contact')

Explicación del código :

  1. Declare una variable para almacenar una lista separada por comas de nombres de columna. Esto predeterminado es NULL.
  2. Use una vista del sistema para determinar los nombres de las columnas en nuestra tabla.
  3. Use SELECT @variable = @variable + ... FROMpara concatenar los nombres de columna. Este tipo de SELECTno devuelve un conjunto de resultados. Este es quizás un comportamiento no documentado, pero funciona en todas las versiones de SQL Server. Como alternativa, puede usar SET @variable = (SELECT ... FOR XML PATH(''))para concatenar cadenas.
  4. Use la ISNULLfunción para anteponer una coma solo si este no es el nombre de la primera columna. Use la QUOTENAMEfunción para admitir espacios y puntuación en los nombres de columna.
  5. Use la WHEREcláusula para ocultar columnas que no queremos ver.
  6. Use EXEC (@variable), también conocido como SQL dinámico , para resolver los nombres de columna en tiempo de ejecución. Esto es necesario porque no conocemos los nombres de las columnas en tiempo de compilación.

¡Gracias! Esta fue la clave para resolver mi problema .
Antonio

Tengo una pregunta: ¿por qué razón la segunda selección debe incluirse en una declaración EXEC? He visto que es efectivamente necesario, pero me pregunto por qué no puedo simplemente escribirSELECT @columns FROM contact
Antonio

17

Como los otros han dicho, no hay forma de hacer esto, pero si está usando SQL Server, un truco que uso es cambiar la salida a coma separada, entonces haga

select top 1 * from table

y cortar la lista completa de columnas de la ventana de salida. Luego puede elegir qué columnas desea sin tener que escribirlas todas.


13
Vea mi consejo sobre cómo arrastrar desde SSMS
gbn

11

Básicamente, no puede hacer lo que le gustaría, pero puede obtener las herramientas adecuadas para ayudarlo a hacer las cosas un poco más fáciles.

Si observa la solicitud SQL de Red-Gate , puede escribir "SELECCIONAR * DE MyTable", y luego mover el cursor hacia atrás después de "*", y presionar <TAB> para expandir la lista de campos, y eliminar esos pocos campos que no necesito

No es una solución perfecta, ¡pero es una muy buena! :-) Lástima que Intellisense de MS SQL Server Management Studio todavía no sea lo suficientemente inteligente como para ofrecer esta característica .......

Bagazo


Esto es bueno, pero el problema es que su consulta puede volverse enorme. Sería bueno tener la función "excepto", no para el código de producto, sino para consultas ad-hoc.
Micah B.

8

no, no hay forma de hacer esto. tal vez pueda crear vistas personalizadas si eso es factible en su situación

EDITAR Puede ser si su base de datos admite la ejecución de sql dinámico. Podría escribir un SP y pasar las columnas que no desea ver y dejar que cree la consulta dinámicamente y le devuelva el resultado. Creo que esto es factible en SQL Server al menos


13
Es factible, pero despediría a la persona que hace eso.
Lieven Keersmaekers

Problema de limpieza clásico: copie el dfata que desea mantener en una tabla temporal, trunca el grande, vuelva a llenar con la tabla temporal. Debe excluir la columna de identidad.
Volker

8

Si está utilizando SQL Server Management Studio, haga lo siguiente:

  1. Escriba el nombre de su tabla deseada y selecciónela
  2. Presione Alt+F1
  3. o / p muestra las columnas en la tabla.
  4. Seleccione las columnas deseadas
  5. Copie y pegue los de su consulta de selección
  6. Dispara la consulta.

Disfrutar.


7

En SQL Management Studio puede expandir las columnas en el Explorador de objetos, luego arrastrar el Columnselemento del árbol a una ventana de consulta para obtener una lista de columnas separadas por comas.


6

En resumen, no puede hacerlo, pero no estoy de acuerdo con todos los comentarios anteriores, hay "escenarios" en los que puede usar legítimamente un * cuando crea una consulta anidada para seleccionar un rango específico de una lista completa (como paginación) ¿por qué en el mundo desearía especificar cada columna en la declaración de selección externa cuando lo ha hecho en la interna?


¿Se puede usar alguna variación de "nombre interno. *" Para representar las columnas internas, similar a "SELECCIONAR tabla1. * ..." al hacer una unión?
ToolmakerSteve

6
DECLARE @SQL VARCHAR(max), @TableName sysname = 'YourTableName'

SELECT @SQL = COALESCE(@SQL + ', ', '') + Name 
FROM sys.columns
WHERE OBJECT_ID = OBJECT_ID(@TableName)
AND name NOT IN ('Not This', 'Or that');

SELECT @SQL = 'SELECT ' + @SQL + ' FROM ' + @TableName

EXEC (@SQL)

ACTUALIZAR:

También puede crear un procedimiento almacenado para encargarse de esta tarea si la usa con más frecuencia. En este ejemplo, he usado el STRING_SPLIT () que está disponible en SQL Server 2016+, pero si lo necesita, hay muchos ejemplos de cómo crearlo manualmente en SO.

CREATE PROCEDURE [usp_select_without]
@schema_name sysname = N'dbo',
@table_name sysname,
@list_of_columns_excluded nvarchar(max),
@separator nchar(1) = N','
AS
BEGIN
 DECLARE 
 @SQL nvarchar(max),
 @full_table_name nvarchar(max) = CONCAT(@schema_name, N'.', @table_name);

 SELECT @SQL = COALESCE(@SQL + ', ', '') + QUOTENAME([Name])
 FROM sys.columns sc
 LEFT JOIN STRING_SPLIT(@list_of_columns_excluded, @separator) ss ON sc.[name] = ss.[value]
 WHERE sc.OBJECT_ID = OBJECT_ID(@full_table_name, N'u')
 AND ss.[value] IS NULL;

 SELECT @SQL = N'SELECT ' + @SQL + N' FROM ' + @full_table_name;
 EXEC(@SQL)
END

Y luego solo:

EXEC [usp_select_without] 
@table_name = N'Test_Table',
@list_of_columns_excluded = N'ID, Date, Name';

5

Si hablamos de procedimientos, funciona con este truco para generar una nueva consulta y EJECUTARLA INMEDIATA :

SELECT LISTAGG((column_name), ', ') WITHIN GROUP (ORDER BY column_id)
INTO var_list_of_columns
FROM ALL_TAB_COLUMNS
WHERE table_name = 'PUT_HERE_YOUR_TABLE'
AND column_name NOT IN ('dont_want_this_column','neither_this_one','etc_column');

5

¿Hay alguna manera de excluir columnas de una tabla sin especificar todas las columnas?

Usando SQL declarativo de la manera usual, no.

Creo que su sintaxis propuesta es digna y buena. De hecho, el lenguaje de base de datos relacional 'Tutorial D' tiene una sintaxis muy similar donde las palabras clave ALL BUTvan seguidas de un conjunto de atributos (columnas).

Sin embargo, el SQL SELECT *ya recibe muchas críticas (la respuesta de @ Guffa aquí es una objeción típica), por lo que no creo SELECT ALL BUTque llegue al Estándar SQL pronto.

Creo que el mejor 'trabajo' es crear una VIEWcon solo las columnas que desee en ese momento SELECT * FROM ThatView.


1
@underscore_d: ahora he revisado mi respuesta.
cuando el

Genial, estoy de acuerdo con tus últimos 2 párrafos. La información sobre el Tutorial D es interesante, aunque tiendo a estar de acuerdo con aquellos que piensan que select *es cuestionable, muy útil para cosas y programas ad hoc que necesitan manejar genéricamente tablas de datos, pero no tanto para construir (a falta de una palabra mejor) consultas 'puras'. Aún así, no estar en el estándar ANSI no significa que Microsoft no pueda agregarlo a su dialecto, como con muchas otras cosas, pero soy escéptico sobre si lo harían.
underscore_d

5

Un dialecto SQL moderno como BigQuery propone una excelente solución

SELECCIONAR * EXCEPTO (ColumnNameX, [ColumnNameY, ...])

Esta es una sintaxis SQL muy poderosa para evitar una larga lista de columnas que deben actualizarse todo el tiempo debido a cambios en el nombre de la columna de la tabla. Y esta funcionalidad falta en la implementación actual de SQL Server, lo cual es una pena. Con suerte, algún día, Microsoft Azure será más amigable con los científicos de datos.

A los científicos de datos les gusta poder tener una opción rápida para acortar una consulta y poder eliminar algunas columnas (debido a la duplicación o cualquier otra razón).

https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select-modifiers


4

Postgres sql tiene una forma de hacerlo

consulte: http://www.postgresonline.com/journal/archives/41-How-to-SELECT-ALL-EXCEPT-some-columns-in-a-table.html

El esquema de información Hack Way

SELECT 'SELECT ' || array_to_string(ARRAY(SELECT 'o' || '.' || c.column_name
        FROM information_schema.columns As c
            WHERE table_name = 'officepark' 
            AND  c.column_name NOT IN('officeparkid', 'contractor')
    ), ',') || ' FROM officepark As o' As sqlstmt

Lo anterior para mi tabla de ejemplo particular: genera una instrucción sql que se ve así

SELECCIONE o.officepark, o.owner, o.squarefootage FROM officepark As o


Si bien esto puede responder teóricamente la pregunta, sería preferible incluir aquí las partes esenciales de la respuesta y proporcionar el enlace para referencia.
Bhargav Rao

3

No conozco ninguna base de datos que soporte esto (SQL Server, MySQL, Oracle, PostgreSQL). Definitivamente no es parte de los estándares SQL, así que creo que debe especificar solo las columnas que desea.

Por supuesto, podría construir su declaración SQL de forma dinámica y hacer que el servidor la ejecute. Pero esto abre la posibilidad de inyección SQL.


3

Sé que esto es un poco viejo, pero acababa de encontrarme con el mismo problema y estaba buscando una respuesta. Luego tuve un desarrollador senior que me mostró un truco muy simple.

Si está utilizando el editor de consultas de Management Studio, expanda la base de datos, luego expanda la tabla que está seleccionando para que pueda ver la carpeta de columnas.

En su declaración de selección, solo resalte la carpeta de columnas referenciadas arriba y arrástrela y suéltela en la ventana de consulta. Pegará todas las columnas de la tabla, luego simplemente eliminará la columna de identidad de la lista de columnas ...


1
Sí, pero qué pasa si tienes 5 uniones, la idea sería hacerSELECT * Except(tableName.ColumnName) FROM ...
Pawel Cioch

Encuentro esto útil :) No he sabido sobre eso, sin embargo, esta no es una respuesta para una pregunta de tema.
Fka

3

La mejor manera de resolver esto es usando la vista, puede crear una vista con las columnas requeridas y recuperar datos de ella

example

mysql> SELECT * FROM calls;
+----+------------+---------+
| id | date       | user_id |
+----+------------+---------+
|  1 | 2016-06-22 |       1 |
|  2 | 2016-06-22 |    NULL |
|  3 | 2016-06-22 |    NULL |
|  4 | 2016-06-23 |       2 |
|  5 | 2016-06-23 |       1 |
|  6 | 2016-06-23 |       1 |
|  7 | 2016-06-23 |    NULL |
+----+------------+---------+
7 rows in set (0.06 sec)

mysql> CREATE VIEW C_VIEW AS
    ->     SELECT id,date from calls;
Query OK, 0 rows affected (0.20 sec)

mysql> select * from C_VIEW;
+----+------------+
| id | date       |
+----+------------+
|  1 | 2016-06-22 |
|  2 | 2016-06-22 |
|  3 | 2016-06-22 |
|  4 | 2016-06-23 |
|  5 | 2016-06-23 |
|  6 | 2016-06-23 |
|  7 | 2016-06-23 |
+----+------------+
7 rows in set (0.00 sec)

3
¿Qué pasa si el número de columnas es grande, digamos 100 y queríamos SELECCIONAR todas las columnas, pero una? ¿Hay un mejor enfoque?
KartikKannapur

55
Este tipo de pierde el punto. Está seleccionando "id, date" en la segunda llamada, que, si iba a hacer eso, simplemente hágalo en primer lugar.
keithpjolley

3

Si desea excluir una columna de mayúsculas y minúsculas como la contraseña, por ejemplo, hago esto para ocultar el valor:

SELECT * , "" as password FROM tableName;


este funcionó para mí
Arun Prasad ES

1
Si bien, por supuesto, nunca debe almacenar contraseñas de texto sin cifrar en su base de datos. Al menos deberían ser picados con sal y quizás pimienta security.stackexchange.com/questions/3272/…
Anders_K

2

Bueno, es una práctica recomendada común especificar qué columnas desea, en lugar de solo especificar *. Por lo tanto, debe indicar qué campos desea que devuelva su selección.


2

Un colegio aconseja una buena alternativa:

  • SELECCIONE EN su consulta anterior (donde genera u obtiene los datos) en una tabla (que eliminará cuando termine). Esto creará la estructura para ti.
  • Realice un script como CREAR en una nueva ventana de consulta.
  • Eliminar las columnas no deseadas. Formatee las columnas restantes en un trazador de líneas 1 y péguelo como su lista de columnas.
  • Elimina la tabla que creaste.

Hecho...

Esto nos ayudó mucho.


1

Haga clic con el botón derecho en la tabla en el Explorador de objetos, seleccione las 1000 filas superiores

Enumerará todas las columnas y no *. Luego, elimine las columnas no deseadas. Debería ser mucho más rápido que escribirlo usted mismo.

Luego, cuando sienta que esto es demasiado trabajo, obtenga el mensaje SQL de Red Gate y escriba ssf desde tbl, vaya a * y haga clic en la pestaña nuevamente.


1

Que lo uso a menudo para este caso:

declare @colnames varchar(max)=''

select @colnames=@colnames+','+name from syscolumns where object_id(tablename)=id and name not in (column3,column4)

SET @colnames=RIGHT(@colnames,LEN(@colnames)-1)

@colnames parece column1,column2,column5


1

A veces, el mismo programa debe manejar diferentes estructuras de bases de datos. Por lo tanto, no podría usar una lista de columnas en el programa para evitar errores en las selectdeclaraciones.

*me da todos los campos opcionales Compruebo si los campos existen en la tabla de datos antes de usarlos. Este es mi razón para usar *en select.

Así es como manejo los campos excluidos:

Dim da As New SqlDataAdapter("select * from table", cn)
da.FillSchema(dt, SchemaType.Source)
Dim fieldlist As String = ""
For Each DC As DataColumn In DT.Columns
   If DC.ColumnName.ToLower <> excludefield Then
    fieldlist = fieldlist &  DC.Columnname & ","
   End If
  Next

Considere elaborar / aclarar su pregunta / problema.
badfilms

1

Sé que esta pregunta es antigua, pero espero que aún pueda ser útil. La respuesta está inspirada en un debate de los foros de SQL Server . Puede hacer de esto un procedimiento almacenado . También se puede modificar para agregar más de uno, excepto los campos.

DECLARE @SQL NVARCHAR(MAX)
SELECT @SQL = COALESCE(@SQL + ', ', ' ' ) + name from sys.columns where name not in ('colName1','colName2') and object_id = (Select id from sysobjects where name = 'tblName')
SELECT @SQL = 'SELECT ' + @SQL + ' FROM ' + 'tblName'
EXEC sp_executesql  @SQL

0

¿No sería más simple hacer esto?

sp_help <table_name>

-Haga clic en la columna 'Column_name'> Copiar> Pegar (crea una lista vertical) en una ventana Nueva consulta y simplemente escriba comas delante del valor de cada columna ... comente las columnas que no desea ... mucho menos escribiendo que cualquier código ofrecido aquí y aún manejable.


"mucho menos tipeo que cualquier código ofrecido aquí" y mucha más molestia que arrastrar el nodo Columnas al editor de consultas o cualquiera de las otras formas superiores de obtener la lista. Quiero decir ¿qué pasa con las tablas con muchos 10s de columnas?
underscore_d

0

Puede obtener SQL Complete de devart.com, que no solo expande el comodín * al igual que lo hace SQL Prompt de Red Gate (como se describe en la respuesta de cairnz), sino que también proporciona un menú desplegable de selección de columnas con casillas de verificación en las que puede marcar todos los columnas que desee en la lista de selección y se insertarán automáticamente por usted (y si desmarca una columna, se eliminará automáticamente de la lista de selección).


0

En SSMS hay una manera más fácil con IntelliSense y Aliasing . Prueba esto

  1. Haga clic derecho en el editor de texto y asegúrese de que IntelliSense esté habilitado.
  2. Escriba la consulta con un alias [SELEC . T. * DESDE nombre de tabla t].
  3. Ir al texto t. * Y elimine el * , y SSMS se auto-lista de las columnas de la f tabla de alias.
Luego puede especificar rápidamente solo las columnas que desea sin tener que usar SSMS para escribir una selección en otro script y luego realizar más operaciones de copiar / pegar. Uso esto todo el tiempo.


¿Podría especificar su respuesta a la exclusión de columnas, por favor?
Kamiccolo

@Kamiccolo: lo que DuckWork describe es una acción MANUAL. Cortar y pegar los nombres de columna deseados. Simplemente dice que esta es una forma de obtener los nombres más fácilmente, sin tener que escribir mucho. No le ayuda a escribir una consulta que diga "excluir esta columna". Simplemente le ayuda a crear la lista deseada de columnas, que luego pega en su consulta.
ToolmakerSteve
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.