MW211 EXIT

devlog
MSSQL/スクリプト生成
2015年01月11日
「SQL Server 2014 Management Studio」にて
スクリプト生成時に詳細オプションを変更すべきところは以下の通り。
┌─────────────────────────┐
│テーブル/ビューオプション                        │
│  ┌────────────────┬──────┤  ┌────────┐
│  │トリガーのスクリプトを生成      │False       │→│True            │
├─┴────────────────┴──────┤  └────────┘
│全般                                              │
│  ┌────────────────┬──────┤  ┌────────┐
│  │スクリプトを生成するデータの種類│スキーマのみ│→│スキーマとデータ│
└─┴────────────────┴──────┘  └────────┘
分類:MSSQL
MSSQL/文字型
2015年01月07日
基本的な文字型には以下の種類がある(固定か?可変か?、半角か?全角か?)
  ・「char」型      (固定長半角)
  ・「nchar」型     (固定長全角)
  ・「varchar」型   (可変長半角)
  ・「nvarchar」型  (可変長全角)

・固定長(「var」なし)の場合は、その決まった長さまで末尾に空白が埋められる。
・半角(「n」なし)の場合でも、全角は使えるが「Shift-JIS」レベルまでで
  「Unicode」系(「UTF-8」など)は使えない。
・半角の最大は8000バイト、全角の最大は4000文字
  #「1文字=2バイト」の関係であれば同じということ
    Unicode系の「1文字=3バイト」だと全角の方が「12000バイト」となり
    有利だが、そもそも半角の方はUnicodeをサポートしていない

なお、文字数が大量になった場合は、以下の特殊な型を使うことになる
  ・「varchar(max)」型   (長文半角)  …旧「text」型
  ・「nvarchar(max)」型  (長文全角)  …旧「ntext」型
分類:MSSQL
MSSQL/インスタンスの削除
2015年01月03日
インスタンス(「\SQLEXPRESS」とかのパス)を削除するには
Windows「コントロールパネル」の「プログラムと機能」で
右クリックメニュー「アンインストールと変更」を選択し、
「追加」・「修復」・「削除」の中から「削除」を選び、
その先で特定のインスタンスを選択して削除処理を進めればよい。
分類:MSSQL
MSSQL/キーを集約
2015年01月02日
キーに「-xxx」的な枝番がついていて、これらを横断して枝番なしの集約キーで
合計を取りたい場合。

まず、文字列操作で集約キーを求めるには以下のような感じになる。
┌──────────────────────────────────────┐
│SELECT CASE                                                                 │
│         WHEN CHARINDEX('-', [キー]) > 0 THEN                               │
│           SUBSTRING([キー], 0, CHARINDEX('-', [キー]))                     │
│         ELSE                                                               │
│           [キー]                                                           │
│       END AS [集約キー]                                                    │
│    FROM [表]                                                               │
└──────────────────────────────────────┘
「CHARINDEX('-', [キー])」で「-」の位置を求める。
なければ「0」なので、別途、キーをそのままとする。
あったら、そこまでを「SUBSTRING([キー], 0, ~)」で抽出する。
(Excel関数の「mid()」みたいなもんだ)

ということで、こいつらをSELECT、GROUP BY、ORDER BYに展開するとできあがり。
┌──────────────────────────────────────┐
│SELECT CASE                                                                 │
│         WHEN CHARINDEX('-', [キー]) > 0 THEN                               │
│           SUBSTRING([キー], 0, CHARINDEX('-', [キー]))                     │
│         ELSE                                                               │
│           [キー]                                                           │
│       END AS [集約キー],                                                   │
│       SUM([値]) AS [合計]                                                  │
│    FROM [表]                                                               │
│    GROUP BY CASE                                                           │
│               WHEN CHARINDEX('-', [キー]) > 0 THEN                         │
│                 SUBSTRING([キー], 0, CHARINDEX('-', [キー]))               │
│               ELSE                                                         │
│                 [キー]                                                     │
│             END                                                            │
│    ORDER BY CASE                                                           │
│               WHEN CHARINDEX('-', [キー]) > 0 THEN                         │
│                 SUBSTRING([キー], 0, CHARINDEX('-', [キー]))               │
│               ELSE                                                         │
│                 [キー]                                                     │
│             END ASC                                                        │
└──────────────────────────────────────┘
分類:MSSQL
MSSQL/文字列照合(続)
2014年12月29日
照合順序の確認と設定について。

(全体の)既定の照合順序を確認する。
┌──────────────────────────────────────┐
│SELECT SERVERPROPERTY('COLLATION')                                          │
└──────────────────────────────────────┘

特定のDBについて、既定の照合順序を確認する。
┌──────────────────────────────────────┐
│SELECT DATABASEPROPERTYEX(DB名, 'COLLATION')                                │
└──────────────────────────────────────┘

