Sélectionnez Toutes les colonnes sauf une dans MySQL?
J'essaie d'utiliser une instruction select pour obtenir toutes les colonnes d'une certaine table MySQL sauf une. Est-il un moyen simple de faire cela?
EDIT: il y a 53 colonnes dans ce tableau (pas mon DESIGN)
28 réponses
En fait, il y a un moyen, vous devez avoir des autorisations bien sûr pour le faire ...
SET @sql = CONCAT('SELECT ', (SELECT REPLACE(GROUP_CONCAT(COLUMN_NAME), '<columns_to_omit>,', '') FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '<table>' AND TABLE_SCHEMA = '<database>'), ' FROM <table>');
PREPARE stmt1 FROM @sql;
EXECUTE stmt1;
Remplacement de <table>, <database> and <columns_to_omit>
Une vue fonctionnerait-elle mieux dans ce cas?
CREATE VIEW vwTable
as
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
Dans les définitions mysql (manual), il n'y a pas une telle chose. Mais si vous avez un très grand nombre de colonnes col1
,..., col100
, ce qui suit peut être utile:
mysql> CREATE TEMPORARY TABLE temp_tb SELECT * FROM orig_tb;
mysql> ALTER TABLE temp_tb DROP col_x;
mysql> SELECT * FROM temp_tb;
Vous pouvez faire:
SELECT column1, column2, column4 FROM table WHERE whatever
Sans obtenir column3, bien que vous cherchiez peut-être une solution plus générale?
Si vous cherchez à exclure la valeur d'un champ, par exemple pour des problèmes de sécurité / informations sensibles, vous pouvez récupérer cette colonne en tant que null.
Par exemple
SELECT *, NULL AS salary FROM users
Au meilleur de ma connaissance, il n'y en a pas. vous pouvez faire quelque chose comme:
SELECT col1, col2, col3, col4 FROM tbl
Et choisissez manuellement les colonnes que vous voulez. Cependant, si vous voulez beaucoup de colonnes, alors vous voudrez peut-être juste faire un:
SELECT * FROM tbl
Et ignorez simplement ce que vous ne voulez pas.
Dans votre cas particulier, je suggère:
SELECT * FROM tbl
, Sauf si vous voulez seulement quelques colonnes. Si vous voulez seulement quatre colonnes, alors:
SELECT col3, col6, col45, col 52 FROM tbl
Serait bien, mais si vous voulez 50 colonnes, alors tout code qui fait le requête deviendrait (trop? difficile à lire.
En essayant les solutions par @ Mahomedalid et @ Junaid j'ai trouvé un problème. Alors pensé à le partager. Si le nom de la colonne a des espaces ou des tirets comme l'enregistrement, la requête échouera. La solution de contournement simple consiste à utiliser backtick autour des noms de colonnes. La requête modifiée est ci-dessous
SET @SQL = CONCAT('SELECT ', (SELECT GROUP_CONCAT(CONCAT("`", COLUMN_NAME, "`")) FROM
INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'users' AND COLUMN_NAME NOT IN ('id')), ' FROM users');
PREPARE stmt1 FROM @SQL;
EXECUTE stmt1;
Si la colonne que vous ne vouliez pas sélectionner contenait une quantité massive de données et que vous ne vouliez pas l'inclure en raison de problèmes de vitesse et que vous sélectionnez souvent les autres colonnes, je vous suggère de créer une nouvelle table avec le champ que vous ne sélectionnez pas habituellement avec une clé de la table d'origine et de supprimer le champ de la table d'origine. Joindre les tables lorsque ce champ supplémentaire est nécessaire.
Vous pouvez utiliser DESCRIBE my_table et en utiliser les résultats pour générer dynamiquement L'instruction SELECT.
Mon principal problème est les nombreuses colonnes que je reçois en joignant des tables. Bien que ce ne soit pas la réponse à votre question (Comment sélectionner toutes les colonnes sauf Certaines de une table), je pense qu'il vaut la peine de mentionner que vous pouvez spécifier table.
pour obtenir toutes les colonnes d'une table particulière, au lieu de simplement spécifier .
Voici un exemple de comment cela pourrait être très utile:
select users.*, phone.meta_value as phone, zipcode.meta_value as zipcode from users left join user_meta as phone on ( (users.user_id = phone.user_id) AND (phone.meta_key = 'phone') ) left join user_meta as zipcode on ( (users.user_id = zipcode.user_id) AND (zipcode.meta_key = 'zipcode') )
Le résultat est toutes les colonnes de la table users, et deux colonnes supplémentaires qui étaient joint à partir de la table meta.
J'ai aimé la réponse de @Mahomedalid
en plus de ce fait informé dans le commentaire de @Bill Karwin
. Le problème possible soulevé par @Jan Koritak
est vrai que j'ai fait face à cela, mais j'ai trouvé un truc pour cela et je veux juste le partager ici pour tous ceux qui font face au problème.
Nous pouvons remplacer la fonction REPLACE par la clause where dans la sous-requête de L'instruction préparée comme ceci:
En utilisant mon nom de table et de colonne
SET @SQL = CONCAT('SELECT ', (SELECT GROUP_CONCAT(COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'users' AND COLUMN_NAME NOT IN ('id')), ' FROM users');
PREPARE stmt1 FROM @SQL;
EXECUTE stmt1;
Donc, cela va exclure que le champ id
, mais pas company_id
Espoir cela aidera tous ceux qui recherchent une solution.
Cordialement
, Il est recommandé de spécifier les colonnes que vous interrogez, même si vous interrogez toutes les colonnes.
Donc, je vous suggère d'écrire le nom de chaque colonne dans l'instruction (à l'exclusion de celle que vous ne voulez pas).
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
Je suis d'accord avec la solution "simple" de lister toutes les colonnes, mais cela peut être lourd, et les fautes de frappe peuvent causer beaucoup de temps perdu. J'utilise une fonction "getTableColumns" pour récupérer les noms de mes colonnes appropriées pour coller dans une requête. Ensuite, tout ce que je dois faire est de supprimer ceux que je ne veux pas.
CREATE FUNCTION `getTableColumns`(tablename varchar(100))
RETURNS varchar(5000) CHARSET latin1
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE res VARCHAR(5000) DEFAULT "";
DECLARE col VARCHAR(200);
DECLARE cur1 CURSOR FOR
select COLUMN_NAME from information_schema.columns
where TABLE_NAME=@table AND TABLE_SCHEMA="yourdatabase" ORDER BY ORDINAL_POSITION;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur1;
REPEAT
FETCH cur1 INTO col;
IF NOT done THEN
set res = CONCAT(res,IF(LENGTH(res)>0,",",""),col);
END IF;
UNTIL done END REPEAT;
CLOSE cur1;
RETURN res;
Votre résultat renvoie une chaîne délimitée par des virgules, par exemple...
Col1,col2,col3,col4,...col53
Je suis d'accord qu'il ne suffit pas de Select *
, si celui dont vous n'avez pas besoin, comme mentionné ailleurs, est un BLOB, vous ne voulez pas avoir ce fluage aérien.
Je créerais une vue avec les données requises, alors vous pouvez Select *
dans comfort-si le logiciel de base de données les supporte. Sinon, mettez les énormes données dans une autre table.
Au début, je pensais que vous pouviez utiliser des expressions régulières, mais comme j'ai lu les documents MYSQL {[2] } il semble que vous ne pouvez pas. si j'étais vous, j'utiliserais un autre langage (tel que PHP) pour générer une liste de colonnes que vous voulez obtenir, la stocker sous forme de chaîne et ensuite l'utiliser pour générer le SQL.
Faites juste
SELECT * FROM table WHERE whatever
Ensuite, déposez la colonne dans votre langage de programmation préféré: php
while (($data = mysql_fetch_array($result, MYSQL_ASSOC)) !== FALSE) {
unset($data["id"]);
foreach ($data as $k => $v) {
echo"$v,";
}
}
Je le voulais aussi alors j'ai créé une fonction à la place.
public function getColsExcept($table,$remove){
$res =mysql_query("SHOW COLUMNS FROM $table");
while($arr = mysql_fetch_assoc($res)){
$cols[] = $arr['Field'];
}
if(is_array($remove)){
$newCols = array_diff($cols,$remove);
return "`".implode("`,`",$newCols)."`";
}else{
$length = count($cols);
for($i=0;$i<$length;$i++){
if($cols[$i] == $remove)
unset($cols[$i]);
}
return "`".implode("`,`",$cols)."`";
}
}
Alors, comment cela fonctionne est que vous entrer dans le tableau, puis une colonne, vous ne voulez pas, ou comme dans un tableau: array("id","nom","whatevercolumn")
, de Sorte à sélectionner, vous pouvez l'utiliser comme ceci:
mysql_query("SELECT ".$db->getColsExcept('table',array('id','bigtextcolumn'))." FROM table");
Ou
mysql_query("SELECT ".$db->getColsExcept('table','bigtextcolumn')." FROM table");
Bien que je sois d'accord avec la réponse de Thomas (+1 ;)), Je voudrais ajouter la mise en garde que je suppose que la colonne que vous ne voulez pas contient pratiquement aucune donnée. Si elle contient d'énormes quantités de texte, xml ou binaire gouttes, puis prendre le temps de sélectionner chaque colonne individuellement. Votre performance en souffrira autrement. À votre santé!
Oui, bien qu'il puisse être élevé e / s en fonction de la table voici une solution de contournement que j'ai trouvée pour cela.
Select *
into #temp
from table
alter table #temp drop column column_name
Select *
from #temp
La réponse Postée par Mahomedalid a un petit problème:
À l'intérieur du code de fonction replace remplaçait "<columns_to_delete>,
" par "", ce remplacement a un problème si le champ à remplacer est le dernier dans la chaîne concat en raison du dernier n'a pas la virgule char", " et n'est pas supprimé de la chaîne.
Ma proposition:
SET @sql = CONCAT('SELECT ', (SELECT REPLACE(GROUP_CONCAT(COLUMN_NAME),
'<columns_to_delete>', '\'FIELD_REMOVED\'')
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = '<table>'
AND TABLE_SCHEMA = '<database>'), ' FROM <table>');
Remplacement <table>
, <database>
et `
La colonne supprimée est remplacée par la chaîne "FIELD_REMOVED" dans mon cas, cela fonctionne parce que j'essayais de coffre-fort de la mémoire. (Le champ que je supprimais est un BLOB d'environ 1 Mo)
Basé sur la réponse @Mahomedalid, j'ai fait quelques améliorations pour supporter "select all columns except some in mysql"
SET @database = 'database_name';
SET @tablename = 'table_name';
SET @cols2delete = 'col1,col2,col3';
SET @sql = CONCAT(
'SELECT ',
(
SELECT GROUP_CONCAT( IF(FIND_IN_SET(COLUMN_NAME, @cols2delete), NULL, COLUMN_NAME ) )
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tablename AND TABLE_SCHEMA = @database
),
' FROM ',
@tablename);
SELECT @sql;
Si vous avez beaucoup de cols, utilisez ce sql pour modifier group_concat_max_len
SET @@group_concat_max_len = 2048;
Peut-être que j'ai une solution à de Jan Koritak a souligné la divergence
SELECT CONCAT('SELECT ',
( SELECT GROUP_CONCAT(t.col)
FROM
(
SELECT CASE
WHEN COLUMN_NAME = 'eid' THEN NULL
ELSE COLUMN_NAME
END AS col
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'employee' AND TABLE_SCHEMA = 'test'
) t
WHERE t.col IS NOT NULL) ,
' FROM employee' );
Tableau :
SELECT table_name,column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'employee' AND TABLE_SCHEMA = 'test'
================================
table_name column_name
employee eid
employee name_eid
employee sal
================================
Résultat De La Requête:
'SELECT name_eid,sal FROM employee'
D'accord sur la réponse de @Mahomedalid. Mais je ne voulais pas faire quelque chose comme une déclaration préparée et je ne voulais pas taper tous les champs. Donc, ce que j'avais était une solution stupide. Allez à la table dans phpmyadmin- > sql - > select, il vide la copie de requête remplacer et fait! :)
Si c'est toujours la même colonne, vous pouvez créer une vue qui ne l'a pas.
Sinon, Non, Je ne pense pas.
Vous pouvez utiliser SQL pour générer SQL si vous le souhaitez et évaluer le SQL qu'il produit. Il s'agit d'une solution générale car elle extrait les noms de colonnes du schéma d'informations. Voici un exemple de la ligne de commande Unix.
Substitution de
- MYSQL avec votre commande mysql
- TABLE avec le nom de la table
- EXCLUDEDFIELD avec le nom du champ exclu
echo $(echo 'select concat("select ", group_concat(column_name) , " from TABLE") from information_schema.columns where table_name="TABLE" and column_name != "EXCLUDEDFIELD" group by "t"' | MYSQL | tail -n 1) | MYSQL
Vous n'aurez vraiment besoin d'extraire les noms de colonne de cette manière qu'une seule fois pour construire le la liste des colonnes a exclu cette colonne, puis utilisez simplement la requête que vous avez construite.
Donc quelque chose comme:
column_list=$(echo 'select group_concat(column_name) from information_schema.columns where table_name="TABLE" and column_name != "EXCLUDEDFIELD" group by "t"' | MYSQL | tail -n 1)
Maintenant, vous pouvez réutiliser la chaîne $column_list
dans les requêtes que vous construisez.
Je voudrais ajouter un autre point de vue pour résoudre ce problème, spécialement si vous avez un petit nombre de colonnes à supprimer.
Vous pouvez utiliser un outil DB comme MySQL Workbench afin de générer l'instruction select pour vous, il vous suffit donc de supprimer manuellement ces colonnes pour l'instruction générée et de la Copier dans votre script SQL.
Dans MySQL Workbench, le moyen de le générer est:
Faites un clic droit sur la table - > Envoyer à L'éditeur Sql - > Tout sélectionner Déclaration.
Je suis assez tard pour trouver une réponse à cela, mettez ceci est la façon dont je l'ai toujours fait et franchement, c'est 100 fois mieux et plus propre que la meilleure réponse, j'espère seulement que quelqu'un le verra. Et trouvez-le utile
//create an array, we will call it here.
$here = array();
//create an SQL query in order to get all of the column names
$SQL = "SHOW COLUMNS FROM Table";
//put all of the column names in the array
foreach($conn->query($SQL) as $row) {
$here[] = $row[0];
}
//now search through the array containing the column names for the name of the column, in this case i used the common ID field as an example
$key = array_search('ID', $here);
//now delete the entry
unset($here[$key]);
Select * est un antipattern SQL. Il ne devrait pas être utilisé dans le code de production pour de nombreuses raisons, y compris:
Cela prend un peu plus de temps à traiter. Quand les choses sont exécutées des millions de fois, ces petits morceaux peuvent avoir de l'importance. Une base de données lente où la lenteur est causée par ce type de codage bâclé est le type le plus difficile à régler.
Cela signifie que vous envoyez probablement plus de données que nécessaire, ce qui provoque à la fois des goulots d'étranglement sur le serveur et le réseau. Si vous avez une jointure intérieure, les chances d'envoyer plus de données que vous avez besoin sont 100%.
Cela provoque des problèmes de maintenance surtout lorsque vous avez ajouté de nouvelles colonnes que vous ne voulez pas voir partout. Si en plus vous avez une nouvelle colonne, vous devrez peut-être faire quelque chose pour l'interface de déterminer quoi faire avec cette colonne.
Il peut casser des vues (Je sais que c'est vrai dans SQl server, il peut ou peut ne pas être vrai dans mysql).
Si quelqu'un est assez stupide pour reconstruire les tables avec les colonnes dans un différent ordre (ce que vous ne devriez pas faire mais cela arrive tout le temps), toutes sortes de code peuvent se casser. Espcially code pour un insert par exemple où soudainement vous mettez la ville dans le champ address_3 parce que sans spécifier, la base de données ne peut aller que dans l'ordre des colonnes. C'est assez mauvais quand les types de données changent mais pire quand les colonnes échangées ont le même type de données parce que vous pouvez aller parfois insérer des données mauvaises qui sont un gâchis à nettoyer. Vous devez vous soucier des données intégrité.
S'il est utilisé dans un insert, il va casser l'insert si une nouvelle colonne est ajoutée dans une table mais pas l'autre.
Il pourrait casser les déclencheurs. Les problèmes de déclenchement peuvent être difficiles à diagnostiquer.
Additionnez tout cela par rapport au temps nécessaire pour ajouter les noms de colonnes (heck vous pouvez même avoir une interface qui vous permet de faire glisser les noms de colonnes (je sais que je fais dans SQL Server, je parie qu'il y a un moyen de le faire est un outil que vous utilisez pour écrire des requêtes mysql.) Nous allons voir ," je peux causer des problèmes de maintenance, je peux causer des problèmes de performance et je peux causer des problèmes d'intégrité des données, mais bon, j'ai économisé cinq minutes de temps de développement."Vraiment juste mettre dans les colonnes spécifiques que vous voulez.
Je vous suggère également de lire ce livre: http://www.amazon.com/SQL-Antipatterns-Programming-Pragmatic-Programmers-ebook/dp/B00A376BB2/ref=sr_1_1?s=digital-text&ie=UTF8&qid=1389896688&sr=1-1&keywords=sql+antipatterns