MW211 EXIT

devlog
MSSQL/文字列照合
2014年11月30日
┌──────────────────────────────────────┐
│SELECT 列                                                                   │
│    FROM 表                                                                 │
│    WHERE 列 = '値';                                                        │
└──────────────────────────────────────┘
文字列で照合をかけると意外にゆるいことに気づく。

厳密に比較するには「COLLATE」をつける。
┌──────────────────────────────────────┐
│SELECT 列                                                                   │
│    FROM 表                                                                 │
│    WHERE 列 = '値' COLLATE JAPANESE_CS_AS_KS_WS;                           │
└──────────────────────────────────────┘

パラメータの意味は以下のような感じ。
┌─┬───────────────┬─┬──────────────────┐
│CS│大文字・小文字を区別          │CI│大文字・小文字を区別しない          │
├─┼───────────────┼─┼──────────────────┤
│AS│アクセント・濁音・破裂音を区別│AI│アクセント・濁音・破裂音を区別しない│
├─┼───────────────┼─┼──────────────────┤
│KS│ひらがな・カタカナを区別      │  │                                    │
├─┼───────────────┼─┼──────────────────┤
│WS│全角・半角を区別              │  │                                    │
└─┴───────────────┴─┴──────────────────┘
分類:MSSQL
MSSQL/sqlcmdでファイル出力
2014年11月28日
sqlcmdでSQL結果をファイル出力するには、以下のような感じで実行すればよい。
┌──────────────────────────────────────┐
│sqlcmd -S . -Q "SET NOCOUNT ON SELECT * FROM 表;" -h -1 -W -o "出力先.txt"  │
│                                                                  >> log.txt│
└──────────────────────────────────────┘

特にポイントとなるのが以下の点。
┌───────┬──────────────────────────────┐
│-h -1         │列名見出しの抑止                                            │
├───────┼──────────────────────────────┤
│SET NOCOUNT ON│「(x行処理されました))」の抑止                              │
├───────┼──────────────────────────────┤
│-W            │固定長右端余白の除去                                        │
└───────┴──────────────────────────────┘
余計な装飾は除去しておこう。
分類:MSSQL
設計/横棒
2014年11月27日
数字の一とマイナスの違いぐらいはわかるけど、
他にもいろいろ紛らわしい文字があるのやら(文字コードはUTF-8)。

【全角半角変換ができるもの】(VBAの「StrConv(,vbNarrow)」「StrConv(,vbWide)」)
┌────┬─┬──────────┐  ┌────┬─┬──────────┐
│0xEFBC8D│-│全角ハイフンマイナス│⇔│    0x2D│- │半角ハイフンマイナス│
├────┼─┼──────────┤  ├────┼─┼──────────┤
│0xE383BC│ー│全角長音            │⇔│0xEFBDB0│ー │半角長音            │
└────┴─┴──────────┘  └────┴─┴──────────┘

【全角のみのもの】(半角変換ができないもの)
┌────┬─┬──────────┐
│0xE28090│‐│全角ハイフン        │
├────┼─┼──────────┤
│0xE28095│―│ホリゾンタルバー    │
├────┼─┼──────────┤
│0xE29480│─│罫線(細)            │
├────┼─┼──────────┤
│0xE29481│━│罫線(太)            │
├────┼─┼──────────┤
│0xE4B880│一│漢字(壱)            │
└────┴─┴──────────┘

【シフトJISにはないもの】(UTF-8)
┌────┬─┬──────────┐
│0xE28092│‒ │フィギュアダッシュ  │
├────┼─┼──────────┤
│0xE28094│— │半角ダッシュ        │
├────┼─┼──────────┤
│0xE28093│– │二分ダッシュ        │
├────┼─┼──────────┤
│0xE28892│− │半角マイナス        │
└────┴─┴──────────┘
分類:設計
ExcelVBA/あいまい判定
2014年11月26日
通常の判定は以下の通り。
┌──────────────────────────────────────┐
│If 変数 = "キーワード" Then                                                 │
│    MsgBox "該当あり"                                                       │
│End If                                                                      │
└──────────────────────────────────────┘

