Rubyで同じ様なreplace文を簡単に書きたい

このQ&Aのポイント
  • Rubyで同じ様なreplace文を簡単に書く方法を教えてください。
  • 質問者はdb.executeメソッドの引数を可変のパラメータとして渡したいと考えています。
  • 具体的には、replaceメソッドにテーブル名とキーの配列、値の配列を渡して、db.executeメソッドのパラメータに展開したいとのことです。
回答を見る
  • ベストアンサー

ruby 毎回同じ様なreplace文を書くのイヤ

db = SQLite3::Database.new('hoge.db') で、 db.execute('replace into table01 (a, b, c, d, e, f, g) values(?, ?, ?, ?, ?, ?, ?)',va, vb, vc, vd, ve, vf, vg); とかって書いてるのですが、 これを、 def replace(table,k,v) db.execute('replace into ' + table + '(' + k.join(',') + ') values('+ k.collect {'?'}'.join(’,’) +')' , ここどうかいたら??) end みたいな事を考えたのですが、vって配列でもらった値をばらばらにdb.executeのパラメータに渡したいのですが、 できませんでして、 replace('table',%w(a, b, c, d, e, f, g),[va, vb, vc, vd, ve, vf, vg]) みたいに使いたいです。 引数が可変のパラメータをそのまま、つぎの関数に渡すみたいな。 なんか、ラクする方法ないですか? ご教授の程、宜しくお願いいたします。

  • Ruby
  • 回答数1
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
  • sholmes
  • ベストアンサー率81% (89/109)
回答No.1

そのまま、可変長引数として取り扱えますよ。 http://doc.ruby-lang.org/ja/1.9.3/doc/spec=2fdef.html#method 受ける側のメソッド内で*を外すと、Array扱いになります。 また、Arrayやらといったオブジェクトに*を付けてやると、他のメソッドへバラけたパラメータとして渡すことができます。 http://ideone.com/jbWZX 記載された例で行くと、 (動作チェックはしていません。「v」の扱い方についてだけです) # このように使いたいなら replace('table',%w(a, b, c, d, e, f, g),[va, vb, vc, vd, ve, vf, vg]) # こうします。 def replace(table, k, v) db.execute('replace into ' + table + '(' + k.join(',') + ') values('+ k.collect {'?'}'.join(’,’) +')' , *v) end # このように使いたいなら replace('table',%w(a, b, c, d, e, f, g), va, vb, vc, vd, ve, vf, vg) # こうします。 def replace(table, k, *v) db.execute('replace into ' + table + '(' + k.join(',') + ') values('+ k.collect {'?'}'.join(’,’) +')' , *v) end

kingfruits
質問者

お礼

sholmesさん ご回答ありがとう御座いました。 おかげさまで、上手く出来ました。

