web-dev-qa-db-fra.com

SQL exclut une colonne à l'aide de SELECT * [sauf columnA] FROM tableA?

Nous savons tous que pour sélectionner toutes les colonnes d’une table, nous pouvons utiliser

SELECT * FROM tableA

Est-il possible d'exclure une ou plusieurs colonnes d'une table sans spécifier toutes les colonnes?

SELECT * [except columnA] FROM tableA

Le seul moyen que je connaisse consiste à spécifier manuellement toutes les colonnes et à exclure la colonne non désirée. Cela prend beaucoup de temps, je cherche donc des moyens de gagner du temps et des efforts, ainsi que la maintenance future si le tableau comporte plus/moins de colonnes.

merci!

581
uuɐɯǝʃǝs

Je suis d'accord avec tout le monde ... mais si j'allais faire quelque chose comme ça, je pourrais le faire de cette façon:

/* 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
384
Norman Skinner

Non.

La meilleure pratique en matière de maintenance est de spécifier uniquement les colonnes requises.

Au moins 2 raisons:

  • Cela rend votre contrat entre le client et la base de données stable. Mêmes données, à chaque fois
  • Performance, couvrant les indices

Edit (juillet 2011):

Si vous faites glisser le nœud Columns d'une table à partir de l'explorateur d'objets, une liste CSV de colonnes de la fenêtre de requête vous permet d'atteindre l'un de vos objectifs

265
gbn

La manière automatisée de le faire en SQL (SQL Server) est la suivante:

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);
61
pl80

Si vous ne voulez pas écrire chaque nom de colonne manuellement, vous pouvez utiliser Script Table As en cliquant avec le bouton droit de la souris sur table ou view dans SSMS comme ceci:

enter image description here

Ensuite, vous obtiendrez la requête entière dans la fenêtre New Query Editor, puis supprimerez les colonnes non désirées comme ceci:

enter image description here

Terminé

54
hims056

Vous pouvez créer une vue contenant les colonnes que vous souhaitez sélectionner, puis vous pouvez simplement sélectionner * dans la vue ...

34
campo

Oui c'est possible (mais pas recommandé).

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')

Explication du code :

  1. Déclarez une variable pour stocker une liste de noms de colonnes séparée par des virgules. La valeur par défaut est NULL.
  2. Utilisez une vue système pour déterminer les noms des colonnes de notre table.
  3. Utilisez SELECT @variable = @variable + ... FROM pour concaténer les noms de colonnes Ce type de SELECT ne renvoie pas de jeu de résultats. Ceci est peut-être un comportement non documenté mais fonctionne dans toutes les versions de SQL Server. Vous pouvez également utiliser SET @variable = (SELECT ... FOR XML PATH('')) pour concaténer des chaînes.
  4. Utilisez la fonction ISNULL pour insérer une virgule uniquement s'il ne s'agit pas du premier nom de colonne Utilisez la fonction QUOTENAME pour prendre en charge les espaces et la ponctuation dans les noms de colonne.
  5. Utilisez la clause WHERE pour masquer les colonnes que nous ne voulons pas voir.
  6. Utilisez EXEC (@variable), également appelé dynamic SQL, pour résoudre les noms de colonnes Au moment de l'exécution. Cela est nécessaire car nous ne connaissons pas les noms des colonnes au moment de la compilation.
22
Anthony Faull

Comme les autres l’ont dit, il n’existe aucun moyen de le faire, mais si vous utilisez Sql Server, une astuce que j’utilise consiste à modifier la sortie en virgule séparée, 

select top 1 * from table

et couper toute la liste des colonnes de la fenêtre de sortie. Ensuite, vous pouvez choisir les colonnes que vous voulez sans avoir à toutes les taper.

17
MrTelly

En gros, vous ne pouvez pas faire ce que vous voulez, mais vous pouvez vous procurer les bons outils pour vous aider à rendre les choses un peu plus faciles.

Si vous consultez l'invite SQL de Red-Gate , vous pouvez taper "SELECT * FROM MyTable", puis déplacer le curseur après le "*" et appuyer sur <TAB> pour développer la liste des champs, puis supprimer ces quelques champs dont vous n'avez pas besoin.

Ce n'est pas une solution parfaite - mais une sacrément bonne! :-) Dommage, Intellisense de MS SQL Server Management Studio n’est toujours pas assez intelligent pour offrir cette fonctionnalité .......

Marc

11
marc_s

Dans SQL Management Studio, vous pouvez développer les colonnes dans l'Explorateur d'objets, puis faire glisser l'élément d'arborescence Columns dans une fenêtre de requête pour obtenir une liste de colonnes séparée par des virgules.

7
cjk

non, il n'y a pas moyen de faire ça. peut-être pouvez-vous créer des vues personnalisées si cela est réalisable dans votre cas

EDITPeut-être si votre base de données prend en charge l'exécution de sql dynamique, vous pouvez écrire un SP et transmettre les colonnes à ne pas vouloir voir. Laissez-le créer la requête de manière dynamique et renvoyer le résultat. à toi. Je pense que cela est faisable dans SQL Server au moins

7
Ali Kazmi

Si vous utilisez SQL Server Management Studio, procédez comme suit:

  1. Tapez le nom de votre table et sélectionnez-le
  2. Presse Alt+F1
  3. o/p montre les colonnes du tableau.
  4. Sélectionnez les colonnes souhaitées
  5. Copier et coller ceux de votre requête sélectionnée
  6. Lance la requête.

Prendre plaisir.

7
asdasdasd
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)

METTRE À JOUR:

Vous pouvez également créer une procédure stockée pour prendre en charge cette tâche si vous l'utilisez plus souvent . Dans cet exemple, j'ai utilisé la fonction intégrée STRING_SPLIT () disponible sur SQL Server 2016 +,. .mais si vous en avez besoin, il existe de nombreux exemples sur la manière de le créer manuellement sur 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

Et puis juste:

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

En résumé, vous ne pouvez pas le faire, mais je suis en désaccord avec tous les commentaires ci-dessus, il existe des scénarios dans lesquels vous pouvez légitimement utiliser un * Lorsque vous créez une requête imbriquée afin de sélectionner une plage spécifique dans une liste complète (pagination, par exemple), pourquoi dans le monde voudrait-il spécifier chaque colonne de l'instruction de sélection externe alors que vous l'avez faite à l'intérieur?

6
Useless Hasid

Existe-t-il un moyen d'exclure une ou plusieurs colonnes d'une table sans spécifier toutes les colonnes?

Utiliser le SQL déclaratif de la manière habituelle, non.

Je pense que votre syntaxe proposée est digne et bonne. En fait, le langage de base de données relationnelle 'Tutorial D' a une syntaxe très similaire, les mots-clés ALL BUT étant suivis d'un ensemble d'attributs (colonnes).

Cependant, le code SELECT * de SQL est déjà très critiqué (la réponse de @ Guffa étant une objection typique), je ne pense donc pas que SELECT ALL BUT entrera dans le standard SQL de si tôt. 

Je pense que la meilleure solution consiste à créer une VIEW avec uniquement les colonnes souhaitées, puis SELECT * FROM ThatView.

5
onedaywhen

Si nous parlons de procédures, cette astuce permet de générer une nouvelle requête et EXECUTE IMMEDIATE it

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
AlexandreWL

Je ne connais aucune base de données qui le supporte (SQL Server, MySQL, Oracle, PostgreSQL). Cela ne fait certainement pas partie des standards SQL, je pense donc que vous devez spécifier uniquement les colonnes souhaitées.

Vous pouvez bien sûr construire votre instruction SQL de manière dynamique et le faire exécuter par le serveur. Mais cela ouvre la possibilité d'injection SQL.

3

Je sais que c'est un peu vieux, mais je venais de rencontrer le même problème et je cherchais une réponse. Ensuite, un développeur senior m'a montré un truc très simple.

Si vous utilisez l'éditeur de requête de Management Studio, développez la base de données, puis développez le tableau que vous avez sélectionné pour que vous puissiez voir le dossier Colonnes.

Dans votre instruction select, sélectionnez simplement le dossier des colonnes référencées ci-dessus, puis faites-le glisser et déposez-le dans la fenêtre de requête. Il va coller toutes les colonnes de la table, puis simplement simplement supprimer la colonne d'identité de la liste des colonnes ...

3
anonymous

Eh bien, il est de pratique courante de spécifier les colonnes de votre choix plutôt que de spécifier *. Vous devez donc simplement indiquer les champs que vous souhaitez que votre sélection retourne.

2
Gustavo

Un collègue a conseillé une bonne alternative:

  • Faites SELECT INTO dans votre requête précédente (où vous générez ou obtenez les données d) dans une table (que vous supprimerez une fois terminé). Cela créera la structure pour vous. 
  • Faites un script en tant que CREATE pour une nouvelle requête Window. 
  • Supprimez les colonnes indésirables. Formatez les colonnes restantes Dans un support et collez-les en tant que liste de colonnes. 
  • Supprimez le tableau que vous avez créé.

Terminé...

Cela nous a beaucoup aidé.

2
Charl

Postgres sql a le moyen de le faire 

veuillez vous reporter à: http://www.postgresonline.com/journal/archives/41-How-tow-toLECT-ALL-EXCEPT-some-columns-in-a-table.html

Le schéma d'information 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

Le tableau ci-dessus pour mon exemple particulier - génère une instruction SQL ressemblant à ceci

SELECT o.officepark, o.owner, o.squarefootage DE officepark as o

1
user3393089

Le meilleur moyen de résoudre ce problème consiste à utiliser view, vous pouvez créer une vue avec les colonnes requises et récupérer les données à partir

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)
1
Mahesh Madushanka

Parfois, le même programme doit gérer différentes structures de base de données. Je ne pouvais donc pas utiliser une liste de colonnes dans le programme pour éviter les erreurs dans les instructions select.

* me donne tous les champs optionnels. Je vérifie si les champs existent dans la table de données avant utilisation. C'est la raison pour laquelle j'ai utilisé * dans select.

Voici comment je gère les champs exclus:

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
1
Dusan

C'est ce que j'utilise souvent pour ce cas:

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 ressemble à column1,column2,column5

1
Valeriy

Faites un clic droit sur la table dans l'explorateur d'objets, sélectionnez les 1000 premières lignes

Il listera toutes les colonnes et pas *. Supprimez ensuite les colonnes indésirables. Devrait être beaucoup plus rapide que de le taper soi-même.

Ensuite, lorsque vous estimez que cela représente un peu trop de travail, procurez-vous l'invite SQL de Red Gate et tapez ssf à partir de tbl, accédez à * et cliquez à nouveau sur l'onglet.

1
cairnz

La réponse proposée (procédure stockée) de BartoszX ne fonctionnait pas pour moi lorsque j'utilisais une vue plutôt qu'une table réelle.

Le crédit pour l'idée et le code ci-dessous (à l'exception de mon correctif) appartient à BartoszX.

Pour que cela fonctionne pour les tables ainsi que pour les vues, utilisez le code suivant:

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[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)
 AND ss.[value] IS NULL;

 SELECT @SQL = N'SELECT ' + @SQL + N' FROM ' + @full_table_name;
 EXEC(@SQL)
END
GO
0
Michael Hafner

Ne serait-il pas plus simple de faire ceci:

sp_help <table_name>

-Cliquez sur la colonne 'Nom_Colonne'> Copier> Coller (crée une liste verticale) dans une fenêtre Nouvelle requête et tapez des virgules devant chaque valeur de colonne ... commentez les colonnes que vous ne voulez pas ... beaucoup moins en tapant que n'importe quel code proposé ici et toujours gérable.

0
plo

Je sais que cette question est ancienne, mais j'espère que cela pourra toujours être utile. La réponse est inspirée par une discussion de SQL Server Forums 1 . Vous pouvez en faire une procédure stockée. Il peut également être modifié pour en ajouter plusieurs, à l'exception des champs. La première colonne ne peut cependant pas être l'exception.

Declare @TBNAME sysname, @SQL NVARCHAR(MAX), @Exception VARCHAR(500)

SET @TBNAME = 'tableName'
SET @Exception = 'columnName'

SELECT @SQL = COALESCE(@SQL + '', '') + SQL FROM (
SELECT 'SELECT ' + COLUMN_NAME As SQL, 1 As SQLGroup
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_NAME = @TBNAME AND ORDINAL_POSITION = 1
UNION ALL
SELECT ', ' + COLUMN_NAME As SQL, 2 As SQLGroup
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_NAME = @TBNAME AND ORDINAL_POSITION <> 1 AND COLUMN_NAME <> @Exception
UNION ALL
SELECT ' FROM ' + TABLE_NAME As SQL, 3 As SQLGroup 
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = @TBNAME
) As S
ORDER BY SQLGroup

SELECT @SQL  --OR EXEC sp_executesql @SQL

Après avoir posté la solution ci-dessus, j'ai eu une meilleure idée: 

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
0
kakugiki

Vous pouvez obtenir SQL Complete à partir de devart.com, qui non seulement étend le caractère générique * comme le fait l’invite SQL de Red Gate (comme décrit dans la réponse de cairnz), mais fournit également une liste déroulante de sélecteurs de colonnes avec des cases à cocher permettant de vérifier toutes les informations. colonnes que vous voulez dans la liste de sélection et elles seront automatiquement insérées (et si vous décochez ensuite une colonne, elle sera automatiquement supprimée de la liste de sélection).

0
yoel halb

Cela ne vous fera pas gagner du temps lors du chargement depuis la base de données. Mais vous pouvez toujours désélectionner la colonne que vous ne voulez pas dans le tableau dans lequel elle est placée. J'avais plusieurs colonnes dans une table mais je ne voulais pas d'une en particulier. J'étais trop paresseux pour tout écrire dans l'instruction SELECT. 

$i=0;
$row_array = array();

while($row = mysqli_fetch_assoc($result)){

  $row_array[$i]=$row;
  unset($row_array[$i]['col_name']);
  $i++;
}
0
user3904583

Je l'ai fait comme ça et ça marche très bien (version 5.5.41):

# prepare column list using info from a table of choice
SET @dyn_colums = (SELECT REPLACE(
GROUP_CONCAT(`COLUMN_NAME`), ',column_name_to_remove','') 
FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE 
`TABLE_SCHEMA`='database_name' AND `TABLE_NAME`='table_name');

# set sql command using prepared columns
SET @sql = CONCAT("SELECT ", @dyn_colums, " FROM table_name");

# prepare and execute
PREPARE statement FROM @sql;
EXECUTE statement;
0

Si quelqu'un utilise MySql, comme moi, j'utilise ceci

CREATE TABLE TempTable AS SELECT * FROM #YourTable; 

ALTER TABLE TempTable 
DROP COLUMN #YourColumn; 

SELECT * FROM TempTable; 
DROP TABLE TempTable;
0
Felix

Dans SSMS, il existe un moyen plus simple avec IntelliSense et Aliasing . Essaye ça

  1. Cliquez avec le bouton droit dans l'éditeur de texte et assurez-vous que IntelliSense est activé.
  2. Tapez la requête avec un alias [SELECT t. * FROM nom_table t] .
  3. Allez dans le texte t. * et supprimez le * , et SSMS listera automatiquement les colonnes de la table f alias .
Vous pouvez ensuite spécifier rapidement uniquement les colonnes de votre choix sans devoir utiliser SSMS pour écrire une sélection sur un autre script, puis effectuer plusieurs opérations de copier/coller .

0
Michael Barash