照合順序(JAPANESE_CS_AS_KS_WS)を特定のDBに対して設定する。
┌──────────────────────────────────────┐
│ALTER DATABASE DB名 COLLATE JAPANESE_CS_AS_KS_WS;                           │
└──────────────────────────────────────┘
分類:MSSQL
MSSQL/連番をふる
2014年12月27日
ある列([順番])を基準として並び替えた場合に、連番を1から振り直すUPDATE文。
しかも、特定のグループごと([組No])に振るという条件も加わった場合。

以下の様な感じになる。
┌──────────────────────────────────────┐
│UPDATE [表]                                                                 │
│    SET [連番] = (                                                          │
│        SELECT [連番]                                                       │
│            FROM (                                                          │
│                SELECT [組No],                                              │
│                       [順番],                                              │
│                       ROW_NUMBER() OVER(PARTITION BY [組No]                │
│                                         ORDER BY [順番] ASC) AS [連番]     │
│                    FROM [表]                                               │
│            ) AS [入力D]                                                   │
│            WHERE [入力D].[組No] = [表].[組No]                             │
│              AND [入力D].[順番] = [表].[順番]                             │
│    );                                                                      │
└──────────────────────────────────────┘

これを一歩すすめて早めに抽出を行うと以下のような感じになる。
┌──────────────────────────────────────┐
│UPDATE [表]                                                                 │
│    SET [連番] = (                                                          │
│        SELECT [連番]                                                       │
│            FROM (                                                          │
│                SELECT [入力D].[順番],                                     │
│                       ROW_NUMBER() OVER(ORDER BY [入力D].[順番] ASC)      │
│                                                                   AS [連番]│
│                    FROM [表] AS [入力D]                                   │
│                    WHERE [入力D].[組No] = [表].[組No]                     │
│            ) AS [入力D]                                                   │
│            WHERE [入力D].[順番] = [表].[順番]                             │
│    );                                                                      │
└──────────────────────────────────────┘
分類:MSSQL
MSSQL/トランザクションのネスト
2014年12月22日
トランザクションをネストして、ロールバックとかしてしまうと
ネスト関係なく全てロールバックしてしまうので注意。
┌───────────────┐
│BEGIN TRY                     │
│    BEGIN TRANSACTION         │
│      ┌─────────────┐
│      │BEGIN TRY                 │
│      │    BEGIN TRANSACTION     │
│      │    COMMIT TRANSACTION    │
│      │END TRY                   │
│      │BEGIN CATCH               │
│      │    ROLLBACK TRANSACTION  ──┐全てをロールバックしてしまう
│      │    RETURN ERROR_NUMBER() │  │
│      │END CATCH                 │  │
│      │RETURN (0);               │  │
│      └─────────────┘  │
│    COMMIT TRANSACTION        │      │
│END TRY                       │      │
│BEGIN CATCH                   │      │
│    ROLLBACK TRANSACTION      ←───┘二重ロールバック扱いでエラーとなる
│    RETURN ERROR_NUMBER()     │
│END CATCH                     │
│RETURN (0);                   │
└───────────────┘
ネストは基本使わない方が賢明のようだ。
もしくはセーブポイント(SAVE TRANSACTION)を使うとか。
分類:MSSQL
MSSQL/代入で該当なし例外対策
2014年12月18日
例えば、ストアドプロシージャにて、以下のような代入文とした場合…。
┌──────────────────────────────────────┐
│DECLARE @変数  int                                                          │
├──────────────────────────────────────┤
│SELECT @変数 = [列]                                                         │
│    FROM [表]                                                               │
│    WHERE [抽出条件列] = 値;                                                │
└──────────────────────────────────────┘
WHERE条件で該当がないと、例外が発生してしまう。

LEFT JOINみたいに、該当なしは「NULL」になってくれるとありがたい場合、

ということで、以下のようなダミー表にLEFT JOINしてあげる。
┌──────────────────────────────────────┐
│DECLARE @変数  int                                                          │
├──────────────────────────────────────┤
│SELECT @変数 = [表].[列]                                                    │
│    FROM (SELECT 1 AS [ダミー列]) AS [ダミー表]                             │
│        LEFT JOIN (                                                         │
│            SELECT [列]                                                     │
│                FROM [表]                                                   │
│                WHERE [抽出条件列] = 値                                     │
│        ) AS [表]                                                           │
│          ON 1 = 1                                                          │
└──────────────────────────────────────┘
ま、これで、実現できることは実現できるのだが、これではちょっと美しくない。

