- ベストアンサー
SQLで半角文字⇒全角変換し特定の文字列を取りたい
- テーブルAの内容の半角文字を全角変換し、特定文字列を取り除く処理を行いたいです。
- SQLでテーブルAの文字列をテーブルBの項目B_Aの内容に該当する文字列をテーブルBの項目B_Bに置き換えを行い、テーブルAを更新(UPDATE)したいです。
- 簡潔に言うと、テーブルAの内容の半角文字を全角変換し、特定文字列を取り除く処理を行いたいです。
- みんなの回答 (8)
- 専門家の回答
質問者が選んだベストアンサー
「1.どうしてtable_a(更新したいデータが入っているテーブル)を1件も読んでいない(FETCHしていない)のに全てのtable_aのデータが更新されるのでしょうか?」 UPDATEをストアド内に記述していますが、回答No.6で実行していただいたのと同じで、単純なUPDATEでtable_aを更新しています。 無条件と言ったのは、WHEREなしで全レコードを対象にする、と言う意味です。 回答No.1のストアドでは、最初に質問された時の、table_aを1件ずつtable_bの件数分処理する、ようにしたので、現在読んでいる1件をidで指定する必要がありました。 FETCHはCURSORに基づいてレコードを読むためのものなので、更新に必要なものではありませんし、CURSORは読み取り専用です。 「2.ストアドプロシジャーを書いていてよく起きたエラーなのですが、IFやCASEのTHEN(ELSEも同じ)には1行しか記載出来ないのでしょうか?」 命令ひとつずつにデリミタ(通常はセミコロン)を入れてみてください。 IF XXXX THEN SET AAA = 'AAA'; SET BBB = 'BBB';
その他の回答 (7)
- dell_OK
- ベストアンサー率13% (766/5720)
SQLでは置換できたようですので、UPDATEで直接するようにしてみました。 テーブルBだけをもとにループして、テーブルAを無条件にUPDATEします。 質問者さまの方でこれがうまくいくとも言えませんので、環境による差異があるのかも知れません。 うまくいかなかった場合は、データベースやテーブルの照合順序、文字列項目のデータ型と長さを教えてください。 ちなみに私の環境は、照合順序はutf8mb4_general_ciで、データ型はtext(長さはありません)にしています。 BEGIN DECLARE done int DEFAULT FALSE; DECLARE b_a_text text; DECLARE b_b_text text; DECLARE cur_b CURSOR FOR SELECT B_A,B_B FROM table_b ORDER BY LENGTH(B_A) DESC; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN cur_b; read_loop_b:LOOP FETCH cur_b INTO b_a_text,b_b_text; IF done THEN LEAVE read_loop_b; END IF; UPDATE table_a SET A_Z = REPLACE(A_Z,b_a_text,b_b_text); END LOOP; CLOSE cur_b; END
補足
ご回答いただきありがとうございます。 この書き方ですと全て更新がかかりました。 すみませんが以下質問させてください。 1.どうしてtable_a(更新したいデータが入っているテーブル)を1件も読んでいない(FETCHしていない)のに全てのtable_aのデータが更新されるのでしょうか? 2.ストアドプロシジャーを書いていてよく起きたエラーなのですが、IFやCASEのTHEN(ELSEも同じ)には1行しか記載出来ないのでしょうか? IF XXXX THEN SET AAA = 'AAA' SET BBB = 'BBB' のようにTHENの中に複数の文を書くと、エラーになってしまいます。 (素人の質問で申し訳ありません)
- dell_OK
- ベストアンサー率13% (766/5720)
なんだか不思議な状態ですね。 では、このSQLを実行してみていただけますか。 UPDATE TABLE_A SET A_Z = REPLACE (A_Z, 'カ', 'カ'); これで半角「カ」が全角「カ」に置換されるかどうか。
補足
お手数をお掛けして申し訳ありません。 UPDATE TABLE_A SET A_Z = REPLACE (A_Z, 'カ', 'カ'); を実行したところ、 (株)あカあイa になりました。
- dell_OK
- ベストアンサー率13% (766/5720)
半角の円マークは2個書いてみてください。 INSERT INTO TABLE_B(B_A,B_B) VALUE('\\', '¥');
- dell_OK
- ベストアンサー率13% (766/5720)
そうでしたか。 もしかしたら文字コードのせいかと思って、テーブルAとテーブルBの照合順序をUTF8とシフトJISで別々にして試してみたのですが、変換されてしまったので、文字コードは関係なさそうですね。 アルファベットも追加してみてどうなるか確認できますでしょうか。 あと、B_Aに「カ」と見えていて「カ 」のように空白が付いていないでしょうか。
補足
ご回答ありがとうございます。 登録はこんな感じで書いています。 INSERT INTO TABLE_B(B_A,B_B) VALUE('a゙','a'); INSERT INTO TABLE_B(B_A,B_B) VALUE('ガ', 'ガ'); 余計なスペースなどは入っていないと思います。 よく分らないのが、(株)などは '' (取り除き)出来るのですが、半角カタカナ(もしくは記号?)が混在している置き換え(カ ⇒ カなど)が出来ないような感じです。半角カタカナ(もしくは記号?)が混在していない場合は英文字の変換は出来ますが、混在していると見た目は正常に処理されますが、変換が行われていません。 ※上記内容とは関係ないと思いますが、円マーク(¥)を登録しようとするとエラーになるのは仕様なのでしょうか?
- dell_OK
- ベストアンサー率13% (766/5720)
私の方では変換されました。 テーブルBに「カ:カ」「a:a」があるので、他の半角文字もすべて登録されているのかと思っていましたが、そうではないのでしょうか。 半角文字は英数カタカナで150文字程度あると思いますのですべて登録してください。 テーブルBのようなものを使用しないで半角全角変換する機能を持っているデータベースはたぶんなかったと思います。 別の方法で変換することもできます。 例えば、ExcelやAccessのVBAに全角変換する機能があるので、ODBCを使ってデータベースに接続して、全角変換と特定文字の削除をして更新する方法です。 こちらの方法がよろしければそれを案内させていただきます。
補足
テーブルBをカタカナのみにしてもやっぱり変わりません。 変更をかける文字列(テーブルA) A_Z:アセットマネジメントーOne・ 本来であれば結果として、 アセットマネジメントーOne・ となるはずですが、変換前と同じ結果です。 Query OK, 0 rows affected (0.00 sec) と返ってきますが。 テーブルAまたはテーブルBの登録内容がおかしいのでしょうか? ちなみにカタカナだけ登録したため、テーブルBは全部で84文字でした、(濁点付きや半角小文字('ッ','ッ')も含みます)
- dell_OK
- ベストアンサー率13% (766/5720)
書き忘れました。 テーブルAには、プライマリーキーとなる「id」がある前提なので、UPDATEのWHEREで使える項目があれば、それに替えてください。
補足
ご回答いただきありがとうございます。 試してみたのですが、全角文字の置き換え((株)を取るなど)は旨く動きますが、半角文字を全角に置き換え(カタカナ)が置き換わってくれないみたいです。
- dell_OK
- ベストアンサー率13% (766/5720)
MySQLでストアドプロシージャーを作ってみました。 メモ テーブルBをB_Aの文字長の逆順で読んでいるのは、例えば、「ケ"」→「ゲ」と「ケ」→「ケ」があった場合に、先に「ケ」が置換されると「ケ"」が「ケ"」(ケと濁点)になってしまい一文字の「ゲ」にならなくなるため、なるべく文字数の多い方から置換した方が安全かと思ってのことです。 BEGIN DECLARE done int DEFAULT FALSE; DECLARE a_id int; DECLARE a_z_text text; DECLARE a_z_new_text text; DECLARE b_a_text text; DECLARE b_b_text text; DECLARE cur_a CURSOR FOR SELECT id,A_Z FROM table_a; DECLARE cur_b CURSOR FOR SELECT B_A,B_B FROM table_b ORDER BY LENGTH(B_A) DESC; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN cur_a; read_loop_a: LOOP FETCH cur_a INTO a_id,a_z_text; SET a_z_new_text = a_z_text; IF done THEN LEAVE read_loop_a; END IF; OPEN cur_b; read_loop_b:LOOP FETCH cur_b INTO b_a_text,b_b_text; IF done THEN LEAVE read_loop_b; END IF; SET a_z_new_text = REPLACE(a_z_new_text,b_a_text,b_b_text); END LOOP; CLOSE cur_b; IF a_z_text != a_z_new_text THEN UPDATE table_a SET A_Z = a_z_new_text WHERE id = a_id; END IF; SET done = false; END LOOP; CLOSE cur_a; END
お礼
丁寧なご回答いつもありがとうございます。 分かりやすくとても助かりました。