関連するQ&A

  • REPLACEクエリで条件文を使用するには?

    REPLACEクエリで条件文を使用するには? 以下で、bannedカラムがtrueの時だけfalseに変更しないようにするにはどうすればいいでしょうか? /*テーブルを作成*/ CREATE TABLE test (name CHAR(100) UNIQUE, banned BOOLEAN DEFAULT FALSE NOT NULL); /*bannedカラムにfalseを注入*/ REPLACE INTO test (name) VALUES('鈴木'); /*bannedカラムをfalseからtrueに変更*/ REPLACE INTO test (name,banned) VALUES('鈴木',true); /*このクエリを実行してもbannedカラムをtrueからfalseにしないようにするには*/ REPLACE INTO test (name) VALUES('鈴木');

    • ベストアンサー
    • MySQL
  • 連続で実行するには?

    下のように、PostgreSQL に接続して insert を実行するプログラムを書いたのですが、 これらの3つのinsert 文を一気に実行してしまいたい場合、どうすればよいのでしょうか? // insert $sql = "insert into area values (1,'中央区')"; $sql = "insert into area values (2,'東区'); $sql = "insert into area values (3,'西区'); //ここより本文です。 <?php // connect $db_con = pg_connect("","","fuk_gourmet"); if($db_con == false) {print "cannot connect"; exit;} // insert (これだと一つしか実行できない) $sql = "insert into area values (1,'中央区')"; // execute $rs = pg_exec($db_con, $sql); if($rs == false) {print "execute error"; exit;} pg_freeresult($rs); pg_close($db_con); ?>

    • ベストアンサー
    • PHP
  • CSVを取込むストアドプロシージャで、1件目が登録されない現象が起きています

    いつもお世話になっております 古い環境なので大変恐縮ですが、行き詰ってしまったので、 ご教示いただきたいと思います。 環境: WinXP sp2 SQLServer8.0 VB6.0 sp4 VBでCSVのデータ1行について、ストアドプロシージャにて3つのテーブルに格納しようとしています。 トランザクションの管理はVB側で行っています。 1行ごとにCommitを行えば、全行格納されるのですが、 2行以上ごとにCommitを行うと、最初の1行のみが格納されないという現象がおきています。 6800行存在する同じCSVファイルについて、1行ごとにCommitを行った場合は、6800件登録されるのに 処理の最後でCommitをきった場合、6799行しか登録されません。 1行ごとにCommitをきった場合に6800行登録されるので、キー重複は考えられません。 いろいろ試してみたことを下記に書きます 結果はこのような感じです。 CASE1・・・全件登録できます CASE2・・・2件目で重複エラーが発生します CASE3・・・全件 - 1件が登録できます CASE4・・・全件登録できます CASE5・・・全件登録できます CASE2, CASE3 で全件登録できない理由をご教示いただきたく思います。 よろしくお願いいたします。 CASE1(VBでINSERT文を記述)  localConnection.beginTrans localConnection.execute "DELETE FROM TABLE_A" localConnection.execute "DELETE FROM TABLE_B" localConnection.execute "DELETE FROM TABLE_C" FOR i = 1 to 6800 localConnection.execute "INSERT INTO TABLE_A (COL_A1, COL_A2) VALUES ('" & VAL_A1(i) & "','" & VAL_A2(i) & "')" localConnection.execute "INSERT INTO TABLE_B (COL_B1, COL_B2) VALUES ('" & VAL_A1(i) & "','" & VAL_B2(i) & "')" localConnection.execute "INSERT INTO TABLE_C (COL_C1, COL_C2) VALUES ('" & VAL_A1(i) & "','" & VAL_C2(i) & "')" NEXT  localConnection.commitTrans CASE2(ストアドプロシージャ) localConnection.beginTrans localConnection.execute "DELETE FROM TABLE_A" localConnection.execute "DELETE FROM TABLE_B" localConnection.execute "DELETE FROM TABLE_C" ' -- ストアドプロシージャのパラメータ作成 FOR i = 1 to 6800 localConnection.execute NEXT  localConnection.commitTrans CASE3(ストアドプロシージャ) localConnection.beginTrans localConnection.execute "DELETE FROM TABLE_A" localConnection.execute "DELETE FROM TABLE_B" localConnection.execute "DELETE FROM TABLE_C"  localConnection.commitTrans ' -- ストアドプロシージャのパラメータ作成 localConnection.beginTrans FOR i = 1 to 6800 localConnection.execute NEXT  localConnection.commitTrans CASE4(ストアドプロシージャ) localConnection.beginTrans localConnection.execute "DELETE FROM TABLE_A" localConnection.execute "DELETE FROM TABLE_B" localConnection.execute "DELETE FROM TABLE_C"  localConnection.commitTrans ' -- ストアドプロシージャのパラメータ作成 localConnection.beginTrans FOR i = 1 to 6800 localConnection.execute   localConnection.commitTrans   localConnection.beginTrans NEXT  localConnection.commitTrans CASE5(ストアドプロシージャ) localConnection.beginTrans localConnection.execute "DELETE FROM TABLE_A" localConnection.execute "DELETE FROM TABLE_B" localConnection.execute "DELETE FROM TABLE_C"  localConnection.commitTrans ' -- ストアドプロシージャのパラメータ作成 localConnection.beginTrans FOR i = 1 to 6800 localConnection.execute if i = 1 then   localConnection.commitTrans   localConnection.beginTrans end if NEXT  localConnection.commitTrans

  • PDOのprepareの使い方が正しいのか教えてください

    1つのレコードに入った二つのデータを反映させようと思ってますが、 prepareの使い方を教えてください。 持っている参考書があまり参考にならず困っているのですが、 prepareを使った再利用のやり方として、下記の方法は正しいでしょうか? $sql = "INSERT INTO $table (name,birth) VALUES(:name,:birth);"; $statement = $dbh->prepare($sql); $rtn = $statement->execute(array('太郎','2000/01/01')); $rtn = $statement->execute(array('花子','2000/10/31')); 一応、DBにデータの追加はでてきますが、 検索すると、 $statement->bindValue(':name',$name,PDO::PARAM_INT); を使ったやり方がたくさん出てきていて、 何が正しいやり方なのかよくわかりません。 宜しくお願いいたします。

    • ベストアンサー
    • PHP
  • あるカラムのMAX値+1をINSERTしたい。

    DB2環境です。 ある列のMAX値+1をINSERTしたいと思っています。 INSERT INTO TableName (atai1) Values ((SELECT MAX(BILLSUBNO)+1 FROM TR0400)) このように書いてみたのですが、「入力ホスト変数または パラメーター*Nで変換エラー」 と言われてしまい、コミットすることが出来ません。 +1を除けば出来るのですが、DB2ではVALUESの中で演算をすることは できないのでしょうか? もし方法がありましたら、教えてください。

  • 指定された趣味を持つメンバーがいるグループを抽出するSQL

    グループテーブル、メンバーテーブル、趣味テーブルの3つのテーブルがあります。 あるメンバーはあるグループに属しており、趣味を1つ持っています。 以下がそのSQLです。 CREATE TABLE groups ( g_id int primary key ); CREATE TABLE members ( m_id int primary key , g_id int , h_id int ); CREATE TABLE hobbies ( h_id int primary key, h_name text ); INSERT INTO groups VALUES ( 1 ); INSERT INTO groups VALUES ( 2 ); INSERT INTO groups VALUES ( 3 ); INSERT INTO members VALUES ( 1, 1, 1); INSERT INTO members VALUES ( 2, 1, 3); INSERT INTO members VALUES ( 3, 1, 4); INSERT INTO members VALUES ( 4, 1, 4); INSERT INTO members VALUES ( 5, 2, 1); INSERT INTO members VALUES ( 6, 2, 2); INSERT INTO members VALUES ( 7, 2, 3); INSERT INTO members VALUES ( 8, 3, 2); INSERT INTO members VALUES ( 9, 3, 3); INSERT INTO members VALUES ( 10, 3, 4); INSERT INTO hobbies VALUES ( 1, 'sports' ); INSERT INTO hobbies VALUES ( 2, 'music' ); INSERT INTO hobbies VALUES ( 3, 'book' ); INSERT INTO hobbies VALUES ( 4, 'drive' ); 指定された趣味を持つメンバーがいるグループを抽出するにはどうすればいいでしょうか? 例えば、「読書が趣味なメンバーとドライブが趣味なメンバーがいるグループは?」「グループ1とグループ3」のような感じです。 一応自分で考えてみたのが、以下ですが、これだと趣味の指定が増減すると大きくSQLが変わってしまいます。 もっといいやり方はないでしょうか? 私はPostgreSQL8を使ってますが、汎用的なSQLであれば、そっちの方がいいです。 SELECT distinct m.g_id FROM members m join hobbies h ON m.h_id = h.h_id where h.h_name = 'drive' INTERSECT SELECT distinct m.g_id FROM members m join hobbies h ON m.h_id = h.h_id where h.h_name = 'book';

  • SQLServerでREPLACE/SELECTができるか?

    My-SQLでは以下のSQLにより test01というDBからtest02というDBへ データをinsertすることができると思います。 また「insert」ではなく「replace」にすることで 同一キーの場合エラーにならず置き換えで データを登録してくれます。 ======================================= insert into [test01].dbo.test_table select * from [test02].dbo.test_table ======================================= そこで上記の「replace」を同じように SQLServerでできないか知っている方が おられたら是非ご教授いただきたく。 よろしくお願いいたします。

  • PerlからDB接続し、データ登録時のエラー処理について

    PerlからDB接続し、データ登録時のエラー処理について DBにデータを登録するときにエラー処理を加えたいと思っていますが、 色んなサイトを参考にさせて頂いて、下記のようにしてみたのですが うまくできません。 $sth = $db->prepare(" INSERT INTO DBNAME (hinmei,su,tani,tuikabi) VALUES($hinmei,$su,$tani,$hiduke) "); if(!$sth->execute){  print "接続エラー";  exit; } または、 $sth = $db->prepare(" INSERT INTO DBNAME (hinmei,su,tani,tuikabi) VALUES($hinmei,$su,$tani,$hiduke) "); $sth->execute or &error('DBに登録出来ません'); 両方とも登録出来なければエラーメッセージを出すように してみたのですが、キー項目が同じものを登録しようとすると $sth->execute この部分でとまってしまうらしく、次の処理に行きません。 もちろん、キー項目が同じでなければDBに登録出来ます。 どうすればエラー処理の設定ができるでしょうか。 教えてください。 お願いします。

    • ベストアンサー
    • Perl
  • INSERT文でフィールドの1つだけを他のテーブルから取ってきた値を入れたい

    挿入するフィールドの内1つだけを他のテーブルから取ってきた値を使いたいのですが、 insert into table1 (field1, field2, field3) values('a', (select field2 from table2 where field4='xxx'), 'b'); Oracleだと↑の書き方でいけるのですが、PostgreSQL(6.5.3)だとエラーになってしまいます。 2回もDBにアクセスしにいくのはいやなので、1文で書きたいです。上記以外で他の書き方をご存知でしたら教えてください。よろしくお願いします。

  • sqliteについて質問があります。

    sqliteについて質問があります。 db browser for sqlite でテーブルを作成したのですが、これをhtmlやphpなどを使いweb上で利用したいです。 例えば、ユーザーが”男”を選択したら”男”のデータ一覧が表示されるようにしたいのですがどうプログラムすればいいですか? 作れたファイルはtest.dbです。 (test.dbは開けませんでしたので以下、test.dbのhumanテーブルです。) BEGIN TRANSACTION; CREATE TABLE IF NOT EXISTS "human" ( "id" INTEGER NOT NULL, "name" TEXT NOT NULL, "sex" TEXT NOT NULL, "age" INTEGER NOT NULL, "prefecture" TEXT, "country" TEXT NOT NULL, PRIMARY KEY("id") ); INSERT INTO "human" VALUES (1,'中村静香','男',48,'千葉','japan'); INSERT INTO "human" VALUES (2,'中村ゆり','女',45,'埼玉','japan'); INSERT INTO "human" VALUES (3,'本田翼','女',22,'','japan'); INSERT INTO "human" VALUES (4,'本田望結','男',16,'東京','japan'); INSERT INTO "human" VALUES (5,'綾瀬はるか','女',34,'東京','japan'); INSERT INTO "human" VALUES (6,'中村アン','男',38,'','usa'); INSERT INTO "human" VALUES (7,'広瀬アリス','女',26,'東京','japan'); INSERT INTO "human" VALUES (8,'有村架純','男',31,NULL,'usa'); INSERT INTO "human" VALUES (9,'長澤まさみ','女',29,NULL,'uk'); INSERT INTO "human" VALUES (10,'有村藍里','男',18,'埼玉','japan'); COMMIT;

    • ベストアンサー
    • PHP