selectステートメントを使用して、1つを除く特定のMySQLテーブルからすべての列を取得しようとしています。これを行う簡単な方法はありますか?
編集:このテーブルには53列があります(私のデザインではありません)
selectステートメントを使用して、1つを除く特定のMySQLテーブルからすべての列を取得しようとしています。これを行う簡単な方法はありますか?
編集:このテーブルには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>
<column_name>
mysqlの定義(手動)では、そのようなことはありません。ただし、列の数が非常に多いcol1
場合col100
は、以下が役立ちます。
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;
この場合、ビューはうまく機能しますか?
CREATE VIEW vwTable
as
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
できるよ:
SELECT column1, column2, column4 FROM table WHERE whatever
column3を取得せずに、おそらくより一般的な解決策を探していましたか?
たとえばセキュリティ上の問題や機密情報のためにフィールドの値を除外したい場合は、その列をnullとして取得できます。
例えば
SELECT *, NULL AS salary FROM users
salary
列を追加します。ただし、*の後に取得されるため、元のファイルが上書きされます。きれいではありませんが、動作します。
私の知る限りではありません。次のようなことができます:
SELECT col1, col2, col3, col4 FROM tbl
必要な列を手動で選択します。ただし、多くの列が必要な場合は、次のようにすることができます。
SELECT * FROM tbl
そして、あなたが望まないものを無視してください。
あなたの特定のケースでは、私はお勧めします:
SELECT * FROM tbl
数列だけ必要な場合を除きます。4つの列だけが必要な場合は、次のようにします。
SELECT col3, col6, col45, col 52 FROM tbl
大丈夫ですが、50列が必要な場合は、クエリを作成するコードが(あまりにも)読みにくくなります。
@Mahomedalidと@Junaidによる解決策を試しているときに問題が見つかりました。だからそれを共有することを考えました。列名にチェックインのようにスペースまたはハイフンがある場合、クエリは失敗します。簡単な回避策は、列名をバックティックで囲むことです。変更されたクエリは以下のとおりです
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;
選択したくない列に大量のデータが含まれていて、速度の問題のためにその列を含めたくなく、他の列を頻繁に選択する場合は、新しいテーブルを作成することをお勧めします元のテーブルへのキーでは通常選択しない1つのフィールドを使用して、元のテーブルからフィールドを削除します。その追加フィールドが実際に必要なときにテーブルを結合します。
あなたは使用することができmy_tableにDESCRIBEと動的SELECT文を生成するために、その結果を使用しています。
主な問題は、テーブルを結合するときに取得する多くの列です。これはあなたの質問(1つのテーブルから特定の列を除くすべてを選択する方法)に対する回答ではありませんが、を指定するだけでなく、特定のテーブルからすべての列を取得するように指定できることは言及する価値があると思います。table.
これが非常に役立つ例を以下に示します。
users。*、phone.meta_valueを電話として、zipcode.meta_valueを郵便番号として選択 ユーザーから user_metaを電話として残す on((users.user_id = phone.user_id)AND(phone.meta_key = 'phone')) user_metaを郵便番号として結合する on((users.user_id = zipcode.user_id)AND(zipcode.meta_key = 'zipcode'))
結果は、usersテーブルのすべての列と、メタテーブルから結合された2つの追加の列です。
からの@Mahomedalid
コメントで知らされたこの事実の他に、私は答えが好きでした@Bill Karwin
。が提起する可能性のある問題@Jan Koritak
は真実です。私はそれに直面しましたが、そのトリックを見つけたので、問題に直面している人のためにここで共有したいと思います。
次のように、REPLACE関数をPreparedステートメントのサブクエリの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
すべての列を照会する場合でも、照会する列を指定することをお勧めします。
したがって、ステートメントに各列の名前を記述することをお勧めします(不要な列は除きます)。
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
するだけ
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,";
}
}
すべての列を一覧表示する「単純な」ソリューションに同意しますが、これは負担が大きく、タイプミスにより多くの時間を無駄にする可能性があります。関数「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
最初は正規表現を使用できると思っていましたが、MYSQLドキュメントを読んでいるので、それはできないようです。私だったら、別の言語(PHPなど)を使用して取得したい列のリストを生成し、それを文字列として格納してから、それを使用してSQLを生成します。
これも欲しかったので、代わりに関数を作成しました。
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")
したがって、selectでは次のように使用できます。
mysql_query("SELECT ".$db->getColsExcept('table',array('id','bigtextcolumn'))." FROM table");
または
mysql_query("SELECT ".$db->getColsExcept('table','bigtextcolumn')." FROM table");
Mahomedalidが投稿した答えには小さな問題があります:
内部の置換機能コードは「<columns_to_delete>,
」を「」に置き換えていました。置換するフィールドが連結文字列の最後のフィールドである場合、この置換には問題があります。文字列。
私の提案:
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です)
@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;
colがたくさんある場合は、このSQLを使用してgroup_concat_max_lenを変更します。
SET @@group_concat_max_len = 2048;
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' );
テーブル :
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
================================
クエリ結果:
'SELECT name_eid,sal FROM employee'
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
この方法で実際に列名を抽出する必要があるのは1回だけで、その列を除外した列リストを作成してから、作成したクエリを使用するだけです。
したがって、次のようなもの:
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
したクエリで文字列を再利用できます。
この問題を解決するために、特に削除する列の数が少ない場合は、別の視点を追加したいと思います。
MySQL WorkbenchなどのDBツールを使用してselectステートメントを生成することができるため、生成されたステートメントの列を手動で削除し、SQLスクリプトにコピーするだけです。
MySQL Workbenchでは、それを生成する方法は次のとおりです。
テーブルを右クリック-> SQLエディターに送信->すべてのステートメントを選択。
受け入れられた回答にはいくつかの欠点があります。
これらの問題はすべて、バッククォートをSEPARATOR
forに含めGROUP_CONCAT
、のWHERE
代わりに条件を使用することで克服できますREPLACE()
。私の目的のため(そして私は他の多くの人を想像します)、列名がテーブル自体に表示されるのと同じ順序で返されるようにしたいと思いました。これを実現するために、ここORDER BY
ではGROUP_CONCAT()
関数内で明示的な句を使用しています。
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';
私はこれに対する答えをスローするのがかなり遅いです、これは私がいつもそれをやってきた方法であり、率直に言って、それは最高の答えよりも100倍優れていて、きちんとしています。そしてそれが便利だと思う
//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
、ここにステートメントはありません。この単語は一度も発生しません。
Select *はSQLアンチパターンです。次のような多くの理由により、本番コードでは使用しないでください。
処理に少し時間がかかります。何百万回も実行されている場合、それらの小さなビットが問題になる可能性があります。このタイプのずさんなコーディングが原因で速度が低下する低速データベースは、パフォーマンスの調整が最も困難です。
これは、おそらく必要以上のデータを送信していることを意味し、サーバーとネットワークの両方のボトルネックを引き起こします。内部結合がある場合、必要以上のデータを送信する可能性は100%です。
特に、どこにも表示したくない新しい列を追加した場合、メンテナンスの問題が発生します。さらに、新しい列がある場合は、その列をどうするかを決定するためにインターフェースに何かをする必要があるかもしれません。
これはビューを壊す可能性があります(これはSQlサーバーでは当てはまりますが、mysqlでは当てはまらない場合もあります)。
列が異なる順序でテーブルを再構築するのに十分な愚か者がいる場合(これは行うべきではありませんが、常に発生します)、あらゆる種類のコードが壊れる可能性があります。たとえば、突然都市をaddress_3フィールドに指定せずに挿入している場合など、挿入の特別なコードを記述します。データベースは列の順序でのみ実行できます。これは、データ型が変更される場合は十分に悪いですが、交換された列が同じデータ型である場合はさらに悪いことがあります。データの整合性に注意する必要があります。
挿入で使用されている場合、一方のテーブルに新しい列が追加され、もう一方のテーブルには追加されないと、挿入が中断されます。
トリガーが壊れる可能性があります。トリガーの問題は診断が難しい場合があります。
列名を追加するのにかかる時間と照らし合わせて、これらすべてを足し合わせてください(列名の上にドラッグできるインターフェイスさえあるかもしれません(SQL Serverでやっていることを知っているので、いくつかの方法があると思います)これは、mysqlクエリの記述に使用するツールです。「メンテナンスの問題が発生したり、パフォーマンスの問題が発生したり、データの整合性の問題が発生したりする可能性がありますが、開発時間を5分節約できました。」必要な特定の列で。
この本を読むことをお勧めします: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