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

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

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

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Java

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

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

1回答

2029閲覧

SQLiteでSELECT文のWHERE句の後に変数を使いたい。

onoko

総合スコア40

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Java

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

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2021/08/30 04:37

SQLiteデータベースの使い方についての質問です。データベースのmeditation2というテーブルの中にtakerというカラムが"1"のレコードが数件入っています。そのtakerが"1"のものをSELECT文で読み込んでandrroid画面にListViewで表示したく思います。しかしSELECT文のWHEREの後に変数を使った以下のコードではデータは表示されず最終の「新規」の行しか出ません。一方SQL文をWHERE句の後のwTakerの部分を直接'1'に書き直して一組の二重引用符で囲んだ一本のSQL文にするとうまくいってtaker="1"のレコードが全部表示されます。カラムの値の誤りではありません。意図通りにレコードを読み出すにはコードをどう改善したらよいでしょう。

java

1package com.onoko.portfolio.android.medicine; 2 3import androidx.appcompat.app.AppCompatActivity; 4 5import android.content.Intent; 6import android.database.Cursor; 7import android.database.sqlite.SQLiteDatabase; 8import android.os.Bundle; 9import android.view.View; 10import android.widget.AdapterView; 11import android.widget.ListView; 12import android.widget.SimpleAdapter; 13 14import java.util.ArrayList; 15import java.util.HashMap; 16import java.util.List; 17import java.util.Map; 18 19public class MainActivity extends AppCompatActivity { 20 private ListView lvDrugs; 21// private List<Map<String,String>> drugs = new ArrayList<>(); 22 private static final String[] FROM = {"name","unit"}; 23 private static final int[] TO ={R.id.tvNameRow,R.id.tvUnitRow}; 24 private DatabaseHelper _helper; 25 26 27 @Override 28 protected void onCreate(Bundle savedInstanceState) { 29 super.onCreate(savedInstanceState); 30 setContentView(R.layout.activity_main); 31 32 ListView lvDrugs = findViewById(R.id.lvDrugs); 33 List<Map<String,String>>drugs =getDrugs("1"); 34 SimpleAdapter adapter = new SimpleAdapter(MainActivity.this, drugs, R.layout.row, FROM, TO); 35 lvDrugs.setAdapter(adapter); 36 37 lvDrugs.setOnItemClickListener(new ListItemClickListener()); 38 39 } 40 41 protected void onStart() { 42 super.onStart(); 43 44 ListView lvDrugs = findViewById(R.id.lvDrugs); 45 Intent intentSub = getIntent(); 46 List<Map<String, String>> drugs = getDrugs(intentSub.getStringExtra("taker")); 47 48 SimpleAdapter adapter = new SimpleAdapter(MainActivity.this, drugs, R.layout.row, FROM, TO); 49 lvDrugs.setAdapter(adapter); 50 51 lvDrugs.setOnItemClickListener(new ListItemClickListener()); 52 53 } 54 55 private List<Map<String,String>> getDrugs (String wTaker){ 56 _helper = new DatabaseHelper(MainActivity.this); 57 SQLiteDatabase db = _helper.getWritableDatabase(); 58 Cursor cursor = db.rawQuery("SELECT * FROM medication2 WHERE taker ='"+wTaker+"'", null); 59 List<Map<String,String>> wDrugs = new ArrayList<>(); 60 int i; 61 while (cursor.moveToNext()) { 62 Map<String, String> drug = new HashMap<>(); 63 64 int idxId = cursor.getColumnIndex("_id"); 65 i = cursor.getInt(idxId); 66 drug.put("_id", Integer.toString(i)); 67 68 int idxTaker = cursor.getColumnIndex("taker"); 69 drug.put("taker", cursor.getString(idxTaker)); 70 71 int idxName = cursor.getColumnIndex("name"); 72 drug.put("name", cursor.getString(idxName)); 73 74 int idxUnit = cursor.getColumnIndex("unit"); 75 i = cursor.getInt(idxUnit); 76 drug.put("unit", Integer.toString(i)); 77 78 int idxTimes = cursor.getColumnIndex("times"); 79 i = cursor.getInt(idxTimes); 80 drug.put("times", Integer.toString(i)); 81 82 int idxDayOfWeek = cursor.getColumnIndex("dayOfWeek"); 83 drug.put("dayOfWeek", cursor.getString(idxDayOfWeek)); 84 85 int idxDays = cursor.getColumnIndex("days"); 86 i = cursor.getInt(idxDays); 87 drug.put("days", Integer.toString(i)); 88 89 int idxStock = cursor.getColumnIndex("stock"); 90 i = cursor.getInt(idxStock); 91 drug.put("stock", Integer.toString(i)); 92 93 int idxUpdateTime = cursor.getColumnIndex("updateTime"); 94 i = cursor.getInt(idxUpdateTime); 95 drug.put("updateTime", Integer.toString(i)); 96 97 wDrugs.add(drug); 98 } 99 Map<String, String> drug = new HashMap<>(); 100 drug.put("_id", "-1"); 101 drug.put("taker", "1"); 102 drug.put("name", "新規"); 103 drug.put("unit", "0"); 104 drug.put("times", "0"); 105 drug.put("dayOfWeek", ""); 106 drug.put("days", "0"); 107 drug.put("stock", "0"); 108 drug.put("updateTime", "0"); 109 wDrugs.add(drug); 110 111 return wDrugs; 112 113 } 114

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

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

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

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

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

m.ts10806

2021/08/30 04:45

変数に想定の値が来ていないか、想定の箇所を通っていないかのどちらかに思いますがデバッグはされましたか?
jimbe

2021/08/30 05:13 編集

SQL を文字列として編集して rawQuery するのではなく、 query を使って SQLiteDatabase 自身に SQL を組み立てさせてください。クオーティングも適切に設定されますし、この状態では変数の値によっては大問題になる可能性があります。 SELECT 列の指定には "*" ではなく、列名を列挙するようにしてください。 テーブルの定義の更新によって列が変名・削除された場合に( query 実行箇所でなく以降のコード上で異常が発生し)原因究明に時間が掛かってしまう可能性があります。
onoko

2021/08/30 05:40

m.ts10806様  もう一度デバッグして確認したところ、変数は"1"で想定値でした。想定の場所を通ったかは、変数の代わりに直接’1’を記入したことで証明されていると思ったのですが、変数wTakerがgetDrugs()の引数として定義されているより前で、メソッドの使用と共に使われていることが、何かコードの実行順序によって未定義のものとしておかしなことになるのかもしれないと思い浮かびましたが適当な直し方が分かりません。ご教示いただければ。
onoko

2021/08/30 05:52

jimbe様  String sql =”SELECT * FROM medication WHERE taker='" + wTaker + "'"; Cursor cursor = db.rawQuery(sql,null); としてテストしてみましたが、taker"1"のレコードは全く表示されませんでした。
dodox86

2021/08/30 06:02

@質問者 onokoさん jimbeさんが書かれているのは、StringにSQLを自力で組み立て、rawQuery()メソッドを使うのではなく、SQLiteDatabaseクラスのquery()メソッドを使いましょう、ということです。 https://developer.android.com/reference/android/database/sqlite/SQLiteDatabase#query(java.lang.String,%20java.lang.String[],%20java.lang.String,%20java.lang.String[],%20java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String) ただ、まぁ現状のまま、rawQuery()メソッドを使ったとしても、String sql =”SELECT * FROM medication WHERE taker='" + wTaker + "'"; で生成された変数sqlの文字列を実際に確認すれば意図通りのものになっているか確認できるのではないでしょうか。
onoko

2021/08/30 06:41

dodox86様  デバッグすると、変数sqlの値は”SELECT * FROM medication WHERE taker= '1'"で狙い通りものでした。このsql文を直接記入したときはレコードが得られてこの変数を使うやり方だと同じ文なのになぜだめかなのは私の経験からはわかりません。
FKM

2021/08/30 06:45

medicationとmedication2はどっちが正規なんですか?
onoko

2021/08/30 06:47

失礼いたしました。medicatiom2です。
dodox86

2021/08/30 06:54 編集

rawQueryをもう少し積極的に使って、こうやってみたらどうでしょう。 > db.rawQuery("SELECT * FROM medication2 WHERE taker=?" new String[] {"1"});
dodox86

2021/08/30 06:56

いや、仮引数wTakerを使って、こうですね。 db.rawQuery("SELECT * FROM medication2 WHERE taker=?" new String[] {wTaker});
jimbe

2021/08/30 07:24 編集

dodox86 さん: 言葉が足りなかった所解説頂きありがとうございます。 onoko さん: 実際の問題は SQL では無く、ライフサイクルに関するほうと思います。 ですので上のコメントは回答では無くこちらに書かせて頂きました。 getDrugs は onCreate の他、onStart からも呼ばれています。そして、onCreate はアクティビティの生成時のみですが、onStart は画面が表示される場合に常に(従って onCreate の後に)呼ばれます。 onStart での getDrugs の呼び出しでは、メソッドのパラメータは intent から取り出されています。そこには何が入っているでしょうか。
onoko

2021/08/30 07:51

jimbe様 このプログラムは服薬管理アプリです。MainActivityはひとりがその日のその食事時に飲むべき薬を表示します。ListViewの個々の薬品名の行または”新規”の行を”ををタップすることで、副画面のSupplyActivityにうつり、タップした薬品の追加または初めての処方の薬名を、一日何回、一回何錠、何日分か入力しそして在庫数を自動計算して登録します。アクションバーの戻りの矢印で副画面はfinish()しMainActivityからIntentで受け渡されたデータのうちtakerのみを副画面でIntentSubにより送り返し、同じ人(taker)の更新後のデータをMainActivityで表示しなおすのにつかっているのです。  ところで私はAndroidアプリ初開発のせいで、onStart()中のコードが、MainActivityへ復帰したときのみ実行されるものとばかり思っていて、初回にMainactivityを出したときにonCreateに続きonStartも実行されるとは思ってもいませんでした。ご指摘の通りまだ副画面でデータを充填されていないintentSubから取り出されたtakerはたぶんnullでSQLite中のtaker="1"のデータはSELECTされなのだと思います。ご指導のほどありがとうございました。  ただこのonStartの中のコードをMainActivityがonCreateしたときのみ実行されないようにするには、どのような処理をしたらよいでしょうか。そこのところを初心者の浅はかさに免じてお教えくださいますようお願いします。
jimbe

2021/08/30 07:56

> このonStartの中のコードをMainActivityがonCreateしたときのみ実行されないようにする コードレベルで見ますと、 onCreate と onStart で行われているのは(該当パラメータの部分以外は)同じです。 ですので、発想を逆にして「どうせonStart でやるのだから onCreate ではやらない」とするのが良いかと思います。 そして、インテントに "taker" が無かった(=null)場合は "1" を渡すように getDrugs のパラメータを調整するとラクかと思います。
onoko

2021/08/30 08:12

jimbe様  早速やってみます。柔軟な視点でのご指導ありがとうございます。
jimbe

2021/08/30 08:17 編集

ついでになりますが、ListView へのリスナの登録は一度すれば十分で、 setAdapter する度に行う必要はありません。 ですので、リスナの登録部分は(上のコメントと逆に) onStart から除いて onCreate に残して大丈夫です。
onoko

2021/08/30 08:16

jimbe様  重ね重ねありがとうございます。
onoko

2021/08/30 08:23

dodox86様  遅れて失礼いたしました。丁寧なご指示ありがとうございました。
onoko

2021/08/31 00:18

jimbe様  おかげさまで解決しました。ところでjimbe様のご回答をベストアンサーにする方法が分かりません。ご教授願えましたらと思います。
jimbe

2021/08/31 02:43

ご自身で回答としてどこをどのように修正したかをお書きくださって、それをベストアンサーとされて構いません d(^^
FKM

2021/08/31 04:13

ご本人様が自己解決を勧められているようですので、後の閲覧者のために質問クローズご協力お願い致します。
guest

回答1

0

自己解決

ご指摘により、WHERE句の後のコードは正常で他に原因があることが判明し、改善後解決しました。

投稿2021/08/31 20:00

onoko

総合スコア40

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問