Ich versuche, eine select-Anweisung zu verwenden, um alle Spalten außer einer aus einer bestimmten MySQL-Tabelle abzurufen. Gibt es eine einfache Möglichkeit, dies zu tun?
BEARBEITEN: Diese Tabelle enthält 53 Spalten (NICHT MEIN DESIGN)
Ich versuche, eine select-Anweisung zu verwenden, um alle Spalten außer einer aus einer bestimmten MySQL-Tabelle abzurufen. Gibt es eine einfache Möglichkeit, dies zu tun?
BEARBEITEN: Diese Tabelle enthält 53 Spalten (NICHT MEIN DESIGN)
Antworten:
Eigentlich gibt es einen Weg, dafür muss man natürlich Berechtigungen haben ...
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;
Ersetzen <table>, <database> and <columns_to_omit>
<column_name>
In MySQL-Definitionen (manuell) gibt es so etwas nicht. Wenn Sie jedoch eine wirklich große Anzahl von Spalten haben col1
, ..., col100
kann Folgendes hilfreich sein:
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;
Würde eine Ansicht in diesem Fall besser funktionieren?
CREATE VIEW vwTable
as
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
Du kannst tun:
SELECT column1, column2, column4 FROM table WHERE whatever
ohne Spalte3 zu bekommen, obwohl Sie vielleicht nach einer allgemeineren Lösung gesucht haben?
Wenn Sie den Wert eines Felds ausschließen möchten, z. B. aus Sicherheitsgründen / wegen vertraulicher Informationen, können Sie diese Spalte als null abrufen.
z.B
SELECT *, NULL AS salary FROM users
salary
Spalte hinzu. Da es jedoch nach dem * abgerufen wird, überschreibt es das Original. Es ist nicht schön, aber es funktioniert.
Nach meinem besten Wissen gibt es keine. Sie können so etwas tun wie:
SELECT col1, col2, col3, col4 FROM tbl
und wählen Sie die gewünschten Spalten manuell aus. Wenn Sie jedoch viele Spalten möchten, möchten Sie möglicherweise nur Folgendes ausführen:
SELECT * FROM tbl
und ignoriere einfach, was du nicht willst.
In Ihrem speziellen Fall würde ich vorschlagen:
SELECT * FROM tbl
es sei denn, Sie möchten nur ein paar Spalten. Wenn Sie nur vier Spalten möchten, dann:
SELECT col3, col6, col45, col 52 FROM tbl
wäre in Ordnung, aber wenn Sie 50 Spalten möchten, wird jeder Code, der die Abfrage macht, (auch?) schwer zu lesen.
Beim Ausprobieren der Lösungen von @Mahomedalid und @Junaid habe ich ein Problem gefunden. Also dachte ich daran, es zu teilen. Wenn der Spaltenname Leerzeichen oder Bindestriche wie beim Einchecken enthält, schlägt die Abfrage fehl. Die einfache Problemumgehung besteht darin, Backtick um Spaltennamen zu verwenden. Die geänderte Abfrage ist unten
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;
Wenn die Spalte, die Sie nicht auswählen wollten, eine große Datenmenge enthielt und Sie sie aufgrund von Geschwindigkeitsproblemen nicht einschließen wollten und Sie die anderen Spalten häufig auswählen, würde ich vorschlagen, dass Sie eine neue Tabelle erstellen mit dem einen Feld, das Sie normalerweise nicht mit einem Schlüssel zur Originaltabelle auswählen, und entfernen Sie das Feld aus der Originaltabelle. Verbinden Sie die Tabellen, wenn dieses zusätzliche Feld tatsächlich benötigt wird.
Sie können DESCRIBE my_table verwenden und die Ergebnisse daraus verwenden, um die SELECT-Anweisung dynamisch zu generieren.
Mein Hauptproblem sind die vielen Spalten, die ich beim Verbinden von Tabellen bekomme. Dies ist zwar nicht die Antwort auf Ihre Frage (wie man alle außer bestimmten Spalten aus einer Tabelle auswählt ), aber ich denke, es ist erwähnenswert, dass Sie angeben können, dass alle Spalten aus einer bestimmten Tabelle abgerufen werden sollen, anstatt nur anzugebentable.
.
Hier ist ein Beispiel, wie dies sehr nützlich sein kann:
Benutzer auswählen. *, phone.meta_value als Telefon, postleitzahl.meta_value als Postleitzahl von Benutzern left join user_meta als Telefon on ((users.user_id = phone.user_id) AND (phone.meta_key = 'phone')) left join user_meta als Postleitzahl on ((users.user_id = zipcode.user_id) AND (zipcode.meta_key = 'postleitzahl'))
Das Ergebnis sind alle Spalten aus der Benutzertabelle und zwei zusätzliche Spalten, die aus der Metatabelle zusammengefügt wurden.
Ich mochte die Antwort von @Mahomedalid
neben dieser Tatsache in Kommentar von informiert @Bill Karwin
. Das mögliche Problem, das sich daraus @Jan Koritak
ergibt, ist wahr, dass ich damit konfrontiert wurde, aber ich habe einen Trick dafür gefunden und möchte ihn hier nur für alle teilen, die mit dem Problem konfrontiert sind.
Wir können die REPLACE-Funktion durch die where-Klausel in der Unterabfrage der Prepared-Anweisung wie folgt ersetzen:
Verwenden Sie meinen Tabellen- und Spaltennamen
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;
Dies schließt also nur das Feld aus id
, nicht jedochcompany_id
Es wird empfohlen, die Spalten anzugeben, die Sie abfragen, auch wenn Sie alle Spalten abfragen.
Daher würde ich vorschlagen, dass Sie den Namen jeder Spalte in die Anweisung schreiben (mit Ausnahme derjenigen, die Sie nicht möchten).
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
Mach einfach
SELECT * FROM table WHERE whatever
Dann lassen Sie die Spalte in Ihrer bevorzugten Programmiersprache fallen: php
while (($data = mysql_fetch_array($result, MYSQL_ASSOC)) !== FALSE) {
unset($data["id"]);
foreach ($data as $k => $v) {
echo"$v,";
}
}
Ich bin mit der "einfachen" Lösung einverstanden, alle Spalten aufzulisten, aber dies kann lästig sein und Tippfehler können viel Zeitverschwendung verursachen. Ich verwende eine Funktion "getTableColumns", um die Namen meiner Spalten abzurufen, die zum Einfügen in eine Abfrage geeignet sind. Dann muss ich nur noch die löschen, die ich nicht will.
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;
Ihr Ergebnis gibt eine durch Kommas getrennte Zeichenfolge zurück, zum Beispiel ...
col1, col2, col3, col4, ... col53
Ich bin damit einverstanden, dass es nicht ausreicht Select *
, wenn dieser, den Sie nicht benötigen, wie an anderer Stelle erwähnt, ein BLOB ist, möchten Sie nicht, dass sich dieser Overhead einschleicht.
Ich würde eine Ansicht mit den erforderlichen Daten erstellen , dann können Sie Select *
bequem - wenn die Datenbanksoftware sie unterstützt. Andernfalls legen Sie die riesigen Daten in eine andere Tabelle.
Zuerst dachte ich, Sie könnten reguläre Ausdrücke verwenden, aber da ich die MYSQL-Dokumente gelesen habe, scheint es, dass Sie das nicht können. Wenn ich Sie wäre, würde ich eine andere Sprache (wie PHP) verwenden, um eine Liste der Spalten zu generieren, die Sie abrufen möchten, sie als Zeichenfolge speichern und diese dann zum Generieren von SQL verwenden.
Ich wollte das auch, also habe ich stattdessen eine Funktion erstellt.
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)."`";
}
}
So funktioniert es, wenn Sie die Tabelle eingeben, dann eine Spalte, die Sie nicht möchten, oder wie in einem Array: array ("id", "name", "Whatevercolumn")
In select können Sie es also folgendermaßen verwenden:
mysql_query("SELECT ".$db->getColsExcept('table',array('id','bigtextcolumn'))." FROM table");
oder
mysql_query("SELECT ".$db->getColsExcept('table','bigtextcolumn')." FROM table");
Ich stimme der Antwort von @ Mahomedalid zu, aber ich wollte nicht so etwas wie eine vorbereitete Aussage machen und ich wollte nicht alle Felder eingeben, also hatte ich eine dumme Lösung.
Gehen Sie zu der Tabelle in phpmyadmin-> sql-> select, es wird die Abfrage ausgegeben: kopieren, ersetzen und fertig! :) :)
Obwohl ich der Antwort von Thomas (+1;)) zustimme, möchte ich den Vorbehalt hinzufügen, dass die Spalte, die Sie nicht möchten, kaum Daten enthält. Wenn es enorme Mengen an Text, XML oder binären Blobs enthält, nehmen Sie sich Zeit, um jede Spalte einzeln auszuwählen. Ihre Leistung wird sonst leiden. Prost!
Die Antwort von Mahomedalid hat ein kleines Problem:
Der Funktionscode für das Ersetzen wurde ersetzt. "<columns_to_delete>,
" durch "" ersetzt. Diese Ersetzung hat ein Problem, wenn das zu ersetzende Feld das letzte in der Concat-Zeichenfolge ist, da das letzte Feld kein Komma "" enthält und nicht entfernt wird die Saite.
Mein Vorschlag:
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>');
Ersetzen <table>
,<database>
und `
Die entfernte Spalte wird durch die Zeichenfolge "FIELD_REMOVED" ersetzt. In meinem Fall funktioniert dies, weil ich versucht habe, den Speicher zu sichern. (Das Feld, das ich entfernt habe, ist ein BLOB von ungefähr 1 MB)
Basierend auf der Antwort von @Mahomedalid habe ich einige Verbesserungen vorgenommen, um "Alle Spalten außer einigen in MySQL auswählen" zu unterstützen.
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;
Wenn Sie viele Spalten haben, verwenden Sie diese SQL, um group_concat_max_len zu ändern
SET @@group_concat_max_len = 2048;
Vielleicht habe ich eine Lösung für Jan Koritaks aufgezeigte Diskrepanz
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' );
Tabelle :
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
===============================
Abfrageergebnis:
'SELECT name_eid,sal FROM employee'
Wenn es sich immer um dieselbe Spalte handelt, können Sie eine Ansicht erstellen, in der sie nicht enthalten ist.
Ansonsten nein, ich glaube nicht.
Sie können SQL verwenden, um SQL zu generieren, wenn Sie das erzeugte SQL mögen und auswerten. Dies ist eine allgemeine Lösung, da die Spaltennamen aus dem Informationsschema extrahiert werden. Hier ist ein Beispiel aus der Unix-Befehlszeile.
Ersetzen
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
Sie müssen die Spaltennamen auf diese Weise nur einmal extrahieren, um die Spaltenliste ohne diese Spalte zu erstellen, und dann einfach die von Ihnen erstellte Abfrage verwenden.
Also so etwas wie:
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)
Jetzt können Sie die $column_list
Zeichenfolge in von Ihnen erstellten Abfragen wiederverwenden .
Ich möchte einen weiteren Gesichtspunkt hinzufügen, um dieses Problem zu lösen, insbesondere wenn Sie eine kleine Anzahl von Spalten entfernen müssen.
Sie können ein DB-Tool wie MySQL Workbench verwenden, um die select-Anweisung für Sie zu generieren. Sie müssen diese Spalten für die generierte Anweisung nur manuell entfernen und in Ihr SQL-Skript kopieren.
In MySQL Workbench können Sie Folgendes generieren:
Klicken Sie mit der rechten Maustaste auf die Tabelle -> An SQL-Editor senden -> Alle Anweisungen auswählen.
Die akzeptierte Antwort weist mehrere Mängel auf.
All diese Probleme können überwunden werden, indem Sie einfach Backticks in das SEPARATOR
für Sie einfügen GROUP_CONCAT
und stattdessen eine WHERE
Bedingung verwenden REPLACE()
. Für meine Zwecke (und ich stelle mir viele andere vor) wollte ich, dass die Spaltennamen in derselben Reihenfolge zurückgegeben werden, in der sie in der Tabelle selbst erscheinen. Um dies zu erreichen, verwenden wir hier eine explizite ORDER BY
Klausel innerhalb der GROUP_CONCAT()
Funktion:
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';
Ich bin ziemlich spät dran, eine Antwort darauf zu finden. Ich habe es immer so gemacht und ehrlich gesagt, es ist 100 Mal besser und ordentlicher als die beste Antwort. Ich hoffe nur, dass jemand es sieht. Und finde es nützlich
//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
Aussage - das Wort kommt nicht einmal vor.
Select * ist ein SQL-Antimuster. Es sollte aus vielen Gründen nicht im Produktionscode verwendet werden, einschließlich:
Die Verarbeitung dauert etwas länger. Wenn Dinge millionenfach ausgeführt werden, können diese winzigen Teile eine Rolle spielen. Eine langsame Datenbank, in der die Langsamkeit durch diese Art von schlampiger Codierung verursacht wird, ist am schwierigsten zu optimieren.
Dies bedeutet, dass Sie wahrscheinlich mehr Daten senden, als Sie benötigen, was sowohl zu Server- als auch zu Netzwerkengpässen führt. Wenn Sie einen inneren Join haben, ist die Wahrscheinlichkeit, dass mehr Daten gesendet werden, als Sie benötigen, 100%.
Dies führt zu Wartungsproblemen, insbesondere wenn Sie neue Spalten hinzugefügt haben, die nicht überall angezeigt werden sollen. Wenn Sie eine neue Spalte haben, müssen Sie möglicherweise etwas an der Schnittstelle tun, um zu bestimmen, was mit dieser Spalte geschehen soll.
Es kann Ansichten unterbrechen (ich weiß, dass dies auf dem SQL-Server zutrifft, es kann auf MySQL zutreffen oder nicht).
Wenn jemand dumm genug ist, die Tabellen mit den Spalten in einer anderen Reihenfolge neu zu erstellen (was Sie nicht tun sollten, aber es passiert immer wieder), können alle Arten von Code beschädigt werden. Insbesondere Code für eine Einfügung, bei der Sie die Stadt plötzlich in das Feld address_3 einfügen, da die Datenbank nur in der Reihenfolge der Spalten ausgeführt werden kann, ohne dies anzugeben. Dies ist schon schlimm genug, wenn sich die Datentypen ändern, aber schlimmer, wenn die ausgetauschten Spalten denselben Datentyp haben, da Sie manchmal schlechte Daten einfügen können, die ein Chaos beim Aufräumen sind. Sie müssen sich um die Datenintegrität kümmern.
Wenn es in einer Einfügung verwendet wird, wird die Einfügung unterbrochen, wenn in einer Tabelle eine neue Spalte hinzugefügt wird, in der anderen jedoch nicht.
Es könnte Auslöser brechen. Auslöserprobleme können schwierig zu diagnostizieren sein.
Addieren Sie all dies gegen die Zeit, die zum Hinzufügen der Spaltennamen erforderlich ist (zum Teufel haben Sie möglicherweise sogar eine Schnittstelle, über die Sie die Spaltennamen ziehen können (ich weiß, dass ich dies in SQL Server tue, ich wette, es gibt eine Möglichkeit dazu) Dies ist ein Tool, mit dem Sie MySQL-Abfragen schreiben.) Mal sehen: "Ich kann Wartungsprobleme verursachen, ich kann Leistungsprobleme verursachen und ich kann Probleme mit der Datenintegrität verursachen, aber hey, ich habe fünf Minuten Entwicklungszeit gespart." in den spezifischen Spalten, die Sie möchten.
Ich schlage außerdem vor, dass Sie dieses Buch lesen: 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