質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Eclipse

Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

Q&A

解決済

1回答

793閲覧

Java でのSQLプログラム

nasubikun

総合スコア1

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Eclipse

Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

1グッド

0クリップ

投稿2023/04/07 03:01

Javaの課題で教えていただきたいです。

<修正事項>
・「select no lesson term from kenshu where no="1" and lesson="English"」とコン ソールに入力するとエラーが起こる
・複数のカラムが指定された際でも、NOの列しか表示されない

下記のコードで、二つの修正事項が全く分かりません。。。
どなたか教えていただきたいです。。。

package HelloWorld5;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class Q75syusei {
public static Map<String, Map<Integer, String>> makeTable() {
int no = 3;

Map<String, Map<Integer, String>> map = new HashMap<String, Map<Integer, String>>(); Map<Integer, String> NO = new HashMap<Integer, String>(); for (int i = 0; i < no; i++) { NO.put(i, Integer.toString(i)); } Map<Integer, String> LESSON = new HashMap<Integer, String>(); LESSON.put(0, "English"); LESSON.put(1, "math"); LESSON.put(2, "Music"); Map<Integer, String> TERM = new HashMap<Integer, String>(); TERM.put(0, "A"); TERM.put(1, "B"); TERM.put(2, "A"); Map<Integer, String> RESULT = new HashMap<Integer, String>(); RESULT.put(0, "90"); RESULT.put(1, "50"); RESULT.put(2, "120"); map.put("NO", NO); map.put("LESSON", LESSON); map.put("TERM", TERM); map.put("RESULT", RESULT); return map; } public static void getSQL(List<String> checkSQL, boolean boo) { Map<String, Map<Integer, String>> tableMap = makeTable(); int selectStartNum = checkSQL.indexOf("SELECT") + 1; int fromStartNum = checkSQL.indexOf("FROM") + 1; int whereStartNum = checkSQL.indexOf("WHERE") + 1; String[] selectstr = checkSQL.get(1).split(","); if (boo) { ArrayList<String> getSQLList = new ArrayList<String>(); System.out.println(checkSQL); int count = whereStartNum; List<Integer> displayNnums = new ArrayList<Integer>(); displayNnums.add(0); displayNnums.add(1); displayNnums.add(2); while (true) { String[] whereTmpStrings = checkSQL.get(count).split("="); List<Integer> delete = new ArrayList<Integer>(); whereTmpStrings[1] = whereTmpStrings[1].substring(1, whereTmpStrings[1].length() - 1); for (int i = 0; i < displayNnums.size(); i++) { if (!tableMap.get(whereTmpStrings[0]).get(i).equals(whereTmpStrings[1])) { System.out.println(tableMap.get(whereTmpStrings[0]).get(i) + whereTmpStrings[1]); delete.add(i); } } for (Integer integer : delete) { displayNnums.remove(displayNnums.indexOf(integer)); } try { checkSQL.get(count + 1); } catch (Exception e) { break; } count += 2; } for (int i = 0; i < selectstr.length; i++) { System.out.printf("%10s", selectstr[i]); } System.out.println(); for (int i : displayNnums) { for (String string : selectstr) { System.out.printf("%10s", tableMap.get(string).get(i) + " "); } System.out.println(); } } else { for (int i = 0; i < selectstr.length; i++) { System.out.printf("%10s", selectstr[i]); } System.out.println(); System.out.println("--------------------------"); for (int i = 0; i < tableMap.get("NO").size(); i++) { for (String string : selectstr) { System.out.printf("%10s", tableMap.get(string).get(i) + " "); } System.out.println(); } } } public static String BB(String string) { return string.toUpperCase(); } public static boolean karam(String string) { List<String> karamList = new ArrayList<String>(Arrays.asList("NO", "LESSON", "TERM", "RESULT")); return karamList.contains(string); } public static void selsectCheck(List<String> checkSQL) { int selectNum = checkSQL.indexOf("FROM"); boolean booe = false; String[] tmpStrings = checkSQL.get(1).split(","); if (!checkSQL.get(0).equals("SELECT")) { System.out.println("SELECT句が正しくありません。"); System.exit(0); } else if (checkSQL.get(1).equals("FROM")) { booe = true; } else { for (String string : tmpStrings) { booe = !karam(string); } } if (booe) { System.out.println("SELECT句の引数が正しくありません。"); System.exit(0); } } public static void fromCheck(List<String> checkSQL) { int fromStartNum = checkSQL.indexOf("FROM") + 1; if (!checkSQL.contains("FROM")) { System.out.println("FROM句が正しくありません。"); System.exit(0); } try { if (!checkSQL.get(fromStartNum).equals("KENSHU")) { System.out.println("FROM句の引数が正しくありません。"); System.exit(0); } } catch (Exception e) { System.out.println("FROM句が正しくありません。"); System.exit(0); } } public static void whereCheck(List<String> checkSQL) { int fromStartNum = checkSQL.indexOf("WHERE") + 1; boolean booe = false; int count = fromStartNum; String tmpFromSqlString = ""; for (int i = fromStartNum; i < checkSQL.size(); i++) { tmpFromSqlString += checkSQL.get(i); } String[] FromSqlString = tmpFromSqlString.split("AND"); int num = 0; while (true) { String[] whereTmpStrings = FromSqlString[num].split("="); if (!karam(whereTmpStrings[0])) { booe = true; } else if (whereTmpStrings.length != 2) { booe = true; } else { String[] tmpStrings = whereTmpStrings[1].split(""); if (!tmpStrings[0].equals("\"") || !tmpStrings[tmpStrings.length - 1].equals("\"")) { booe = true; } } if (booe) { System.out.println("WHERE句の引数が正しくありません。"); System.exit(0); } String tmp = ""; try { tmp = FromSqlString[num + 1]; } catch (Exception e) { break; } num++; } } public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("SQLを入力してください。"); boolean whereboo = false; String scstr = sc.nextLine(); String[] sqlstr = scstr.split(" "); for (int i = 0; i < sqlstr.length; i++) { sqlstr[i] = BB(sqlstr[i]); } List<String> checkSQL = new ArrayList<String>(Arrays.asList(sqlstr)); checkSQL.remove(""); checkSQL.remove(" "); checkSQL.remove(","); selsectCheck(checkSQL); fromCheck(checkSQL); if (checkSQL.size() == checkSQL.indexOf("FROM") + 2) { } else { boolean boo = false; int fromEndNum = checkSQL.indexOf("FROM") + 1; if (!checkSQL.get(fromEndNum + 1).equals("WHERE")) { System.out.println("WHERE句が正しくありません。"); System.exit(0); } else { for (String str : checkSQL) { if (str.contains("=")) { whereCheck(checkSQL); boo = true; } whereboo = true; } if (boo == false) { System.out.println("WHERE句の引数が正しくありません。"); System.exit(0); } } } System.out.println("SQL は正しいです。"); getSQL(checkSQL, whereboo); }

}
ボールドテキスト

