MW211 EXIT

devlog
MSSQL/ADODBで更新件数取得
2014年12月13日
ADODBで以下のような感じで、「.Execute」の第二引数で更新件数を取得できる。
┌──────────────────────────────────────┐
│Private データベース As New ADODB.Connection                                │
├──────────────────────────────────────┤
│データベース.Execute 更新SQL文, 更新件数                                    │
└──────────────────────────────────────┘
でも、トリガが設定されている場合、
トリガで作用したSQL文の結果が取得されてしまう。

これを抑止するのは、トリガの結果を戻さないようにする。
以下のような感じで冒頭で「SET NOCOUNT ON;」を実行して抑止すればよい。
┌──────────────────────────────────────┐
│CREATE TRIGGER [dbo].[トリガ] ON [DB].[dbo].[表]                            │
│    AFTER UPDATE                                                            │
│AS                                                                          │
│BEGIN                                                                       │
│    SET NOCOUNT ON;                                                         │
│    ~SQL文~                                                               │
│END;                                                                        │
└──────────────────────────────────────┘
もちろん、トリガの呼び元には抑止の影響がないので、
.Executeで実行したSQL文の更新件数が確実に取得できる。
分類:MSSQL
MSSQL/日付変換のストアドプロシージャ
2014年12月12日
日付変換関係のいろいろな処理を含んだストアドプロシージャは以下の通り。
┌──────────────────────────────────────┐
│CREATE PROCEDURE PROCEDURE_日付変換                                         │
│    @yyyymmdd char(8) = ''                                                  │
│AS                                                                          │
│BEGIN                                                                       │
│    DECLARE @return     int                                                 │
│    DECLARE @date       date                                                │
│    SET @return = 0                                                         │
│    IF @yyyymmdd = ''                                                       │
│        SET @yyyymmdd = CONVERT(NVARCHAR, GETDATE(), 112)                   │
│    BEGIN TRY                                                               │
│        SELECT @date = DATEFROMPARTS(substring(@yyyymmdd, 1, 4),            │
│                                     substring(@yyyymmdd, 5, 2),            │
│                                     substring(@yyyymmdd, 7, 2))            │
│    END TRY                                                                 │
│    BEGIN CATCH                                                             │
│        RETURN(-1)                                                          │
│    END CATCH                                                               │
│PRINT @date                                                                 │
│    RETURN(@return)                                                         │
│END;                                                                        │
└──────────────────────────────────────┘
分類:MSSQL
MSSQL/自動採番の取得
2014年12月08日
┌──────────────────────────────────────┐
│CREATE TABLE 表 (                                                           │
│    [キー]              [int] IDENTITY(1,1) NOT NULL,                       │
│    [列]                [int]               NULL,                           │
│    CONSTRAINT [主キー] PRIMARY KEY CLUSTERED (                             │
│        [キー]              ASC                                             │
│    )                                                                       │
│);                                                                          │
└──────────────────────────────────────┘
上記のような自動採番する表があって、
採番直後にその値を取得する方法には以下がある。
                                          ┌─────┬─────┬─────┐
                                          │セッション│ スコープ │ テーブル │
┌──┬─────────────────┼─────┼─────┼─────┤
│案1│SELECT MAX(キー) FROM 表;         │   全て   │   全て   │ 指定のみ │
├──┼─────────────────┼─────┼─────┼─────┤
│案2│SELECT IDENT_CURRENT('表');       │   全て   │   全て   │ 指定のみ │
├──┼─────────────────┼─────┼─────┼─────┤
│案3│SELECT @@IDENTITY;                │ 自身のみ │   全て   │   全て   │
├──┼─────────────────┼─────┼─────┼─────┤
│案4│SELECT SCOPE_IDENTITY();          │ 自身のみ │ 自身のみ │   全て   │
└──┴─────────────────┴─────┴─────┴─────┘
  セッションが「全て」のものは、同時に他から更新された場合、
  その影響を受けてしまう。
  スコープが「全て」の場合は、トリガなどにより連動した結果も反映されてしまう。
  よって、案4が一番安全なようだ。
分類:MSSQL
MSSQL/数値項目を文字列に変換する
2014年12月07日
【案1】キャストする
┌──────────────────────────────────────┐
│CAST([数値項目] AS varchar)                                                 │
└──────────────────────────────────────┘
  一番オーソドックスなやり方か。

【案2】型を変更する
┌──────────────────────────────────────┐
│CONVERT(varchar, [数値項目])                                                │
└──────────────────────────────────────┘
  これもオーソドックスなやり方か。

【案3】文字列に変更する
┌──────────────────────────────────────┐
│LTRIM(STR([数値項目]))                                                      │
└──────────────────────────────────────┘
  STR()で変換するのだが、左側に余計なスペースも入ってしまうので
  LTRIM()でこれを除去する。
分類:MSSQL
MSSQL/ユーザ関数の引数省略の罠
2014年12月03日
┌──────────────────────────────────────┐
│CREATE FUNCTION [dbo].[ユーザ関数] (@引数1 int,                             │
│                                    @引数2 int = 1)                         │
│:                                                                          │
└──────────────────────────────────────┘
上記(引数2)のように、引数を省略して既定値を活かす指定をした場合
「ユーザ関数(1)」でOKかと思いきやエラーとなる。
「ユーザ関数(1,DEFAULT)」と「DEFAULT」を明記してあげなければならないらしい。
分類:MSSQL
MSSQL/BULK INSERTによるCSV取込
2014年12月02日
一発でできる。すごい。
┌──────────────────┬───────────────────┐
│BULK INSERT [DB].[dbo].[表]         │                                      │
│    FROM 'ファイルフルパス'         │                                      │
│    WITH                            │                                      │
│    (                               │                                      │
│        FIELDTERMINATOR   = ',',    │区切り文字                            │
│        ROWTERMINATOR     = '\r\n', │改行文字                              │
│        FIRSTROW          = 2,      │明細開始行(ヘッダ行の有無)            │
│        LASTROW           = 0,      │明細終了行(フッタ行の有無) 0は末尾まで│
│        CHECK_CONSTRAINTS,          │制約をチェックする                    │
│        FIRE_TRIGGERS               │トリガを起動させる                    │
│    );                              │                                      │
└──────────────────┴───────────────────┘
分類:MSSQL
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
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
前へ 1 2 3 4 5 6 7 8 9 10 11 12 13 次へ