もっと、シンプルに書けるのは以下の通り。
┌──────────────────────────────────────┐
│DECLARE @変数  int                                                          │
├──────────────────────────────────────┤
│SELECT @変数 = (                                                            │
│    SELECT [列]                                                             │
│        FROM [表]                                                           │
│        WHERE [抽出条件列] = 値                                             │
│);                                                                          │
└──────────────────────────────────────┘
分類:MSSQL
MSSQL/マッチング・後編
2014年12月15日
MERGE文はあきらめて、地道にINSERT・UPDATE文でやっちまうのが手っ取り早い。

「変更→削除→追加」の順が妥当なようだ。

ということで、以下のような感じで。
┌──────────────────────────────────────┐
│-- 変更                                                                     │
│UPDATE [旧表]                                                               │
│    SET [列]       = [新表].[列],                                           │
│        [更新日時] = getdate()                                              │
│    FROM [旧表]                                                             │
│        INNER JOIN [新表]                                                   │
│          ON  [新表].[キー] =  [旧表].[キー]                                │
│          AND [新表].[列]   <> [旧表].[列]                                  │
│    WHERE [旧表].[削除済フラグ] = 0;                                        │
├──────────────────────────────────────┤
│-- 削除                                                                     │
│UPDATE [旧表]                                                               │
│    SET [削除済フラグ] = 1,                                                 │
│        [更新日時]     = getdate()                                          │
│    WHERE [旧表].[削除済フラグ] = 0                                         │
│      AND NOT EXISTS (                                                      │
│              SELECT *                                                      │
│                  FROM [新表]                                               │
│                  WHERE [新表].[キー]         = [旧表].[キー]               │
│                    AND [新表].[削除済フラグ] = 0                           │
│          );                                                                │
├──────────────────────────────────────┤
│-- 追加                                                                     │
│INSERT INTO [旧表] (                                                        │
│        [キー],                                                             │
│        [列],                                                               │
│        [更新日時]                                                          │
│    )                                                                       │
│    SELECT [新表].[キー],                                                   │
│           [新表].[列],                                                     │
│           getdate()                                                        │
│        FROM [新表]                                                         │
│        WHERE [新表].[削除済フラグ] = 0                                     │
│          AND NOT EXISTS (                                                  │
│                  SELECT *                                                  │
│                      FROM [旧表] AS [追加先]                               │
│                      WHERE [追加先].[キー]         = [新表].[キー]         │
│                        AND [追加先].[削除済フラグ] = 0                     │
│              );                                                            │
└──────────────────────────────────────┘
分類:MSSQL
MSSQL/マッチング・前編
2014年12月14日
旧表に新表を突合させ、旧表がなければ追加、旧表があれば更新、
逆に新表になければ削除という典型的なマッチング処理がある。

これはMERGE文で一発できる。
┌──────────────────────────────────────┐
│MERGE INTO [旧表]                                                           │
│    USING [新表]                                                            │
│      ON  [旧表].キー = [新表].[キー]                                       │
│    WHEN MATCHED THEN                                                       │
│        UPDATE SET [列] = [新表].[列]                                       │
│    WHEN NOT MATCHED BY TARGET THEN                                         │
│        INSERT (                                                            │
│                [キー],                                                     │
│                [列]                                                        │
│            ) VALUES (                                                      │
│                [新表].[キー],                                              │
│                [新表].[列]                                                 │
│            )                                                               │
│    WHEN NOT MATCHED BY SOURCE THEN                                         │
│        DELETE;                                                             │
└──────────────────────────────────────┘
しかし、これに以下の条件が付いた場合、途端に対応できなくなる
  ・削除は直接DELETEするのではなく、削除済フラグを1にすることで行う
  ・変更の場合、更新する列に差分がある時のみ行う
    #同時に更新日時を更新することを想定(差分がない場合は更新したくない)

せいぜい対応できるのは、新表側を抽出することぐらいのみ。
┌──────────────────────────────────────┐
│MERGE INTO [旧表]                                                           │
│    USING (SELECT * FROM [新表] WHERE [削除済フラグ] = 0) AS [新表]         │
│      ON  [旧表].キー = [新表].[キー]                                       │
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
└──────────────────────────────────────┘

まず、旧表側(更新先)を抽出することはできない。
┌──────────────────────────────────────┐
│MERGE INTO (SELECT * FROM [旧表] WHERE [削除済フラグ] = 0) AS [旧表]        │
│    USING [新表]                                                            │
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
└──────────────────────────────────────┘

IF文を挟むこともできない。
┌──────────────────────────────────────┐
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
│    WHEN MATCHED THEN                                                       │
│        IF [列] <> [新表].[列]                                              │
│            UPDATE SET [列] = [新表].[列]                                   │
└──────────────────────────────────────┘

MERGE文は本格的なマッチング処理ではなく、
ミラーリング的なところに用いるものなのだろう。

ということで、その解決策は後編へ続く。。。
分類:MSSQL
前へ 1 2 3 4 5 6 7 8 9 10 11 12 13 次へ