MySQL テーブルの一部のカラムだけを表示させる方法を教えてください
tblAに
id, a1,a2,a3,a4
のカラムがあった場合、tblA のカラムa3,a4だけを表示したい場合、
SELECT a3,a4 FROM tblA WHERE
と書けばよいのは分かっています。
ここで質問です。
別のテーブル tblBに
x, y
------
a1,1
a2,3
a3,2
a4,2
というデータがあった場合、カラムa3,a4を「tblBのyが2であるxの値(tblAのカラム名)」としてSELECT文をどう書いたらよいのかがわかりません。
つまり、
y=2とすれば、a3,a4の意味、
y>=2 とすれば、a2,a3,a4の意味、
y=1 とすれば a1 の意味
になるような書き方が知りたいです。
No.4ベストアンサー
- 回答日時:
drop procedure if exists select_a_fromB;
delimiter //
create procedure select_a_fromB(IN operator varchar(20))
begin
set @sql=concat("select group_concat(x) into @a from tbl_b where y",operator);
PREPARE stmt from @sql;
EXECUTE stmt;
set @sql=concat("select ",@a," from tbl_a");
PREPARE stmt from @sql;
EXECUTE stmt;
end
//
delimiter ;
call select_a_fromB(">=2");
No.10
- 回答日時:
テーブル名とか決め打ちで書いているのでご利用の環境とちがっていませんか?
procedureの実行者の権限とか大丈夫ですか?
>テーブル名とか決め打ちで書いているのでご利用の環境とちがっていませんか?
テーブル名はNo2で回答頂いた、tbl_a, tbl_bのままで、中身もそのままです。
>procedureの実行者の権限とか大丈夫ですか?
正直、よくわかりません。何も考えずに、XAMPPをインストール直後のままでの動作確認です。
教科書には、セキュリティのためパスワードをつけろとあったので、一旦はつけたのですが、
XAMPP の phpMyAdmin
が起動しなくなってしまったので、パスワードなしで(インストール直後の状態に戻して)テストしています。
No.9
- 回答日時:
#2に補足をつけたようですが、#4を利用してください
また「select @a from tbl_a」はまったく趣旨が異なるので
意味がありません
何度もありがとうございます。
>「select @a from tbl_a」はまったく趣旨が異なるので
了解です。展開して「select a3,a4 from tbl_a;」という文字列にして実行しないと駄目ということですね。
ここまで理解出来たのですが、#4で
call select_a_fromB("=2");
を実行しても状況は変わらず、何も出力されません。
なお、動作確認はXAMPP の phpMyAdmin の SQL です。
また、コマンドラインから
select a3,a4 from tbl_a;
を実行した場合と
set @a='a3,a4';
set @sql=concat("select ",@a," from tbl_a");
PREPARE stmt from @sql;
EXECUTE stmt;
を順番に実行した場合は同じ表示が出ますが、
call select_a_fromB("=2");
を実行すると、今度は、
ERROR 1370 (42000): execute command denied to user ''@'localhost' for routine 'test.select_a_fromB'
とエラーが表示されてしまいます。
つまり、call select_a_fromB("=2");は、
phpMyAdmin の SQL では何も出力されない
コマンドラインではエラーになってしまう
ため、どちらでもうまく行きません。
No.8
- 回答日時:
> 考え方がかなりイレギュラー
ちょっといい方が悪かったかもしれません。
お気になさっているようなら申し訳ないです。
「SQLの考え方としてイレギュラー」ということです。
ユーザーが渡せるものはデータだけというのが原則論を伝えたかったのですが
うまくニュアンスが伝わってないですね・・・
ユーザーごとにアクセスを変えるのであれば、
カラムは全て返すとして、アクセスできないはずのでカラムは
nullを返すなど工夫すればSQLライクな書き方になると思います
>「SQLの考え方としてイレギュラー」ということです。
なるほど。正直、SQLの考え方にまだ不慣れですね。どうしてもC言語的に考えてしまいます。
別に気にしているわけではありませんので、ご安心を。
それよりも、ご親切な回答に感謝していますよ。
いろいろとありがとうございます。
No.7
- 回答日時:
> 定番の処理はないのでしょうかね。
#1でも触れましたが、考え方がかなりイレギュラーです。
データからカラム名を取ることは一般的な方法ではありません。
プログラム言語によく用意されているプレースホルダー機能(prepare処理)も
テーブル名やカラム名、関数名には利用できません。
ホワイトリストを使って一般的な方法となると、普通はプログラム言語側で
対応することでしょうね
>考え方がかなりイレギュラーです。
技術者には戒め、研究者にはお褒めの言葉ありがとうございます。
>データからカラム名を取ることは一般的な方法ではありません。
カラム名を取りたいのではなく、
ユーザ毎にアクセスできるカラムを制約したい
だけです。各カラムにアクセスレベルが設定でき、ユーザのアクセスレベルが設定値未満のカラムは、当該ユーザには存在を隠したいのですが、なさそうなので、アクセスレベルを記載したテーブルtblBを用意しておいて、ユーザがアクセス可能なカラムだけを表示させる方法を思いついた訳です。
考え方がかなりイレギュラーなのかしら。
No.6
- 回答日時:
結局プロシージャを利用すれば普通のSQLでできない大抵のことを
できてしまいます。
ただそれは汎用性を損なうということなので、プロシージャの多様するなら
仕様書をきっちり作り込む必要がありますし、
ユーザーからのデータ投入に対してサニタイズ、バリデーション処理や
各種例外処理が必要だということを理解した上で対応することになります。
上記リスクとメリット・デメリットを理解した上で、スキルが伴えば
プロシージャがもっとも楽な解決方法になるでしょう
思慮深い回答ありがとうございます。
プロシージャを使うといろんなことができそうですね。
おっしゃる通り、メリット・デメリットを理解することが必要なこと、同感です。
No1>セキュリティ的な課題もありそういう運用はなるべくしないほうが良いと思います
そうなんですね。私は逆に、
利用者ごとに、作業開始直後に、
利用者が扱えるデータだけを集めた一時テーブルを作り、その一時テーブル上で作業をする
ことで、PHPプログラムの簡素化や安全性向上を期待していますので、使い方を誤ると逆効果ということですね。
対象レコードの抽出はWHERE部で可能ですが、カラムの抽出ができなくて質問しました。
でも操作可能対象だけを取り出す処理は、汎用的と思うのですが、定番の処理はないのでしょうかね。
No.5
- 回答日時:
ちなみにphpでやるなら別に全部ぬきだして、必要なところだけ
phpでつまめばいいだけ
また#4のoperatorが不正だった場合や結果が空だったときの
例外処理など結構手を入れないと実用に耐えないでしょう
今回も回答ありがとうございます
https://oshiete.goo.ne.jp/qa/11557860.html
間髪入れずに、デモプログラムを作成いただき、ありがとうございます。
なるほど、
set @sql=concat("select group_concat(x) into @a from tbl_b where y",operator);
で y=2 や y>=2 から、a3,a4 や a2,a3,a4 を@a に読み取り
set @sql=concat("select ",@a," from tbl_a");
で、 SELECT a3,a4 FROM tblA WHERE ・・・
というSQL文を @sql に作文して
PREPARE stmt from @sql;
EXECUTE stmt;
で実行するのですね。
>ちなみにphpでやるなら別に全部ぬきだして、必要なところだけ
>phpでつまめばいいだけ
確かにそうとも言えます。
C言語ならなんとかなるのですが、PHPもMySQLもよくわからないので苦労しているところです。どっちで処理したほうが楽なんでしょうかね。
PHPもMySQLも同じくらい不得意なので、
不要なデータを取得して必要な物を抽出
するより、
必要な物だけを取得
するほうがエレガントなプログラムの気がしますので、教示くださったデモプログラムを参考に進めて行こうと思います。
ありがとうございました。
No.2
- 回答日時:
一応procedureのサンプルです
//元データ
create table tbl_a(id int primary key,a1 int,a2 int,a3 int,a4 int);
insert into tbl_a values
(1,1001,2001,3001,4001),
(2,1002,2002,3002,4002),
(3,1003,2003,3003,4003);
create table tbl_b(id int primary key,x enum('a1','a2','a3','a4'),y int,unique key(x,y));
insert into tbl_b values
(1,'a1',1),
(2,'a2',3),
(3,'a3',2),
(4,'a4',2);
//procedure 作成
drop procedure if exists select_a_fromB;
delimiter //
create procedure select_a_fromB(IN y int)
begin
set @sql=concat("select group_concat(x) into @a from tbl_b where y=",y);
PREPARE stmt from @sql;
EXECUTE stmt;
set @sql=concat("select ",@a," from tbl_a");
PREPARE stmt from @sql;
EXECUTE stmt;
end
//
delimiter ;
//call
call select_a_fromB(2);
回答ありがとうございます
動作確認したのですが、色々試したのですが、うまく行きません
select a3,a4 from tbl_a;
と
set @a='a3,a4';
select @a from tbl_a;
では、表示が異なるようです。
何か、勘違いがあるのでしょうか?
No.1
- 回答日時:
通常のSQL文ではカラム名をレコードからひっぱることはできません
無理すればプロシージャでできるかもしれまえせんが
セキュリティ的な課題もありそういう運用はなるべくしないほうが良いと思います
回答ありがとうございます
>通常のSQL文ではカラム名をレコードからひっぱることはできません
そうですか、了解です。
となるとPHPの方で、
SELECT x FROM tblB WHERE y=2;
でデータベースに問いかけて、 a3,a4 を取得し、
この情報を使って
SELECT a3,a4 FROM tblA WHERE ・・・
というSQL文を作文して呼び出すことになりますね。
方針は決まりましたが、具体的には上に述べた処理をPHPでどのようなプログラムを書いたら良いのかアドバイスいただければ嬉しいです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- MySQL 共通点はあります。何が違うのでしょうか? 1 2023/01/27 05:22
- Excel(エクセル) マクロだと数式が表示される 2 2022/09/10 14:48
- Oracle SQL update方法 2 2022/06/22 14:07
- 数学 a1,a2, a3をベクトル空間Vのベクトルとする。a1+a2,a2+a3,a3+a1が一次独立のと 2 2022/10/02 15:55
- MySQL PHPとMySQLを使った掲示板の作り方 1 2022/06/02 13:00
- PostgreSQL 列が存在しないと言われる 2 2023/02/10 18:33
- その他(プログラミング・Web制作) Excel の判定式で正しく判定されない場合があります。 2 2022/05/31 14:43
- 数学 行列の問題が分かりません。 3次正則行列Aの列ベクトル分割をA=(a1 a2 a3)とおくとき,次を 4 2022/06/23 08:34
- 数学 3次元実ベクトル空間において, 平面 P:x-y+z+1=0 と直線 L:2(x-1)=-y=-z 3 2022/10/29 14:39
- Oracle sql(oracle)で質問です。 テーブルAのカラム名、日付(yyyymmdd)の値を テーブルB 2 2023/01/06 10:31
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
MYSQLで小数点を表示する場合と...
-
MySQL AUTO_INCREMENTが最大に...
-
select * での表示が崩れる?
-
時間範囲が重複したレコードを...
-
テーブルの列数を調べたい
-
MYSQLのストアドでの動的SQLに...
-
[MySQL]LOAD DATA INFILE一部レ...
-
MYSQLのレコードを上書きしたい...
-
group byで最後のレコードを抽...
-
now()かCURRENT_TIMESTAMPか
-
LIKEの右側にカラムを指定でき...
-
INDIRECT関数の代替方法は?
-
UNIONする際、片方テーブルしか...
-
SQLServerでNULLを挿入したいです
-
BULK INSERT時のNull許容について
-
DBの定義のサイズを大きくし過...
-
Accessの「IIF」に相当するSQL...
-
sql , insert で空行(全ての列...
-
一部のカラムでdistinctし全て...
-
AUTO_INCREMENTに0はダメ?
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
テーブルの列数を調べたい
-
[MySQL]LOAD DATA INFILE一部レ...
-
WHEREなどの条件が多い場合、ど...
-
group byで最後のレコードを抽...
-
フレンドリストのようなものを...
-
MYSQLで小数点を表示する場合と...
-
MySQL AUTO_INCREMENTが最大に...
-
時間範囲が重複したレコードを...
-
MYSQLのストアドでの動的SQLに...
-
「VARCHAR(255)」を「text」に...
-
MySQL テーブルの一部のカラム...
-
select * での表示が崩れる?
-
データの暗号化について
-
MySQLのselect文で、最大ID値の...
-
カラムの値を、条件により動的...
-
betweenを使うyyyy/mm/ddでの範...
-
MySQL 改行コードを含む文字列...
-
MySQLで、指定の複数カラムのみ...
-
mysqlでカンマデータのgroup by
-
ここで「INSERT INTO」を使う意...
おすすめ情報