Próbuję użyć instrukcji select, aby uzyskać wszystkie kolumny z określonej tabeli MySQL oprócz jednej. Czy istnieje prosty sposób to zrobić?
EDYCJA: W tej tabeli znajduje się 53 kolumny (NIE MÓJ PROJEKT)
Próbuję użyć instrukcji select, aby uzyskać wszystkie kolumny z określonej tabeli MySQL oprócz jednej. Czy istnieje prosty sposób to zrobić?
EDYCJA: W tej tabeli znajduje się 53 kolumny (NIE MÓJ PROJEKT)
Odpowiedzi:
W rzeczywistości istnieje sposób, aby to zrobić, musisz oczywiście mieć uprawnienia ...
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;
Zastąpienie <table>, <database> and <columns_to_omit>
<column_name>
W definicjach mysql (manual) nie ma czegoś takiego. Ale jeśli masz naprawdę dużą liczbę kolumn col1
, ..., col100
przydatne mogą być:
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;
Czy widok działałby lepiej w tym przypadku?
CREATE VIEW vwTable
as
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
Możesz to zrobić:
SELECT column1, column2, column4 FROM table WHERE whatever
bez zdobywania column3, chociaż być może szukałeś bardziej ogólnego rozwiązania?
Jeśli chcesz wykluczyć wartość pola, np. Ze względów bezpieczeństwa / poufnych informacji, możesz pobrać tę kolumnę jako null.
na przykład
SELECT *, NULL AS salary FROM users
salary
kolumnę. Ale ponieważ jest pobierany po *, zastępuje oryginał. To nie jest ładne, ale działa.
Według mojej najlepszej wiedzy nie ma. Możesz zrobić coś takiego:
SELECT col1, col2, col3, col4 FROM tbl
i ręcznie wybierz odpowiednie kolumny. Jeśli jednak chcesz mieć wiele kolumn, możesz po prostu zrobić:
SELECT * FROM tbl
i po prostu zignoruj to, czego nie chcesz.
W twoim konkretnym przypadku sugerowałbym:
SELECT * FROM tbl
chyba że chcesz tylko kilka kolumn. Jeśli chcesz tylko cztery kolumny, to:
SELECT col3, col6, col45, col 52 FROM tbl
byłoby dobrze, ale jeśli chcesz 50 kolumn, to każdy kod, który powoduje, że zapytanie będzie (zbyt?) trudne do odczytania.
Podczas próby rozwiązania przez @Mahomedalid i @Junaid znalazłem problem. Więc pomyślałem o udostępnieniu tego. Jeśli nazwa kolumny zawiera spacje lub łączniki, takie jak zameldowanie, zapytanie zakończy się niepowodzeniem. Prostym obejściem jest użycie znaku wstecz wokół nazw kolumn. Zmodyfikowane zapytanie znajduje się poniżej
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;
Jeśli kolumna, której nie chciałeś wybrać, zawierała w sobie ogromną ilość danych, a nie chciałeś dołączyć jej z powodu problemów z prędkością, a często wybierasz inne kolumny, sugerowałbym utworzenie nowej tabeli z jednym polem, którego zwykle nie wybiera się za pomocą klucza do oryginalnej tabeli i usuwa pole z oryginalnej tabeli. Dołącz do tabel, gdy to dodatkowe pole jest rzeczywiście wymagane.
Możesz użyć DESCRIBE moja_tabela i użyć jej wyników do dynamicznego generowania instrukcji SELECT.
Moim głównym problemem jest wiele kolumn, które pojawiają się podczas łączenia tabel. Chociaż nie jest to odpowiedź na twoje pytanie (jak wybrać wszystkie kolumny z jednej tabeli z wyjątkiem niektórych ), myślę, że warto wspomnieć, że możesz określić, aby uzyskać wszystkie kolumny z określonej tabeli, zamiast po prostu określać .table.
Oto przykład, w jaki sposób może to być bardzo przydatne:
wybierz użytkowników. *, phone.meta_value jako telefon, zipcode.meta_value jako kod pocztowy od użytkowników lewo dołącz do user_meta jako telefon on ((users.user_id = phone.user_id) AND (phone.meta_key = 'phone')) lewo dołącz do user_meta jako kod pocztowy on ((users.user_id = zipcode.user_id) ORAZ (zipcode.meta_key = 'zipcode'))
Wynikiem są wszystkie kolumny z tabeli użytkowników i dwie dodatkowe kolumny, które zostały połączone z tabeli meta.
Podobała mi się odpowiedź @Mahomedalid
poza tym faktem podana w komentarzu od @Bill Karwin
. Możliwy problem podniesiony przez @Jan Koritak
to prawda. Stawiłem temu czoła, ale znalazłem sztuczkę i po prostu chcę ją tutaj udostępnić każdemu, kto napotka problem.
możemy zamienić funkcję REPLACE na klauzulę where w zapytaniu podrzędnym instrukcji Prepared w następujący sposób:
Używam nazwy mojej tabeli i kolumny
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;
To wyklucza tylko pole, id
ale niecompany_id
Dobrą praktyką jest określenie zapytanych kolumn, nawet jeśli zapytania dotyczą wszystkich kolumn.
Proponuję więc wpisać nazwę każdej kolumny w zestawieniu (z wyjątkiem tej, której nie chcesz).
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
Po prostu zrób
SELECT * FROM table WHERE whatever
Następnie upuść kolumnę w swoim ulubionym języku programowania: php
while (($data = mysql_fetch_array($result, MYSQL_ASSOC)) !== FALSE) {
unset($data["id"]);
foreach ($data as $k => $v) {
echo"$v,";
}
}
Zgadzam się z „prostym” rozwiązaniem wyszczególnienia wszystkich kolumn, ale może to być uciążliwe, a literówki mogą powodować wiele straconego czasu. Korzystam z funkcji „getTableColumns”, aby pobrać nazwy moich kolumn odpowiednie do wklejenia do zapytania. Następnie wszystko, co muszę zrobić, to usunąć te, których nie chcę.
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;
Twój wynik zwraca ciąg rozdzielany przecinkami, na przykład ...
col1, col2, col3, col4, ... col53
Zgadzam się, że nie wystarczy Select *
, że jeśli ten, którego nie potrzebujesz, jak wspomniano w innym miejscu, jest BLOBEM, nie chcesz, aby ten napowietrzny wkradł się.
Chciałbym utworzyć widok z wymaganych danych, a następnie można Select *
w komfortowych warunkach --if oprogramowanie bazy danych obsługuje je. W przeciwnym razie umieść ogromne dane w innej tabeli.
Na początku myślałem, że możesz użyć wyrażeń regularnych, ale kiedy czytałem dokumenty MYSQL , wydaje się, że nie możesz. Gdybym był tobą, użyłbym innego języka (np. PHP), aby wygenerować listę kolumn, które chcesz uzyskać, zapisać go jako ciąg, a następnie użyć go do wygenerowania kodu SQL.
Też tego chciałem, więc zamiast tego stworzyłem funkcję.
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)."`";
}
}
Więc działa to tak, że wchodzisz do tabeli, a następnie do kolumny, której nie chcesz lub jak w tablicy: array („id”, „name”, „whatcolumn”)
Więc w select możesz użyć tego w następujący sposób:
mysql_query("SELECT ".$db->getColsExcept('table',array('id','bigtextcolumn'))." FROM table");
lub
mysql_query("SELECT ".$db->getColsExcept('table','bigtextcolumn')." FROM table");
Zgadzam się z odpowiedzią @ Mahomedalid, ale nie chciałem robić czegoś takiego jak przygotowane oświadczenie i nie chciałem wpisywać wszystkich pól, więc to, co miałem, było głupim rozwiązaniem.
Przejdź do tabeli w phpmyadmin-> sql-> select, zrzuci zapytanie: skopiuj, zamień i gotowe! :)
Chociaż zgadzam się z odpowiedzią Thomasa (+1;)), chciałbym dodać zastrzeżenie, że zakładam, że kolumna, której nie chcesz, nie zawiera prawie żadnych danych. Jeśli zawiera ogromne ilości tekstu, xml lub binarnych obiektów blob, poświęć czas na wybranie każdej kolumny osobno. Twoja wydajność ucierpi inaczej. Twoje zdrowie!
Odpowiedź wysłana przez Mahomedalid ma mały problem:
Wewnątrz kodu funkcji zastępowania zastępowano „ <columns_to_delete>,
” przez „”, to zastąpienie ma problem, jeśli pole do zamiany jest ostatnim z ciągu konkat, ponieważ ostatni nie ma przecinka char „” i nie jest usuwany z ciąg.
Moja propozycja:
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>');
Wymiana <table>
, <database>
i `
Usunięta kolumna zostaje zastąpiona ciągiem „FIELD_REMOVED”. W moim przypadku działa to, ponieważ próbowałem zabezpieczyć pamięć. (Pole, które usunąłem, to BLOB o wielkości około 1 MB)
W oparciu o odpowiedź @Mahomedalid wprowadziłem kilka ulepszeń w celu obsługi „zaznacz wszystkie kolumny oprócz niektórych w 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;
Jeśli masz dużo cols, użyj tej sql, aby zmienić group_concat_max_len
SET @@group_concat_max_len = 2048;
Być może mam rozwiązanie wskazanej rozbieżności Jana Koritaka
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' );
Stół :
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
================================
Wynik zapytania:
'SELECT name_eid,sal FROM employee'
Jeśli zawsze jest to ta sama kolumna, możesz utworzyć widok, w którym jej nie ma.
W przeciwnym razie nie, nie sądzę.
Możesz użyć SQL do wygenerowania SQL, jeśli chcesz i oceń SQL, który produkuje. Jest to ogólne rozwiązanie, ponieważ wyodrębnia nazwy kolumn ze schematu informacyjnego. Oto przykład z wiersza poleceń systemu Unix.
Zastępstwo
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
Naprawdę będziesz musiał tylko wyodrębnić nazwy kolumn w ten sposób tylko raz, aby zbudować listę kolumn z wyłączeniem tej kolumny, a następnie po prostu użyj utworzonego zapytania.
Więc coś takiego:
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)
Teraz możesz ponownie wykorzystać $column_list
ciąg w tworzonych zapytaniach.
Chciałbym dodać inny punkt widzenia w celu rozwiązania tego problemu, zwłaszcza jeśli masz do usunięcia niewielką liczbę kolumn.
Możesz użyć narzędzia DB, takiego jak MySQL Workbench , aby wygenerować dla siebie instrukcję select, więc musisz ręcznie usunąć te kolumny z wygenerowanej instrukcji i skopiować ją do skryptu SQL.
W MySQL Workbench sposobem na jego wygenerowanie jest:
Kliknij prawym przyciskiem myszy tabelę -> wyślij do edytora Sql -> Wybierz wszystko.
Przyjęta odpowiedź ma kilka wad.
Wszystkie te problemy można przezwyciężyć, po prostu włączając backticks w SEPARATOR
for GROUP_CONCAT
i używając WHERE
warunku zamiast REPLACE()
. Dla moich celów (i wyobrażam sobie wielu innych) chciałem, aby nazwy kolumn były zwracane w tej samej kolejności, w jakiej pojawiają się w samej tabeli. Aby to osiągnąć, używamy wyraźnej ORDER BY
klauzuli wewnątrz GROUP_CONCAT()
funkcji:
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';
Jestem dość późno, próbując znaleźć odpowiedź na to pytanie. Mówię to w ten sposób, że zawsze tak robiłem. Szczerze mówiąc, jest on 100 razy lepszy i ładniejszy niż najlepsza odpowiedź, mam tylko nadzieję, że ktoś to zobaczy. I uznaj to za przydatne
//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
tu żadnej instrukcji - słowo nie pojawia się ani razu.
Wybierz * to antipattern SQL. Nie należy go używać w kodzie produkcyjnym z wielu powodów, w tym:
Przetwarzanie zajmuje trochę dłużej. Kiedy rzeczy są uruchamiane miliony razy, te małe kawałki mogą mieć znaczenie. Powolna baza danych, w której powolność jest powodowana przez tego rodzaju niechlujne kodowanie, jest najtrudniejsza do dostrojenia.
Oznacza to, że prawdopodobnie wysyłasz więcej danych niż potrzebujesz, co powoduje wąskie gardła zarówno serwera, jak i sieci. Jeśli masz połączenie wewnętrzne, szanse na wysłanie większej liczby danych niż potrzebujesz to 100%.
Powoduje to problemy konserwacyjne, zwłaszcza gdy dodałeś nowe kolumny, których nie chcesz widzieć wszędzie. Ponadto, jeśli masz nową kolumnę, może być konieczne zrobienie czegoś z interfejsem, aby ustalić, co zrobić z tą kolumną.
Może to popsuć widoki (wiem, że jest to prawdą na serwerze SQl, może być lub nie być prawdą w mysql).
Jeśli ktoś jest wystarczająco głupi, aby odbudować tabele z kolumnami w innej kolejności (czego nie powinieneś robić, ale zdarza się to cały czas), wszelkiego rodzaju kod może się zepsuć. W szczególności kod dla wstawki, na przykład, gdy nagle wpisujesz miasto w polu adres_3, ponieważ nie określono, baza danych może przechodzić tylko w kolejności kolumn. Jest to wystarczająco złe, gdy zmieniają się typy danych, ale gorzej, gdy zamienione kolumny mają ten sam typ danych, ponieważ można czasem wstawić złe dane, które są bałaganem do wyczyszczenia. Musisz dbać o integralność danych.
Jeśli zostanie zastosowany we wstawce, spowoduje uszkodzenie wkładki, jeśli nowa kolumna zostanie dodana do jednej tabeli, ale nie do drugiej.
Może to spowodować uszkodzenie wyzwalaczy. Problemy z wyzwalaczem mogą być trudne do zdiagnozowania.
Zsumuj to w stosunku do czasu potrzebnego na dodanie nazw kolumn (do cholery możesz nawet mieć interfejs, który pozwala ci przeciągać nazwy kolumn (wiem, że robię to w SQL Server, założę się, że jest jakiś sposób na zrób to narzędzie, którego używasz do pisania zapytań mysql.) Zobaczmy: „Mogę powodować problemy z konserwacją, mogę powodować problemy z wydajnością i problemy z integralnością danych, ale hej, zaoszczędziłem pięć minut na programowaniu”. w konkretnych kolumnach, które chcesz.
Sugeruję także przeczytanie tej książki: 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 i słowa kluczowe = sql + antipatterns