これをあいまい判定する場合には「Like」を使う。
┌──────────────────────────────────────┐
│If 変数 Like "*キーワード*" Then                                            │
│    MsgBox "該当あり"                                                       │
│End If                                                                      │
└──────────────────────────────────────┘
SQLのLike判定ライクだ。
分類:ExcelVBA
MSSQL/一意制約の後付け時に
2014年11月25日
┌──────────────────────────────────────┐
│CREATE UNIQUE NONCLUSTERED INDEX [一意制約] ON [データベース].[dbo].[表] (  │
│    [列]            ASC                                                     │
│);                                                                          │
└──────────────────────────────────────┘
一意制約を後から付けた場合に、既に重複していたらどうなるか?
┌──────────────────────────────────────┐
│オブジェクト名 'dbo.表' およびインデックス名 '一意制約' に                  │
│重複したキーが見つかったので、                                              │
│CREATE UNIQUE INDEX ステートメントは終了しました。                          │
│重複したキーの値は (■) です。                                              │
│ステートメントは終了されました。                                            │
└──────────────────────────────────────┘
一意制約を付けられないというのが正解です。
分類:MSSQL
MSSQL/更新直後トリガで表を参照した場合
2014年11月24日
「AFTER UPDATE」の時に、「inserted」ではなく表を参照した場合、
参照が反映されているかをふと気になったので確認してみた。
  →結論:反映されている

【前準備】
┌──────────────────────────────────────┐
│CREATE DATABASE [実験DB];                                                   │
├──────────────────────────────────────┤
│CREATE TABLE [実験DB].[dbo].[T_実験] (                                      │
│    [キー]              [int]               NOT NULL,                       │
│    [値1]               [int]               NULL,                           │
│    [値2]               [int]               NULL,                           │
│    CONSTRAINT [PK_実験] PRIMARY KEY CLUSTERED (                            │
│        [キー]                ASC                                           │
│    )                                                                       │
│);                                                                          │
├──────────────────────────────────────┤
│CREATE VIEW [dbo].[V_実験]                                                  │
│AS                                                                          │
│    SELECT [キー],                                                          │
│           [値1],                                                           │
│           [値2]                                                            │
│        FROM [実験DB].[dbo].[T_実験]                                        │
│;                                                                           │
└──────────────────────────────────────┘

【トリガ1】
┌──────────────────────────────────────┐
│CREATE TRIGGER [dbo].[TRIGGER_実験] ON [実験DB].[dbo].[T_実験]              │
│    AFTER UPDATE                                                            │
│AS                                                                          │
│BEGIN                                                                       │
│    BEGIN                                                                   │
│        UPDATE [実験DB].[dbo].[T_実験]                                      │
│            SET [値2] = inserted.[値1]                                      │
│            FROM inserted                                                   │
│            WHERE [T_実験].[キー] = inserted.[キー]                         │
│    END;                                                                    │
│END;                                                                        │
└──────────────────────────────────────┘
  直にinsertedを見るパターン。
  「値1」の値を変更すると「値2」に反映される。(想定通り)

【トリガ2】
┌──────────────────────────────────────┐
│CREATE TRIGGER [dbo].[TRIGGER_実験] ON [実験DB].[dbo].[T_実験]              │
│    AFTER UPDATE                                                            │
│AS                                                                          │
│BEGIN                                                                       │
│    BEGIN                                                                   │
│        UPDATE [実験DB].[dbo].[T_実験]                                      │
│            SET [値2] = [新].[値1]                                          │
│            FROM inserted                                                   │
│                INNER JOIN [実験DB].[dbo].[T_実験] AS [新]                  │
│                  ON [新].[キー] = inserted.[キー]                          │
│    END;                                                                    │
│END;                                                                        │
└──────────────────────────────────────┘
  表を参照するパターン。
  「値1」の値を変更すると「値2」に反映される。(これも想定通り)

【トリガ3】
-- DROP TRIGGER [dbo].[TRIGGER_実験];
┌──────────────────────────────────────┐
│CREATE TRIGGER [dbo].[TRIGGER_実験] ON [実験DB].[dbo].[T_実験]              │
│    AFTER UPDATE                                                            │
│AS                                                                          │
│BEGIN                                                                       │
│    BEGIN                                                                   │
│        UPDATE [実験DB].[dbo].[T_実験]                                      │
│            SET [値2] = [新].[値1]                                          │
│            FROM inserted                                                   │
│                INNER JOIN [実験DB].[dbo].[V_実験] AS [新]                  │
│                  ON [新].[キー] = inserted.[キー]                          │
│    END;                                                                    │
│END;                                                                        │
└──────────────────────────────────────┘
  仮想表を介して表を参照するパターン。
  「値1」の値を変更すると「値2」に反映される。(これも想定通り)

