J'essaie d'utiliser une instruction select pour obtenir toutes les colonnes d'une certaine table MySQL sauf une. Existe-t-il un moyen simple de procéder?
EDIT: Il y a 53 colonnes dans ce tableau (PAS MON DESIGN)
J'essaie d'utiliser une instruction select pour obtenir toutes les colonnes d'une certaine table MySQL sauf une. Existe-t-il un moyen simple de procéder?
EDIT: Il y a 53 colonnes dans ce tableau (PAS MON DESIGN)
Réponses:
En fait, il existe un moyen, vous devez bien sûr avoir des autorisations 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 <table>, <database> and <columns_to_omit>
<column_name>
Dans les définitions mysql (manuel), cela n'existe pas. Mais si vous avez un très grand nombre de colonnes col1
, ... col100
, les éléments suivants peuvent être utiles:
DROP TABLE IF EXISTS temp_tb;
CREATE TEMPORARY TABLE ENGINE=MEMORY temp_tb SELECT * FROM orig_tb;
ALTER TABLE temp_tb DROP col_x;
SELECT * FROM temp_tb;
DROP TABLE IF EXISTS temp_tb;
Une vue fonctionnerait-elle mieux dans ce cas?
CREATE VIEW vwTable
as
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
Tu peux faire:
SELECT column1, column2, column4 FROM table WHERE whatever
sans obtenir column3, mais peut-être que vous cherchiez 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 comme nulle.
par exemple
SELECT *, NULL AS salary FROM users
salary
colonne. Mais comme il est récupéré après le *, il écrase l'original. Ce n'est pas joli, mais ça marche.
À 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 souhaitées. Cependant, si vous voulez beaucoup de colonnes, vous pouvez simplement 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 ne voulez que quelques colonnes. Si vous ne voulez que quatre colonnes, alors:
SELECT col3, col6, col45, col 52 FROM tbl
serait bien, mais si vous voulez 50 colonnes, alors tout code qui rend la requête deviendrait (trop?) difficile à lire.
En essayant les solutions de @Mahomedalid et @Junaid, j'ai trouvé un problème. Alors j'ai pensé à le partager. Si le nom de la colonne contient des espaces ou des tirets comme l'archivage, la requête échoue. La solution de contournement simple consiste à utiliser la barre oblique inverse autour des noms de colonne. 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 énorme quantité 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 seul champ que vous ne sélectionnez généralement pas avec une clé de la table d'origine et supprimez le champ de la table d'origine. Rejoignez les tables lorsque ce champ supplémentaire est réellement requis.
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 le nombre de colonnes que j'obtiens en joignant des tables. Bien que ce ne soit pas la réponse à votre question (comment sélectionner toutes les colonnes, sauf certaines, d' une même table), je pense qu'il convient de mentionner que vous pouvez spécifier d'obtenir toutes les colonnes d'une table particulière, au lieu de simplement spécifier .table.
Voici un exemple de la façon dont cela pourrait être très utile:
sélectionnez les utilisateurs. *, phone.meta_value comme téléphone, zipcode.meta_value comme zipcode des utilisateurs joindre à gauche user_meta comme téléphone on ((users.user_id = phone.user_id) AND (phone.meta_key = 'phone')) rejoindre à gauche user_meta comme code postal on ((users.user_id = zipcode.user_id) AND (zipcode.meta_key = 'zipcode')))
Le résultat est toutes les colonnes de la table des utilisateurs et deux colonnes supplémentaires qui ont été jointes à partir de la méta-table.
J'ai aimé la réponse de d' @Mahomedalid
ailleurs ce fait informé dans le commentaire de @Bill Karwin
. Le problème possible soulevé par @Jan Koritak
est vrai, j'ai fait face à cela, mais j'ai trouvé une astuce pour cela et je veux juste le partager ici pour toute personne confrontée au problème.
nous pouvons remplacer la fonction REPLACE par la clause where dans la sous-requête de l'instruction Prepared comme ceci:
Utilisation de 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 uniquement le champ id
mais pascompany_id
Il est recommandé de spécifier les colonnes que vous interrogez même si vous interrogez toutes les colonnes.
Je vous suggère donc d'écrire le nom de chaque colonne dans la déclaration (à l'exclusion de celle que vous ne voulez pas).
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
Fais juste
SELECT * FROM table WHERE whatever
Déposez ensuite 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 suis d'accord avec la solution "simple" consistant à répertorier toutes les colonnes, mais cela peut être fastidieux et les fautes de frappe peuvent entraîner beaucoup de perte de temps. J'utilise une fonction "getTableColumns" pour récupérer les noms de mes colonnes pouvant être collés dans une requête. Ensuite, tout ce que je dois faire est de supprimer ceux dont 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 séparée par des virgules, par exemple ...
col1, col2, col3, col4, ... col53
Oui, bien qu'il puisse y avoir des E / S élevées selon 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
Je suis d'accord qu'il ne suffit pas Select *
, si celui dont vous n'avez pas besoin, comme mentionné ailleurs, est un BLOB, vous ne voulez pas que cette surcharge s'introduise.
Je créerais une vue avec les données requises, alors vous pouvez Select *
dans le confort - si le logiciel de base de données les prend en charge. Sinon, mettez les énormes données dans un autre tableau.
Au début, je pensais que vous pouviez utiliser des expressions régulières, mais comme j'ai lu les documents MYSQL, il semble que vous ne puissiez pas. Si j'étais vous, j'utiliserais un autre langage (tel que PHP) pour générer une liste de colonnes que vous souhaitez obtenir, le stocker sous forme de chaîne, puis l'utiliser pour générer le SQL.
Je le voulais aussi, j'ai donc 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)."`";
}
}
Donc, comment cela fonctionne, c'est que vous entrez dans la table, puis une colonne que vous ne voulez pas ou comme dans un tableau: tableau ("id", "nom", "quelle que soit la colonne")
Donc, dans select, 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");
Je suis d'accord avec 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 idiote.
Allez dans le tableau dans phpmyadmin-> sql-> sélectionnez, il vide la requête: copiez, remplacez et c'est fait! :)
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 presque aucune donnée. S'il contient d'énormes quantités de texte, des objets XML ou des objets binaires binaires, prenez le temps de sélectionner chaque colonne individuellement. Votre performance en souffrira autrement. À votre santé!
La réponse publiée par Mahomedalid a un petit problème:
Le code de fonction de remplacement interne remplaçait "<columns_to_delete>,
" par "", ce remplacement a un problème si le champ à remplacer est le dernier de la chaîne de concaténation car le 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 sauvegarder la mémoire. (Le champ que je supprimais est un BLOB d'environ 1 Mo)
Sur la base de la réponse de @Mahomedalid, j'ai apporté quelques améliorations pour prendre en charge "sélectionner toutes les colonnes sauf certaines dans 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 colonnes, utilisez ce SQL pour changer group_concat_max_len
SET @@group_concat_max_len = 2048;
Peut-être ai-je une solution à l' écart signalé par Jan Koritak
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' );
Table :
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'
Si c'est toujours la même colonne, vous pouvez créer une vue qui ne la contient pas.
Sinon, non, je ne pense pas.
Vous pouvez utiliser SQL pour générer du 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 colonne du schéma d'informations. Voici un exemple de la ligne de commande Unix.
Substitution
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 façon qu'une seule fois pour construire la liste des colonnes excluant 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)
Vous pouvez maintenant réutiliser la $column_list
chaîne dans les requêtes que vous construisez.
Je voudrais ajouter un autre point de vue afin de résoudre ce problème, surtout si vous avez un petit nombre de colonnes à supprimer.
Vous pouvez utiliser un outil de base de données 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, la façon de le générer est:
Cliquez avec le bouton droit sur le tableau -> envoyer à l'Éditeur SQL -> Sélectionner toute la déclaration.
La réponse acceptée présente plusieurs lacunes.
Tous ces problèmes peuvent être surmontés en incluant simplement des backticks dans le SEPARATOR
for your GROUP_CONCAT
et en utilisant une WHERE
condition à la place de REPLACE()
. Pour mes besoins (et j'imagine beaucoup d'autres), je voulais que les noms des colonnes soient retournés dans le même ordre qu'ils apparaissent dans le tableau lui-même. Pour ce faire, nous utilisons ici une ORDER BY
clause explicite à l' intérieur de la GROUP_CONCAT()
fonction:
SELECT CONCAT(
'SELECT `',
GROUP_CONCAT(COLUMN_NAME ORDER BY `ORDINAL_POSITION` SEPARATOR '`,`'),
'` FROM `',
`TABLE_SCHEMA`,
'`.`',
TABLE_NAME,
'`;'
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE `TABLE_SCHEMA` = 'my_database'
AND `TABLE_NAME` = 'my_table'
AND `COLUMN_NAME` != 'column_to_omit';
Je suis assez tard pour trouver une réponse à cela, c'est comme ça que je l'ai toujours fait et franchement, c'est 100 fois mieux et plus net 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
déclaration ici - le mot ne se produit même pas une seule fois.
Select * est un antipattern SQL. Il ne doit pas être utilisé dans le code de production pour de nombreuses raisons, notamment:
Le traitement prend un tout petit peu plus de temps. Lorsque les choses sont exécutées des millions de fois, ces minuscules morceaux peuvent être importants. 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 des goulots d'étranglement du serveur et du réseau. Si vous avez une jointure interne, les chances d'envoyer plus de données que vous n'en avez besoin sont de 100%.
Cela provoque des problèmes de maintenance, en particulier lorsque vous avez ajouté de nouvelles colonnes que vous ne souhaitez pas voir partout. De plus, si vous avez une nouvelle colonne, vous devrez peut-être faire quelque chose à l'interface pour déterminer quoi faire avec cette colonne.
Il peut casser des vues (je sais que cela est vrai dans le serveur SQl, cela peut ou peut ne pas être vrai dans mysql).
Si quelqu'un est assez idiot pour reconstruire les tables avec les colonnes dans un ordre différent (ce que vous ne devriez pas faire mais cela arrive tout le temps), toutes sortes de codes peuvent casser. Surtout codez pour un insert par exemple où soudainement vous mettez la ville dans le champ address_3 parce que sans préciser, la base de données ne peut aller que dans l'ordre des colonnes. C'est déjà assez mauvais lorsque les types de données changent, mais pire quand les colonnes échangées ont le même type de données, car vous pouvez parfois insérer des données incorrectes qui sont un gâchis à nettoyer. Vous devez vous soucier de l'intégrité des données.
S'il est utilisé dans une insertion, il cassera l'insertion si une nouvelle colonne est ajoutée dans une table mais pas dans l'autre.
Cela pourrait casser les déclencheurs. Les problèmes de déclenchement peuvent être difficiles à diagnostiquer.
Ajoutez tout cela au temps qu'il faut pour ajouter les noms des colonnes (diable, vous pouvez même avoir une interface qui vous permet de faire glisser les noms des colonnes (je sais que je le fais dans SQL Server, je parierais qu'il existe un moyen de faites ceci est un outil que vous utilisez pour écrire des requêtes mysql.) Voyons, "Je peux causer des problèmes de maintenance, je peux causer des problèmes de performances 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." dans les colonnes spécifiques que vous souhaitez.
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 & mots-clés = sql + antipatterns