自作アドインの作り方
シートをコピーして名前を変更するプロシージャ
サンプルには記載していませんが、
シート操作はエラーが起きやすいので、必要に応じてエラー処理が必要になります。
左からA,B,Cとシートが並んでいるとき
コピー元としてシートB、コピーしたシートに付ける名前として「D」を引数にして
このサンプルを実行すると、A,D,B,C という並びになります。
'* '* シートをコピーする '* '* in wsBaseSheet コピー元ワークシート '* sNewSheetName コピー後のシート名 '* Private Sub SheetCopy(ByVal wsBaseSheet As Worksheet, ByVal sNewSheetName As String) Dim lFmtIndex As Long Dim lNewIndex As Long 'シートをコピーして、コピー元の手前に置く wsBaseSheet.Copy Before:=wsBaseSheet 'コピー元シートのインデックスを取得する lFmtIndex = Sheets(”コピー元シート名”).Index 'コピー先のインデックスは「コピー元 - 1」 lNewIndex = lFmtIndex - 1 'コピー先シートの名前を変更する ThisWorkbook.Sheets(lNewIndex).Name = sNewSheetName End Sub
ざっくりSQL入門 #11:トランザクション
※MySQLを前提に書いています。一部関数などは方言差がある場合もあるのでご注意ください。
今回はトランザクションについて。
トランザクションとは
「分けることのできない複数の処理をまとめた単位」です。
(データベースに限った意味合いではありませんが、以降、データベースについての話とします)
例えばどういうこと?
ひとつの処理に対して、複数のテーブルに対する更新が発生する場合があります。
例えば通販サイトの購入手続き時…
注文のメイン情報であるorderテーブル(order_id, user_id, name, address, ...)と
orderに紐づき、購入商品単位のデータをもつorder_productテーブル(order_id, product_id, count, price, ...)
の2つがあるとします。
注文が発生すると、それぞれのテーブルにINSERTが発生することになります。
order
order_id | user_id | name | address | ... |
51088 | 43109 | 鈴木太郎 | 東京都新宿区... | ... |
order_product
order_id | product_id | count | price | ... |
51088 | 101 | 2 | 2000 | ... |
51088 | 102 | 5 | 5000 | ... |
このとき、orderへのINSERTは成功し、order_productへのINSERTは失敗してしまうと、
orderにだけ中途半端なデータが残ってしまうことになります。
それでは困る、というときに、この2つのINSERTをまとめてひとつのトランザクションにするのです。
具体的にはどう書くの?
トランザクションの開始時に「BEGIN(もしくは START TRANSACTION)」
トランザクションの正常終了時に「COMMIT」
トランザクションを全部取り消したいときに「ROLLBACK」です。
COMMITを書いていない場合や途中でエラーになった場合は、
ROLLBACKを明示しなくとも全部取り消されます。
BEGIN; INSERT INTO `order` VALUES ... INSERT INTO `order_product` VALUES ... COMMIT;
SQLを手打ちするだけならROLLBACKを使うことはそうそうないのですが、
アプリケーションで実装する場合は例えば以下のようなパターンが実現できます。
// UPDATEを行うが、 // その結果が1件以下ならそのUPDATEを取り消し、 // 2件以上なら別のテーブルにもINSERTを行う BEGIN; UPDATE `hoge` SET ... ; if ( /* UPDATEの結果が1件以下 */ ) { ROLLBACK; } else { INSERT `fuga` ... ; COMMIT; }
暗黙的なコミットについて
「TRUNCATE TABLE」など一部の構文については、コミットが発生してしまうため注意が必要です。
過去に詳しく書いていますのでリンクにとどめておきます。
トランザクションの挙動検証 - アナログCPU:5108843109
プレースホルダのいい感じの作り方
頭が悪いタイトル。
例えば以下のようなクエリを組み立てることはよくあるのですが
SELECT ... FROM ... WHERE `id` IN (1, 2, 3, ...)
ここ。
IN (1, 2, 3, ...)
ここをPHP上で組み立てるのに最初は苦労しましたが、今は以下のように書いています。
$param_list = array(1, 2, 3, ...); $query = "SELECT ... "; $query .= "FROM ... "; $query .= "WHERE `id` IN (" . implode(",", array_fill(0, count($param_list), "?")) . ") ";
理屈は以下のとおり。
- $param_listの要素個数分の配列を生成し、中身は「?」にする
- implodeを用いてカンマ区切りの文字列に変換する
PHPは配列まわりの関数を使いこなすとこうやってあっさり1行で済むのが楽しいところですね。
ただ、毎回コピペしてるけどもうちょっとスマートにしたいな。
ざっくりSQL入門 #10:一時テーブルを活用する
※MySQLを前提に書いています。一部関数などは方言差がある場合もあるのでご注意ください。
今回は一時テーブルについて。
一時テーブルとは、普段使用しているテーブルとは異なり、その名の通り、一時的に保持されるテーブルです。
作成した一時テーブルはそのセッションでのみ使用可能で、セッションが閉じられるときに自動で削除されます。
複数のセッションが同時に同じ名前の一時テーブルをそれぞれで作成・使用することができます。
基本的な構文
以下の書き方で、結果セットを簡単に一時テーブル化することができます。
CREATE TEMPORARY TABLE 【一時テーブル名】 SELECT ...
このテーブルはセッション終了時に削除されますが、個人的には明示的に削除するのが好きです。
DROP TEMPORARY TABLE IF EXISTS 【一時テーブル名】
活用例
普通は一時テーブルを用いることなく対応可能でしょうが、
一時テーブルを活用することで、可読性や実行速度などが大幅に向上する場合があります。
(個人的に)ありがちな例を以下に記載します。
- 複雑な集計を行い、その結果に対してさらに処理を加えたい場合
- 何らかのスコア計算を行い、それに順位を付けたい、など
- あるレコード群に対して、段階的に処理を加えたい場合
- Aに該当するレコードにaの処理を加え、それ以外でBに該当するレコードにbの処理を加え…
- 大規模なINSERTレコードを生成する場合
- いくつかの複雑な条件を用いて一時テーブル上にINSERTしたいレコード群を構築していき、最後に一括でINSERTする
ざっくりSQL入門 #8:クエリを書く<データの削除編>
※MySQLを前提に書いています。一部関数などは方言差がある場合もあるのでご注意ください。
今回は、DELETEやTRUNCATEの構文を用いて、レコードの削除を行う方法について。
DELETEとは
指定したレコードを削除します。
指定方法はおなじみWHERE句。
DELETE FROM 【テーブル名】 WHERE 【条件】
WHERE句の条件に合うレコードがすべて削除されますし、
WHERE句を省略すると全件削除されるため、実行前にはくれぐれも注意してください。
TRUNCATEとは
指定したテーブルを空にします。
TRUNCATE TABLE 【テーブル名】
これだけ。
空にするということはつまり全件削除されるため、
こちらも実行前にはくれぐれも注意してください。
全件削除するときはどちらがいいの?
前述のとおり、DELETEもWHERE句を省略すればテーブルが空になります。
TRUNCATEとどちらを用いるべきかは、
以下の違いを参照の上、適した方を選ぶことになります。
TRUNCATE | DELETE | |
速度 | 高速 | 低速 |
auto_increment | 初期化される | 変わらない |
トランザクション | ロールバック不可(暗黙のコミット) | ロールバックできる |
少なくとも、「auto_incrementを維持したい」「トランザクション内で実行する」という場合は
DELETEを選ぶ必要があるというわけです。
(トランザクションについては後から説明しています)
これらの差異は、
TRUNCATEは内部的に「テーブルを一度削除して同じ構造の空テーブルを作る」という処理で、
DELETEはあくまで「レコードを削除する」という処理、という根本的な違いから来ています。
削除対象がどれだけあろうとテーブルを作り直すだけのTRUNCATEは高速ですが、
新しいテーブルなのでauto_incrementもリセットされますし、
消えるレコードの中身を見ることもないので復元ができない…ということです。
FE聖戦:ネタバレを避けたかんたん攻略メモ(後半)
ネタバレは見たくないけど手に入るアイテムなどを把握しておきたかった自分用メモ、後半戦。
前半に比べると「重要アイテムだけどなかなか気づかない条件」は少なそうだけども。
前半はこちら
FE聖戦:ネタバレを避けたかんたん攻略メモ(前半) - アナログCPU:5108843109
手に入るアイテムメモ
- 6章
- 7章
- ゆうしゃの剣(パティ→セリス 会話)
- トローン(イシュトーを倒す)
- スピードリング(レンスター城南東の村)
- シールドリング(ダーナ城西の村)
- バリアの剣(レイリアでレンスター城に一番近い村)
- 【未継承の場合】ねぎりのうでわ(クトゥーゾフを倒す)
- 【未継承の場合】スキルリング(ジャバローを倒す)
- 【未継承の場合】マジックリング(ライザを倒す)
- 【未継承の場合】ナイトキラー(ブラムセルを倒す)
- 【未継承の場合】ぎんの大剣(ブルームを倒す)
- 8章
- パワーリング(一番北の村)
- シーフのうでわ(一番南東の村)
- 【未継承の場合】ゆうしゃのやり(ムハマドを倒す)
- 【未継承の場合】シールドリング(オーヴォを倒す)
- 【未継承の場合】ゆうしゃのゆみ(コノート城西のジェネラルを倒す)
- 【未継承の場合】ゆうしゃの剣(コルータを倒す)
- 【未継承の場合】いのりの剣(たいちょうを倒す)
- 【未継承の場合】キラーボウ(マイコフを倒す)
- 9章
- 10章
- 終章
- ナーガ(ユリアがヴェルトマー城に入城)