MW211 EXIT

devlog
Excel/マクロショートカットの状況
2014年10月25日
Excelマクロのオプションでショートカットキーを割り当てたものの
何を割り当てたか忘れてしまった場合。

ソースコードを出力すると、ショートカットキーの割り当て状況がわかる。

例えば以下のようなマクロに「Ctrl+q」を割り当てた場合…。
┌──────────────────────────────────────┐
│Sub マクロ名()                                                              │
│    処理                                                                    │
│End Sub                                                                     │
└──────────────────────────────────────┘

以下のように、関数の先頭に一行追加されるのだ。
┌──────────────────────────────────────┐
│Sub マクロ名()                                                              │
│Attribute マクロ名.VB_ProcData.VB_Invoke_Func = "q\n14"                 ←これ
│    処理                                                                    │
│End Sub                                                                     │
└──────────────────────────────────────┘
分類:ExcelVBA
MSSQL/自然キーによる復活のトリガ
2014年10月24日
レコードを追加した時、削除レコード(削除済フラグがONのレコード)に
(自然キー基準で)該当するものがある場合に復活させるトリガは以下のような感じ。
┌──────────────────────────────────────┐
│CREATE TRIGGER [dbo].[トリガ] ON [QC工程表DB].[dbo].[表]                    │
│    INSTEAD OF INSERT                                                       │
│AS                                                                          │
│    MERGE INTO [QC工程表DB].[dbo].[表] AS [旧表]                            │
│        USING inserted AS [新表]                                            │
│        ON (                                                                │
│                [新表].[自然キー1] = [旧表].[自然キー1],                    │
│            AND [新表].[自然キー2] = [旧表].[自然キー2]                     │
│        )                                                                   │
│        WHEN MATCHED THEN                                                   │
│            UPDATE SET [列]           = [新].[列],                          │
│                       [削除済フラグ] = 0                                   │
│        WHEN NOT MATCHED THEN                                               │
│            INSERT (                                                        │
│                    [サロゲートキー],                                       │
│                    [自然キー1],                                            │
│                    [自然キー2],                                            │
│                    [列],                                                   │
│                    [削除済フラグ]                                          │
│                )                                                           │
│                VALUES (                                                    │
│                    (自動採番),                                             │
│                    [新].[自然キー1],                                       │
│                    [新].[自然キー2],                                       │
│                    [新].[列],                                              │
│                    [新].[削除済フラグ]                                     │
│                )                                                           │
│;                                                                           │
└──────────────────────────────────────┘
分類:MSSQL
MSSQL/自動採番をトリガで実現
2014年10月23日
主キー以外の項目で自動採番を実現するトリガは以下のような感じ。
(その項目にNULLが指定された場合のみ発動)
┌──────────────────────────────────────┐
│CREATE TRIGGER [dbo].[トリガ] ON [DB].[dbo].[表]                            │
│    INSTEAD OF INSERT                                                       │
│AS                                                                          │
│    INSERT INTO [DB].[dbo].[表]                                             │
│        (                                                                   │
│            [連番],                                                         │
│            [列]                                                            │
│        )                                                                   │
│        SELECT CASE WHEN [連番] IS NULL THEN                                │
│                        ISNULL(                                             │
│                            (SELECT MAX([別表].[連番])                      │
│                                 FROM [DB].[dbo].[表] AS [別表]             │
│                                 WHERE [表].[主キー] = inserted.[主キー]),  │
│                            0                                               │
│                        ) + 1                                               │
│                    ELSE                                                    │
│                        [連番]                                              │
│               END,                                                         │
│               [列]                                                         │
│            FROM inserted                                                   │
│;                                                                           │
└──────────────────────────────────────┘
分類:MSSQL
DB設計/削除済フラグと復活の考察
2014年10月22日
削除処理時、直接DELETEで抹消するのではなく、
削除済フラグを立ててで削除レコード扱いとしたとする。

