select ステートメントを使用して、特定の MySQL テーブルから 1 つを除くすべての列を取得しようとしています。これを行う簡単な方法はありますか?
編集:この表には53列あります(私のデザインではありません)
実際には方法があります、もちろんこれを行うための許可が必要です...
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;
交換<table>, <database> and <columns_to_omit>
(大きなテーブルでこれを試さないでください。結果は... 驚くべきものになる可能性があります!)
一時テーブル
DROP TABLE IF EXISTS temp_tb;
CREATE TEMPORARY TABLE ENGINE=MEMORY temp_tb SELECT * FROM orig_tb;
ALTER TABLE temp_tb DROP col_a, DROP col_f,DROP col_z; #// MySQL
SELECT * FROM temp_tb;
DROP 構文はデータベースによって異なる場合があります@Denis Rozhnev
この場合、ビューの方がうまく機能しますか?
CREATE VIEW vwTable
as
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
できるよ:
SELECT column1, column2, column4 FROM table WHERE whatever
おそらく、より一般的な解決策を探していましたが、column3 を取得しませんでしたか?
私の知る限り、ありません。次のようなことができます:
SELECT col1, col2, col3, col4 FROM tbl
必要な列を手動で選択します。ただし、多くの列が必要な場合は、次のことを行うだけでよい場合があります。
SELECT * FROM tbl
望まないものは無視してください。
あなたの特定のケースでは、私はお勧めします:
SELECT * FROM tbl
数列だけが必要な場合を除きます。4 つの列のみが必要な場合は、次のようにします。
SELECT col3, col6, col45, col 52 FROM tbl
問題はありませんが、50 列が必要な場合は、クエリを作成するコードが (あまりにも?) 読みにくくなります。
セキュリティ上の懸念や機密情報など、フィールドの値を除外する場合は、その列を null として取得できます。
例えば
SELECT *, NULL AS salary FROM users
選択したくない列に大量のデータが含まれていて、速度の問題のためにそれを含めたくなく、他の列を頻繁に選択する場合は、新しいテーブルを作成することをお勧めします元のテーブルへのキーで通常選択しない 1 つのフィールドを使用して、元のテーブルからフィールドを削除します。その余分なフィールドが実際に必要な場合は、テーブルを結合します。
DESCRIBE my_tableを使用し、その結果を使用して SELECT ステートメントを動的に生成できます。
私の主な問題は、テーブルを結合するときに得られる多くの列です。これはあなたの質問 ( 1 つのテーブルから特定の列を除くすべてを選択する方法) に対する答えではありませんが、指定するだけでなく、特定のテーブルからすべての列を取得するように指定できることに言及する価値があると思います。table.
これが非常に役立つ例を次に示します。
users.*、phone.meta_value を電話、zipcode.meta_value を郵便番号として選択します。 ユーザーから 電話としてuser_metaに参加したまま on ( (users.user_id = phone.user_id) AND (phone.meta_key = '電話') ) 郵便番号としてuser_metaに参加したまま on ( (users.user_id = zipcode.user_id) AND (zipcode.meta_key = 'zipcode') )
結果は、users テーブルのすべての列と、meta テーブルから結合された 2 つの追加の列です。
@Mahomedalid
からのコメントで通知されたこの事実に加えて、からの回答が気に入りました@Bill Karwin
。によって提起された可能性のある問題は@Jan Koritak
、私がそれに直面したことは事実ですが、そのためのトリックを見つけたので、問題に直面しているすべての人のためにここで共有したいと思います.
次のように、Prepared ステートメントのサブクエリで REPLACE 関数を where 句に置き換えることができます。
テーブル名と列名の使用
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;
したがって、これはフィールドのみを除外しますが、除外しid
ませんcompany_id
はい、表によってはI / Oが高くなる可能性がありますが、ここで見つけた回避策です。
SELECT *
INTO #temp
FROM table
ALTER TABLE #temp DROP COlUMN column_name
SELECT *
FROM #temp
すべての列をリストするという「単純な」解決策には同意しますが、これは負担になる可能性があり、タイプミスは多くの時間を無駄にする可能性があります。関数「getTableColumns」を使用して、クエリに貼り付けるのに適した列の名前を取得します。あとは、不要なものを削除するだけです。
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;
結果は、カンマ区切りの文字列を返します。たとえば...
col1,col2,col3,col4,...col53
すべての列を照会する場合でも、照会する列を指定することをお勧めします。
したがって、ステートメントの各列の名前を書くことをお勧めします(不要なものを除く)。
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
最初は正規表現を使用できると思っていましたが、MYSQL のドキュメントを読んでいると、できないようです。私があなたなら、別の言語 (PHP など) を使用して、取得する列のリストを生成し、それを文字列として保存し、それを使用して SQL を生成します。
@Mahomedalidの回答に基づいて、「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;
列がたくさんある場合は、この sql を使用して group_concat_max_len を変更します
SET @@group_concat_max_len = 2048;
Select *
他の場所で述べたように、必要のないものが BLOB である場合、そのオーバーヘッドが忍び寄るのを望まないことに同意します。
必要なデータを含むビューを作成Select *
します。データベース ソフトウェアがそれらをサポートしている場合は、安心して作成できます。それ以外の場合は、巨大なデータを別のテーブルに入れます。
私もこれが欲しかったので、代わりに関数を作成しました。
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)."`";
}
}
したがって、どのように機能するかは、テーブルを入力してから、不要な列または配列のように入力することです: array("id","name","whatevercolumn")
したがって、選択では次のように使用できます。
mysql_query("SELECT ".$db->getColsExcept('table',array('id','bigtextcolumn'))." FROM table");
また
mysql_query("SELECT ".$db->getColsExcept('table','bigtextcolumn')." FROM table");
Thomas の回答 (+1 ;)) には同意しますが、不要な列にはほとんどデータが含まれていないと仮定するという警告を追加したいと思います。膨大な量のテキスト、xml、またはバイナリ BLOB が含まれている場合は、時間をかけて各列を個別に選択してください。そうしないと、パフォーマンスが低下します。乾杯!
Mahomedalid が投稿した回答には小さな問題があります。
内部の置換関数コードは " <columns_to_delete>,
" を "" に置換していました。置換するフィールドが連結文字列の最後のフィールドである場合、最後のフィールドに char カンマ "," がなく、削除されないため、この置換に問題があります。文字列。
わたしの提案:
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>');
<table>
、<database>
および `の置き換え
削除された列は、メモリを保護しようとしていたため、私の場合は「FIELD_REMOVED」という文字列に置き換えられます。(削除していたフィールドは約 1MB の BLOB です)
やるだけ
SELECT * FROM table WHERE whatever
次に、お気に入りのプログラミング言語で列をドロップします: php
while (($data = mysql_fetch_array($result, MYSQL_ASSOC)) !== FALSE) {
unset($data["id"]);
foreach ($data as $k => $v) {
echo"$v,";
}
}
必要に応じて、SQL を使用して SQL を生成し、生成された SQL を評価できます。これは、情報スキーマから列名を抽出する一般的なソリューションです。Unix コマンド ラインからの例を次に示します。
代用
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
この方法で列名を一度だけ抽出して、その列を除外した列リストを作成し、作成したクエリを使用するだけで済みます。
次のようなものです:
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)
$column_list
これで、作成したクエリで文字列を再利用できます。
常に同じ 1 つの列である場合は、それを含まないビューを作成できます。
そうでなければ、いいえ、そうは思いません。
特に削除する列の数が少ない場合は、この問題を解決するために別の視点を追加したいと思います。
Select ステートメントを生成するためにMySQL Workbenchなどの DB ツールを使用できます。そのため、生成されたステートメントの列を手動で削除し、それを SQL スクリプトにコピーするだけです。
MySQL Workbench で生成する方法は次のとおりです。
テーブルを右クリック -> Sql Editor に送信 -> すべてのステートメントを選択します。
私はこれに対する答えを出すのにかなり遅れています. そして、それが役に立つと思います
//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]);