アプリ版:「スタンプのみでお礼する」機能のリリースについて

Webアプリを開発しておりまして、SQLに詳しい方にDB回りをお願いしいますが、躓いてしまいました。
W3Cに則り作成のため、WebSQLを使って名簿のようなテーブルから、該当するデーターをループを組んで読みだそうとしていますが、最後のデーターしか返ってきません。
目的は、該当する名前を表示して、それぞれに付加(追加する:空のテーブルは用意しておいて)データーを入力して、DBへ返そうと思っています。
しかしSQLの超初心者のため、またWebSQLやSQLiteも始めたばかりで、簡単にループを掛けてインクリメントで読み出し、表示して  が 巧く行きません。
なにやら「同期」とか「非同期」なる言葉があるようですが、そもそもこれもよくわかりません。
上記の目的を達成させることが可能なのか、不可能なのかを教えていただければ助かります。参考文献などを示唆していただければなお良いと思います。


まず、以下のようなテーブルを用意しています。
  名前  性別  身長  体重  
  山田  男
  高橋  男
  田中  女
  吉田  男
  佐藤  女
  などなど

以上から 女だけを順に取ってきて  :入力ボックスとは input type="text"の様なものです

  田中  女   入力ボックス  入力ボックス
  佐藤  女     〃        〃
  以下該当者全て同じように表示

入力したデーターを 該当する空欄(あるいは上書き)でデーターを戻す

これを ループ処理でやりたいと思っています。

よろしくお願いします

A 回答 (3件)

websql での関数が callback であるところ、結構混乱しますね。


プレースホルダーに入れるデータを、わざわざ変数に入れ替えてるのが仇になってるんじゃないかな。callback関数は、非同期 つまり元の呼び出し時のデータではなく、その変数が最終的に持ってる値をみると言うこと。local 変数で渡すのは、メモリリークの原因にもなって危ないみたいです。
補足のスクリプトにコメント追加してみました。

for (var i=0:i<dt.length;i++) {
// var cd=dt[i][0];// 不要
// var nm=dt[i][1];// 不要
db.transaction(
function(tx) {
tx.executeSql(
/* "insert into 対象 (番号,名称) values(?,?)",[cd,nm], // ← ここ cd, nm は、変数の参照が渡されているので、実際の実行時には、最終値 つまり dt[n-1][] の値になってしまう
↓ 配列 dt[i] で入力すれば、とりあえずこの関数全体が終了するまでは、個別に違うメモリ位置を見てくれるはず。
*/
"insert into 対象 (番号,名称) values(?,?)",dt[i],
function(tx,rs) {},
fiunction(tx,er) {alert(er.message);}
);
},
function(er) {alert(er.message);},
function() {}
);
}
    • good
    • 0
この回答へのお礼

丁寧に考えていただき大変ありがとうございます。
DBの担当の人に伝えて実行してみます。
ありがとうございました。

お礼日時:2013/07/31 10:23

投稿してからもう一回見直していたら、 dt[i] の iもlocal変数だった、 i がn-1 まで回りきってから、callbackが呼ばれるので、callback 関数にもう一つかぶせないといけない


db.transaction(
 (function(x1,x2){ /* データの受け渡し用wrapper関数と引数 */
  return function(tx) {
   tx.executeSql( "insert into 対象 (番号,名称) values(?,?)",[x1,x2],
    function(tx,rs) {},
    function(tx,er) {alert(er.message);}
   );/* tx.executeSql の閉じ */
  };/* return するcallback 関数の閉じ */
 })(cd,nm) ,/* wrapper関数に渡すデータの指定。これは、 db.transaction が呼ばれた時点の変数値が入る */
 function(er) {alert(er.message)},
 function() {}
);/* transaction メソッドの閉じ */
※ ()や{} の多重入れ子で括りの対応が解らなくなるので、全角空白でインデントしてます。コピー時は、半角に変換してください。
実行チェックしてないので、まだ間違いがあるかも?
    • good
    • 0
この回答へのお礼

丁寧に説明いただきありがとうございます
DB担当の人に変更して実行してもらいます

お礼日時:2013/07/31 10:22

実行してるSQL文がないとなんとも言えないと思いますが。

この回答への補足

すみません、そうですよね。DBを担当してもらっている人から、現状をもらいます。

補足日時:2013/07/30 14:40
    • good
    • 0
この回答へのお礼

もう一つ補足の欄がないので、現状をここに記載しますので、よろしくお願いします。

 以下 dbはオープン済みのデータベースオブジェクトとする。
dtは要素が[番号,名称]の2要素からなる配列の可変長配列とする。
    (selectbox等で設定済みとする)
    テーブル「対象」は
create table 対象(番号 varchar(4),名称 varchar(20))
    で生成されている(行データは存在しない)ものとする。
 問題は配列dtの内容をテーブル「対象」に追加することである。 

    for (var i=0:i<dt.length;i++) {
     var cd=dt[i][0];
var nm=dt[i][1];
db.transaction(
function(tx) {
tx.executeSql(
"insert into 対象 (番号,名称) values(?,?)",[cd,nm],
function(tx,rs) {],
fiunction(tx,er) [alert(er.message);}
);
},
function(er) [alert(er.message),
function() {}
);
}

このプログラムを実行すると(n=dt.lengthとする)
 ・n件の行が追加される。
 ・しかしn件の行はすべて番号=dt[n-1][0]、名称=dt[n-1][1]となっている。
これはtransactionやexecuteSqlが非同期に実行されるためinsertの処理前に
ループでiが増加され(従ってcdやnmも変化する)てinsertの実行時には
i=n-1(従ってcd=dt[n-1]][0]、nm=dt[n-1][1])となっているためと思われる。
これを回避する方法が知りたいです。

お礼日時:2013/07/30 15:05

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!