もし、「値1」が昔の値のままなら、「値2」も昔の値に更新される
…が、そうはならないことを確認。
分類:MSSQL
ExcelVBA/INIファイルの読み書き
2014年11月23日
クラス化すると以下のような感じ。
┌──────────────────────────────────────┐
│ClassINI.cls                                                                │
├──────────────────────────────────────┤
│Option Explicit                                                             │
│'***************************************************************************│
│'  クラス:INIファイル                                                      │
│'***************************************************************************│
│Private mINIファイル As String                                              │
│Private m環境名 As String                                                   │
│'===========================================================================│
│'  宣言:INIファイルアクセス関数(API)                                       │
│'===========================================================================│
│Private Declare Function GetPrivateProfileString Lib "kernel32" _           │
│    Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, _  │
│                                      ByVal lpKeyName As Any, _             │
│                                      ByVal lpDefault As String, _          │
│                                      ByVal lpReturnedString As String, _   │
│                                      ByVal nSize As Long, _                │
│                                      ByVal lpFileName As String) As Long   │
│Private Declare Function WritePrivateProfileString Lib "kernel32" _         │
│    Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As String, _│
│                                        ByVal lpKeyName As Any, _           │
│                                        ByVal lpString As Any, _            │
│                                        ByVal lpFileName As String) As Long │
│'===========================================================================│
│'  コンストラクタ                                                           │
│'===========================================================================│
│Private Sub Class_Initialize()                                              │
│End Sub                                                                     │
│'===========================================================================│
│'  メソッド:準コンストラクタ                                               │
│'===========================================================================│
│Public Sub 準コンストラクタ(ByVal INIファイル As String)                    │
│    If InStr(INIファイル, "\") = 0 Then                                     │
│        mINIファイル = Application.ThisWorkbook.Path & "\" & INIファイル    │
│    Else                                                                    │
│        mINIファイル = INIファイル                                          │
│    End If                                                                  │
│End Sub                                                                     │
│'===========================================================================│
│'  デストラクタ                                                             │
│'===========================================================================│
│Private Sub Class_Terminate()                                               │
│End Sub                                                                     │
│'===========================================================================│
│'  メソッド:参照                                                           │
│'===========================================================================│
│Public Function getter(ByVal セクション As String, _                        │
│                       ByVal キー As String, _                              │
│                       ByVal 既定値 As String) As String                    │
│    Dim ファイル名 As String                                                │
│    Dim リターンコード As Long                                              │
│    Dim 取得値 As String                                                    │
│    取得値 = Space$(256)                                                    │
│    リターンコード = GetPrivateProfileString(セクション, _                  │
│                                             キー, _                        │
│                                             既定値, _                      │
│                                             取得値, _                      │
│                                             255, _                         │
│                                             mINIファイル)                  │
│    If リターンコード > 0 Then                                              │
│        If InStr(取得値, Chr$(0)) > 0 Then                                  │
│            getter = Left$(取得値, InStr(取得値, Chr$(0)) - 1)              │
│        Else                                                                │
│            getter = ""                                                     │
│        End If                                                              │
│    Else                                                                    │
│        getter = 既定値                                                     │
│    End If                                                                  │
│End Function                                                                │
│'===========================================================================│
│'  メソッド:設定                                                           │
│'===========================================================================│
│Public Function setter(ByVal セクション As String, _                        │
│                       ByVal キー As String, _                              │
│                       ByVal 設定値 As String) As Long                      │
│    Dim ファイル名 As String                                                │
│    Dim リターンコード As Long                                              │
│    リターンコード = WritePrivateProfileString(セクション, _                │
│                                               キー, _                      │
│                                               設定値, _                    │
│                                               mINIファイル)                │
│    setter = リターンコード                                                 │
│End Function                                                                │
│'***************************************************************************│
└──────────────────────────────────────┘
以下のような感じで実行できる
┌──────────────────────────────────────┐
│Option Explicit                                                             │
│Public Sub 実行()                                                           │
│    Dim objINI As New ClassINI                                              │
│    Call objINI.準コンストラクタ("環境設定.ini")                            │
│    MsgBox objINI.getter("DB", "SERVER_NAME", "既定値")                     │
│    Call objINI.setter("DB", "SERVER_NAME", "設定値")                       │
│End Sub                                                                     │
└──────────────────────────────────────┘
分類:ExcelVBA
ExcelVBA/Variant型の比較
2014年11月16日
Variant型に値を代入等して比較等した結果。
┌──┬─────┬─────┬─────┬─────┬─────┬─────┐
│値\│= 0       │= 1       │= ""      │= "a"     │IsEmpty() │= Empty   │
├──┼─────┼─────┼─────┼─────┼─────┼─────┤
│未入│   ○真   │   ×偽   │   ○真   │   ×偽   │   ○真   │   ○真   │
├──┼─────┼─────┼─────┼─────┼─────┼─────┤
│   0│   ○真   │   ×偽   │   ×偽   │   ×偽   │   ×偽   │   ○真   │
├──┼─────┼─────┼─────┼─────┼─────┼─────┤
│   1│   ×偽   │   ○真   │   ×偽   │   ×偽   │   ×偽   │   ×偽   │
├──┼─────┼─────┼─────┼─────┼─────┼─────┤
│""  │   ×偽   │   ×偽   │   ○真   │   ×偽   │   ×偽   │   ○真   │
├──┼─────┼─────┼─────┼─────┼─────┼─────┤
│"a" │   ×偽   │   ×偽   │   ×偽   │   ○真   │   ×偽   │   ×偽   │
├──┼─────┼─────┼─────┼─────┼─────┼─────┤
│Null│   ×偽   │   ×偽   │   ×偽   │   ×偽   │   ×偽   │   ×偽   │
└──┴─────┴─────┴─────┴─────┴─────┴─────┘
┌──┬─────┬───────────┬─────┐
│値\│IsNull()  │= vbNullString        │Is Nothing│
├──┼─────┼───────────┼─────┤
│未入│   ×偽   │         ○真         │ (エラー) │
├──┼─────┼───────────┼─────┤
│   0│   ×偽   │         ×偽         │ (エラー) │
├──┼─────┼───────────┼─────┤
│   1│   ×偽   │         ×偽         │ (エラー) │
├──┼─────┼───────────┼─────┤
│""  │   ×偽   │         ○真         │ (エラー) │
├──┼─────┼───────────┼─────┤
│"a" │   ×偽   │         ×偽         │ (エラー) │
├──┼─────┼───────────┼─────┤
│Null│   ○真   │         ×偽         │ (エラー) │
└──┴─────┴───────────┴─────┘
┌──┬─────┬───────────┐
│値\│  Len()   │      VarType()       │
├──┼─────┼───────────┤
│未入│     0    │     0(vbEmpty)       │
├──┼─────┼───────────┤
│   0│     1    │     2(vbInteger)     │
├──┼─────┼───────────┤
│   1│     1    │     2(vbInteger)     │
├──┼─────┼───────────┤
│""  │     0    │     8(vbString)      │
├──┼─────┼───────────┤
│"a" │     1    │     8(vbString)      │
├──┼─────┼───────────┤
│Null│   Null   │     1(vbNull)        │
└──┴─────┴───────────┘
分類:ExcelVBA
SQL/順番再計算
2014年11月14日
親キーごとに基準項目を元に、連番を昇順に振り直す場合は、以下の通り。
┌──────────────────────────────────────┐
│UPDATE 表                                                                   │
│    SET 順番項目 = (                                                        │
│        SELECT COUNT(*)                                                     │
│            FROM 表 AS 順番調査                                             │
│            WHERE 順番調査.親キー   =  表.親キー                            │
│              AND 順番調査.基準項目 <= 表.基準項目                          │
│    );                                                                      │
└──────────────────────────────────────┘

但し、基準項目がグループ内で一意でなければ、同順位が発生してしまうので
便宜上、一意キー(主キーなど)で、以下のように重複を分散させる場合あり。
┌──────────────────────────────────────┐
│UPDATE 表                                                                   │
│    SET 順番項目 = (                                                        │
│        SELECT COUNT(*)                                                     │
│            FROM 表 AS 順番調査                                             │
│            WHERE 順番調査.親キー = 表.親キー                               │
│              AND (順番調査.基準項目 < 表.基準項目                          │
│               OR  (順番調査.基準項目 =  表.基準項目                        │
│                AND 順番調査.一意キー <= 表.一意キー))                      │
│    );                                                                      │
└──────────────────────────────────────┘
分類:SQL
ExcelVBA/IsEmpty関数の罠
2014年11月10日
「IsEmpty()」は「0」や「""」(長さ0の文字列)を比較する関数ではなく
未初期化(定義後一度も代入していない)を判定する関数なのだ。
┌──────────────────────────────────────┐
│Dim 変数 As Variant                                                         │
│MsgBox IsEmpty(変数) ' →True                                               │
│変数 = 0                                                                    │
│MsgBox IsEmpty(変数) ' →False                                              │
└──────────────────────────────────────┘
分類:注意、ExcelVBA
前へ 1 2 次へ