この場合、自然キーとサロゲートキー(主キー)のあるレコードで
同一自然キーで再度追加したら、以下の二つの対応ができる。

(1) 削除レコードの削除済フラグを落として、上書きする(復活)
(2) 別サロゲートキーを採番して別レコードとして追加する(追加)

容量的なことを考えると前者が効率的だし、履歴管理的なことを考えると後者が実用的。

では、そのレコードに子分がいた場合には?

前者は子分も復活できるが削除した経緯を知らない人が追加したつもりで
子分が突然ゾンビのように現れてくるということがおきる。

一方後者は、親分が一度削除されたら子分も削除される。復活はできない。
CASCADEのDELETEと同じようなものだ。

どっちらかというと後者が一般的か。
間違って削除したのを復活するのは
ハードディスクから削除データを復活する的な職人技と考えれば、
前者はSQLで解決できるが、一般的には簡単にできないという点で合致する。
分類:SQL
MSSQL/括弧を含む列名の変更
2014年10月21日
┌──────────────────────────────────────┐
│SP_RENAME '[DB名].[dbo].[表名].[旧列名]', '新列名', 'COLUMN';               │
└──────────────────────────────────────┘
上記とすべきところ、うっかり下記のように変更後の名称にも「[]」をつけてしまった。
┌──────────────────────────────────────┐
│SP_RENAME '[DB名].[dbo].[表名].[旧列名]', '[新列名]', 'COLUMN';             │
└──────────────────────────────────────┘

さぁ大変とばかりに是正しようとして以下を行うも、エラーとなる。
┌──────────────────────────────────────┐
│SP_RENAME '[DB名].[dbo].[表名].[[新列名]]', '新列名', 'COLUMN';             │
└──────────────────────────────────────┘

特殊文字だから「\」とかつけてみて…もダメ。
┌──────────────────────────────────────┐
│SP_RENAME '[DB名].[dbo].[表名].[\[新列名\]]', '新列名', 'COLUMN';           │
└──────────────────────────────────────┘

答えは以下の通り、「""」で囲えばよい。
┌──────────────────────────────────────┐
│SP_RENAME '[DB名].[dbo].[表名]."[新列名]"', '新列名', 'COLUMN';             │
└──────────────────────────────────────┘

ま、途方に暮れたら「Management Studio」で手動で直すこともできるんだけどね。
分類:MSSQL
データベース/削除済みフラグと一意性制約
2014年10月20日
削除レコードを直接DELETEしたくない場合には、削除済みフラグなんかを設ける。
この時問題となるのが、自然キーの一意性制約を邪魔することだ。

例えば、会員№が自然キーでそれが「1」のレコードを削除した場合、
居座ってしまうので、再び会員№「1」のレコードを追加することはできない。

それじゃ、自然キーと削除済みフラグをまとめて一意性制約にするとする。
この場合、二回目以降の削除をすると、削除レコードが重複するので、
削除ができなくなる。

ということで、削除レコードは制約のない履歴テーブルへ移して…と考える訳だが
それをしなくても解決する方法がある。

(1) 部分インデックス(MSSQLやPostgreSQLの場合)
  条件に該当する中で一意性制約をつけるということができる。
  MSSQLではこんな感じ。
┌──────────────────────────────────────┐
│CREATE UNIQUE NONCLUSTERED INDEX [一意性制約]                               │
│    ON [dbo].[表] (                                                         │
│        [自然キー]          ASC                                             │
│    )                                                                       │
│    WHERE ([削除済フラグ] = 0);                                             │
└──────────────────────────────────────┘
  削除レコード(削除済フラグ=1)については、一意性制約が効かないので
  ちょうど、別履歴テーブルに移動したのと同じような感じになる。

(2) 一意性制約中のNULL特性(MySQLやOracleの場合)
  複合キーにNULLが混じっていると、一意性制約の範疇外となる特性を利用する。
  つまり制約を「自然キー+削除済みフラグ」にして、
  削除済みの場合は「TRUE」ではなく「NULL」としてしまうのだ。
  「自然キー+NULL」となれば一意性制約が効かないので、
  「自然キー」の部分が重複していてもいけてしまうというわけだ。