ockeghemを押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2023/04/07 03:12

課題 であれば出題者に質問すべきでは。いずれにしてもコンソールにSQLそのものを入力する意図がわかりません。Javaプログラムの実行ではないのですか?
nasubikun

2023/04/07 03:43

Javaで簡易SQLをつくってみようという課題でした!出題者ではなく、こちらで教えていただける方がいらっしゃればいいと思い質問しています(⌒∇⌒)
m.ts10806

2023/04/07 03:57

此処には赤の他人しかおらず出題者の意図を汲める回答者はおそらくいないので自己責任になります。 が、エラー内容提示されてないのと、コードのマークダウンが不十分なのと、ファイル毎に分けられてないのとで再現確認が困難です。再現確認できないと答えるのは難しいので、質問修正してください。(なので出題者に聞くのが一番確実で早い。)
1T2R3M4

2023/04/07 04:41

https://teratail.com/help/avoid-asking コードをください・デバッグしてください等の丸投げの質問 何かを作りたいのでコードを書いてほしい、学校の課題を解いてほしい等の質問は、具体的にプログラミングで困っている質問ではないと考え、推奨していません。
jimbe

2023/04/07 04:44

これだけコード書いてて分からないというのはどういうことでしょう。 sql も似非ですし MySql 関係なさそうですからタグは要らないのでは。
xebme

2023/04/08 03:58

簡易SQLの仕様はあるのですか。
xebme

2023/04/08 07:03

引用符の中もupperCaseされますね。 例外はこれでなくなると思います。 if (displayNnums.contains(integer)) displayNnums.remove(displayNnums.indexOf(integer)); その他の問題は指摘しません。
guest

回答1

0

ベストアンサー

質問の回答

・「select no lesson term from kenshu where no="1" and lesson="English"」とコン ソールに入力するとエラーが起こる

前の列条件処理で既に削除された要素をdisplayNumから削除しようとしているから。修正コードは下記。

Java

1 for (Integer integer : delete) { 2 if (displayNnums.contains(integer)) 3 displayNnums.remove(displayNnums.indexOf(integer)); 4 }

・複数のカラムが指定された際でも、NOの列しか表示されない

簡易SQLの仕様に依存します。select no lesson term from kenshuの列の区切り文字を[,]にすると正常実行します。区切り文字を[ ]も許すならバグ(今は許してSQLを実行しています)。許さないのなら構文エラー。

  • バグの場合は字句解析、構文解析の両方を直して列の並びを全て取得できるようにします
    • String.split()だけで字句解析できる仕様にするか、字句解析を自作する
  • 構文エラーにするなら、FROMを期待しているところに列名がくるとエラーにするなどの対策を講じる

アドバイス

  • 簡易SQLの言語仕様を(BNFを使うなどして)明確にしたうえでプログラミングしてください
  • 字句解析、構文解析などのコンパイラー技術を学んで適用してください
  • このプログラムを簡潔にしてください
    • 使われない変数や、思いつきの構造、強引なコードが見られます

関数を使うSQL実行

コンパイラ技術は調べればいくらでも情報が出てきます。さてSQLの実行をどうするか。以下のように関数を使うことにしました。

<KENSHUテーブルのレコード>.stream().filter(<WHERE条件の適用>).map(<SELECT列の値取得>).toList();

質問のコードを変更してSQL実行をStreamと関数で行いました。コードの抜粋を追記しておきます。SQLTokenizerクラスは省略します。ご自分で補ってください。

Java