分類:SQL
PHP/パスワード管理(2)
2014年10月19日
パスワードを暗号化するのにハッシュ関数を使う。
以下は「md5()」を使った例。
┌──────────────────────────────────────┐
│$平文 = 'パスワード';                                                       │
│$暗号文 = md5($平文);                                                       │
├──────────────────────────────────────┤
│$入力文 = 'パスワード';                                                     │
│if (md5($入力文) == $暗号文) {                                              │
│    echo '合格';                                                            │
│} else {                                                                    │
│    echo '不合格';                                                          │
│}                                                                           │
└──────────────────────────────────────┘
これで、ほぼ十分なのだが、問題がある。
例えばよく使うパスワードの文字として「password」ってのがあるが
これは「5f4dcc3b5aa765d61d8327deb882cf99」に変換されるのだ。
(自分で変換してみればいい)
つまり「5f4dcc3b5aa765d61d8327deb882cf99」が流出すれば
元々「password」だったってことがわかってしまう。
この地道な作業を繰り返せば、機械的な変換表ができてしまう。

では、これにどう対策したらいいか。
つまりは、決まった変換が公になっているのが問題なのだ。

ということで、いたずらで私的な文字列を追加してあげればよい。
ハッシュ関数なのでちょっとした違いだけで、結果が大きく変わる。
こんな感じ。(「$適当な文字」には「1」とか「A」だけでもよい)
┌──────────────────────────────────────┐
│$平文 = 'パスワード';                                                       │
│$暗号文 = md5($平文 . $適当な文字);                                         │
├──────────────────────────────────────┤
│$入力文 = 'パスワード';                                                     │
│if (md5($入力文 . $適当な文字) == $暗号文) {                                │
│    echo '合格';                                                            │
│} else {                                                                    │
│    echo '不合格';                                                          │
│}                                                                           │
└──────────────────────────────────────┘
でも、問題がある。「$適当な文字」の管理が煩雑だ。
忘れると照合できなくなる一方、流出の恐れもある。
また、何をつかえばよいかも悩みどころだ。

ということで、これを簡単に実現してくれるのが「crypt()」だ。
┌──────────────────────────────────────┐
│$平文 = 'パスワード';                                                       │
│$暗号文 = crypt($平文);                                                     │
├──────────────────────────────────────┤
│$入力文 = 'パスワード';                                                     │
│if (crypt($入力文, $暗号文) == $暗号文) {                                   │
│    echo '合格';                                                            │
│} else {                                                                    │
│    echo '不合格';                                                          │
│}                                                                           │
└──────────────────────────────────────┘
「$適当な文字」的なところを、暗号文自身に付加してあげる感じ。
「crypt()」では、その「$適当な文字」的なところを抜き出して、
これを使って暗号化してくれるという仕組みだ。

なによりも「crypt($平文)」の部分は、実行する度に結果が変わる。
ハッシュを二重にかけているような感じだ。

ちなみに「crypt()」の「salt」は種別によって以下のような感じとなる。
┌───────┬──────────────────────────────┐
│CRYPT_STD_DES │xx                                                          │
├───────┼──────────────────────────────┤
│CRYPT_EXT_DES │_0000xxxx                                                   │
├───────┼──────────────────────────────┤
│CRYPT_MD5     │$1$xxxxxxxx$                                                │
├───────┼──────────────────────────────┤
│CRYPT_BLOWFISH│$2a$00$xxxxxxxxxxxxxxxxxxxxx                                │
│              │$2x$00$xxxxxxxxxxxxxxxxxxxxx                                │
│              │$2y$00$xxxxxxxxxxxxxxxxxxxxx                                │
├───────┼──────────────────────────────┤
│CRYPT_SHA256  │$5$xxxxxxxxxxxxxxxx                                         │
│              │$5$rounds=5000$xxxxxxxxxxxxxxxx                             │
├───────┼──────────────────────────────┤
│CRYPT_SHA512  │$6$xxxxxxxxxxxxxxxx                                         │
│              │$6$rounds=5000$xxxxxxxxxxxxxxxx                             │
└───────┴──────────────────────────────┘
分類:PHP
PHP/パスワード管理(1)
2014年10月18日
設定パスワードは平文で管理していては流出した時にすぐばれてしまうので
復号化できない暗号文の状態で保存しておくのが鉄則。