1 2import java.util.ArrayList; 3import java.util.List; 4import java.util.Map; 5import java.util.Scanner; 6import java.util.function.BiPredicate; 7import java.util.function.BinaryOperator; 8import java.util.function.Function; 9import java.util.function.Predicate; 10import java.util.stream.Collectors; 11 12public class SimpleSQLInterpreter { 13 static record lesson(String no, String name, String term, String result) {} 14 static Map<String,List<lesson>> tables = Map.of( 15 "KENSHU", List.of( 16 new lesson("0","English","A","90"), 17 new lesson("1","Math","B","50"), 18 new lesson("2","Music","A","120") 19 ) 20 ); 21 static Map<String,Function<lesson,String>> columners = Map.of( 22 "NO", x -> x.no(), 23 "LESSON", x -> x.name(), 24 "TERM", x -> x.term(), 25 "RESULT", x -> x.result() 26 ); 27 static Map<String,BiPredicate<String,String>> relOperators = Map.of( 28 "=", (x,y) -> x != null && x.compareTo(y) == 0, 29 "<", (x,y) -> x != null && x.compareTo(y) < 0, 30 "<=", (x,y) -> x != null && x.compareTo(y) <= 0, 31 ">", (x,y) -> x != null && x.compareTo(y) > 0, 32 ">=", (x,y) -> x != null && x.compareTo(y) >= 0 33 ); 34 static Map<String,BinaryOperator<Predicate<lesson>>> logicalOperators = Map.of( 35 "AND", (x,y) -> x == null ? y : x.and(y), 36 "OR", (x,y) -> x == null ? y : x.or(y) 37 ); 38 /* SQLを実行する **/ 39 public static List<String> goSQL(String tableName, Predicate<lesson> conditions, Function<lesson,String> columns) { 40 List<lesson> kenshu = tables.get(tableName); 41 // WHERE条件で選択(filter)、レコードから列を取り出す(map) 42 return kenshu.stream().filter(x -> conditions.test(x)).map(x -> columns.apply(x)).toList(); 43 } 44 public static Function<lesson,String> checkSelectClause(List<String> checkSQL) { 45 List<Function<lesson,String>> columnList = new ArrayList<>(); 46 int pos = 0; 47 // ... 48 // 列一覧を解析する 49 // looping 50 String col = checkSQL.get(pos).toUpperCase(); 51 if (!columners.containsKey(col)) { 52 System.out.println("列["+col+"]が存在しません"); 53 } 54 // ... 55 columnList.add(columners.get(col)); 56 // ... 57 // lessonレコードから必要な列の値を取得して','で区切り表示する 58 return x -> columnList.stream().map(f -> f.apply(x)).collect(Collectors.joining(",")).toString(); 59 } 60 public static String checkFromClause(List<String> checkSQL) { 61 int pos = 0; 62 // ... 63 String tableName = checkSQL.get(++pos).toUpperCase(); 64 if (!tables.containsKey(tableName)) { 65 System.out.println("テーブルが存在しません"); 66 } 67 // ... 68 return tableName; 69 } 70 public static Predicate<lesson> checkWhereClause(List<String> checkSQL) { 71 boolean notfound = true; // WHERE が存在しない 72 // ... 73 if (notfound) { 74 return x -> true; // 全件選択 75 } 76 // WHERE が存在する 77 Predicate<lesson> conditions = null; 78 int s = 0; 79 // 列選択条件を解析する 80 // looping 81 // 列名を解析する 82 String col = checkSQL.get(s).toUpperCase(); 83 if (!columners.containsKey(col)) { 84 System.out.println("列が存在しません"); 85 } 86 // ... 87 // 比較演算子を解析する 88 String cnd = checkSQL.get(s+1); 89 if (!relOperators.containsKey(cnd)) { 90 System.out.println("比較演算子が不正です"); 91 } 92 // ... 93 BiPredicate<String,String> operator = relOperators.get(cnd); 94 // ... 95 // 文字列リテラルを解析する 96 String evalue = checkSQL.get(s+2); 97 // ... 98 // 列の値を比較して条件を満たすか判定する述語 99 Predicate<lesson> p = x -> operator.test(columners.getOrDefault(col,c->"").apply(x),evalue); 100 // AND結合 OR(?) 優先度は無視 101 conditions = logicalOperators.get("AND").apply(conditions,p); 102 // ... 103 return conditions; 104 } 105 public static void main(String[] args) { 106 try (Scanner sc = new Scanner(System.in)) { 107 System.out.println("SQLを入力してください。"); 108 String scstr = sc.nextLine(); 109 // 字句解析 110 List<String> checkSQL = SQLTokenizer.decompose(scstr); 111 // 構文解析 112 Function<lesson,String> selectColumns = null; 113 String tableName = null; 114 Predicate<lesson> conditions = null; 115 // ... 116 System.out.println("SQL は正しいです。"); 117 System.out.println(goSQL(tableName,conditions,selectColumns)); 118 } 119 } 120}

投稿2023/04/09 20:39

編集2023/04/09 20:45
xebme

総合スコア1083

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問