パスワード照合の場面では、入力された平文のパスワードを同様に暗号化、
お互い暗号文の状態として、そこで一致すれば、合格ということになる。

もし、暗号化された設定パスワードを流出し、誰かの手に渡っても
パスワード入力の場面で、それをそのまま使うとさらに暗号化されてしまい
別な文字になるので、照合できなくなる。

つまり、暗号化せずに照合するか、平文に戻して入力するかの
いずれかの方法をとらねば照合できないわけだ。
ところが、前者はもちろんシステムの問題だから手が出せない(*1)。
一方、後者は復号化できない暗号化がなされているので、無理ということになる(*2)。
  *1:但し、そういう機能が存在した場合には、そのルートをみつけだせばよい。
      よって、パスワード照合機能を実装する場合には注意が必要だ。
  *2:従って、元々のパスワードがなんだったかの問い合わせには回答できない。
      よって、パスワードを忘れた場合には、再発行ということになる。

ということで、復号化できない暗号化により、パスワードは強固なものになる。
で、その実現方法。
ハッシュ関数を使う。
まさにこれにうってつけの関数なのだ。

まず、バラバラに暗号化される。つまり、隣の文字(例えば「1」と「2」)でも
まったく関係のない文字に変換される。つまり、類推が難しい。

そして、復号化できない。
大雑把にいえば、例えば、どんな文字でも、必ず「松」「竹」「梅」に変換されるとして
「松」は元々何という文字だったか?というような仕組みだ。
もちろん、「鶴」と入力しても「亀」と入力しても「松」では、
パスワードとして不安を感じるが、この衝突が起こらない程度に大きな範囲で
変換されるのがハッシュ関数といえる。
#理論的には衝突が起きる可能性があることが復号化できないことにつながるが
  事実上は衝突が起きないという感じか。
分類:PHP
HTTP/チャンク形式
2014年10月17日
応答HTTPヘッダにて以下の形式が選択される(併存は不可)
┌──────┬─────────────┬──────────┬──────┐
│内容長形式  │Content-Length    :xxxx   │全サイズがわかる    │            │
├──────┼─────────────┼──────────┼──────┤
│チャンク形式│Transfer-Encoding :chunked│全サイズがわからない│大容量向け  │
└──────┴─────────────┴──────────┴──────┘
分類:Apache
DOSコマンド/年月日時分秒
2014年10月15日
年月日を「YYYYMMDD」形式で取得する方法。
┌──────────────────────────────────────┐
│set YMD=%date:~-10,4%%date:~-5,2%%date:~-2,2%                               │
│echo %YMD%                                                                  │
├──────────────────────────────────────┤
│set YMD=%date:/=%                                                           │
│echo %YMD%                                                                  │
└──────────────────────────────────────┘

時分秒を「HHIISS」形式で取得する方法。
┌──────────────────────────────────────┐
│set HIS=%time:~-11,2%%time:~-8,2%%time:~-5,2%                               │
│set HIS=%HIS: =0%                                                           │
│echo %HIS%                                                                  │
├──────────────────────────────────────┤
│set HIS=%time:~0,8%                                                         │
│set HIS=%HIS::=%                                                            │
│set HIS=%HIS: =0%                                                           │
│echo %HIS%                                                                  │
└──────────────────────────────────────┘
時(HH)がゼロパディングされないので、自前で行う必要がある。

バックアップファイルのファイル名などに利用できる。
分類:Windows
前へ 1 … 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 … 156 次へ