MW211 EXIT

devlog
MSSQL/ORDER BYの別列名
2015年04月04日
ORDER BYには別列名(AS列名)を指定できる。

以下の場合、「[表].[列2]」で並び替えが行われる。
┌──────────────────────────────────────┐
│SELECT [列1] AS [列2],                                                      │
│       [列2] AS [列1]                                                       │
│    FROM [表]                                                               │
│    ORDER BY [列1] ASC;                                                     │
└──────────────────────────────────────┘

表を直接してすれば、別列名ではなくそれで並び替えが行われる。
┌──────────────────────────────────────┐
│SELECT [列1] AS [列2],                                                      │
│       [列2] AS [列1]                                                       │
│    FROM [表]                                                               │
│    ORDER BY [表].[列1] ASC;                                                │
└──────────────────────────────────────┘
上記の場合は、「[表].[列1]」で並び替えが行われる。

基本的な以下(「[表].[列1]」で並び替えが行われる)と混同しないように注意したい。
┌──────────────────────────────────────┐
│SELECT [列1],                                                               │
│       [列2]                                                                │
│    FROM [表]                                                               │
│    ORDER BY [列1] ASC;                                                     │
└──────────────────────────────────────┘
いろいろ編集しているとやらかしそうなところだ。
分類:MSSQL
MSSQL/INSERT FROM SELECTの排他
2015年03月29日
「INSERT FROM SELECT」中は、更新側および参照側の排他状態は
どのようになっているのか?
確かめてみた。

  (1) 非トランザクション下での挙動
    (1-1) 実行中時
            更新側:排他ロック
            参照側:共有ロック

  (2) トランザクション下での挙動
    (2-1) 実行中時
            更新側:排他ロック
            参照側:共有ロック
    (2-2) 実行後コミット前
            更新側:排他ロック
            参照側:ロックなし

参照側は読込の為、共有ロックがかかるが
それはトランザクションの有無に関わらず実行中の間のみ。

気になっていたのが、トランザクション完了待ちで
更新側が排他ロックから抜け出せなかった場合(2-2)
参照側はどうなるのかという点。
こちらは、用が済んだので共有ロックは解除されるのだ。
分類:MSSQL
MSSQL/利用状況モニターのプロセス
2015年03月28日
利用状況モニターのプロセスを出力するSQL文。
┌──────────────────────────────────────┐
│SELECT s.[session_id]                        AS [セッションID],             │
│       CONVERT(char(1), s.[is_user_process]) AS [ユーザープロセス],         │
│       s.[login_name]                        AS [ログイン],                 │
│       CASE                                                                 │
│         WHEN p.[dbid] = 0 THEN N''                                         │
│         ELSE                   ISNULL(DB_NAME(p.[dbid]), N'')              │
│       END AS [データベース],                                               │
│       ISNULL(t.[task_state], N'')           AS [タスクの状態],             │
│       ISNULL(r.[command], N'')              AS [コマンド],                 │
│       ISNULL(s.[program_name], N'')         AS [アプリケーション],         │
│       ISNULL(w.[wait_duration_ms], 0)       AS [待機時間(ミリ秒)],         │
│       ISNULL(w.[wait_type], N'')            AS [待機の種類],               │
│       ISNULL(w.[resource_description], N'') AS [待機リソース],             │
│       ISNULL(CONVERT(varchar, w.[blocking_session_id]), '')                │
│           AS [ブロック元],                                                 │
│       CASE                                                                 │
│         WHEN r2.[session_id] IS NOT NULL                                   │
│          AND (r.[blocking_session_id] = 0 OR r.[session_id] IS NULL) THEN  │
│           '1'                                                              │
│         ELSE                                                               │
│           ''                                                               │
│       END AS [先頭ブロック],                                               │
│       s.[cpu_time]                          AS [Total CPU(ms)] ,           │
│       (s.[reads] + s.[writes]) * 8 / 1024   AS [Total Physical I/O(MB)],   │
│       s.[memory_usage] * (8192 / 1024)      AS [メモリ使用量(KB)],         │
│       ISNULL(r.[open_transaction_count], 0) AS [Open Transactions],        │
│       s.[login_time]                        AS [Login Time],               │
│       s.[last_request_start_time]           AS [Last Request Start Time],  │
│       ISNULL(s.[host_name], N'')            AS [ホスト名],                 │
│       ISNULL(c.[client_net_address], N'')   AS [Net Address],              │
│       ISNULL(t.[exec_context_id], 0)        AS [Execution Context ID],     │
│       ISNULL(r.[request_id], 0)             AS [Request ID],               │
│       ISNULL(g.[name], N'')                 AS [Workload Group]            │
│    FROM [sys].[dm_exec_sessions] AS s                                      │
│        LEFT JOIN [sys].[dm_exec_connections] AS c                          │
│          ON s.[session_id] = c.[session_id]                                │
│        LEFT JOIN [sys].[dm_exec_requests] AS r                             │
│          ON s.[session_id] = r.[session_id]                                │
│        LEFT JOIN [sys].[dm_os_tasks] AS t                                  │
│          ON  r.[session_id] = t.[session_id]                               │
│          AND r.[request_id] = t.[request_id]                               │
│        LEFT JOIN (                                                         │
│            SELECT *,                                                       │
│                   ROW_NUMBER() OVER (PARTITION BY [waiting_task_address]   │
│                                      ORDER BY [wait_duration_ms] DESC      │
│                   ) AS [row_num]                                           │
│                FROM [sys].[dm_os_waiting_tasks]                            │
│        ) AS w                                                              │
│          ON  t.[task_address] = w.[waiting_task_address]                   │
│          AND w.[row_num]      = 1                                          │
│       LEFT JOIN [sys].[dm_exec_requests] AS r2                             │
│         ON s.[session_id] = r2.[blocking_session_id]                       │
│       LEFT JOIN [sys].[dm_resource_governor_workload_groups] AS g          │
│         ON g.[group_id] = s.[group_id]                                     │
│       LEFT JOIN [sys].[sysprocesses] AS p                                  │
│         ON s.[session_id] = p.[spid]                                       │
│    WHERE s.[is_user_process] = 1                                           │
│    ORDER BY s.[session_id];                                                │
└──────────────────────────────────────┘
分類:MSSQL
MSSQL/非クラスタ化インデックスと付加列インデックス
2015年03月27日
┌──────────────────────────────────────┐
│CREATE NONCLUSTERED INDEX [非クラスタ化インデックス] ON [DB].[dbo].[表] (   │
│    [列]                                                                    │
│) INCLUDE (                                                                 │
│    [付加列]                                                                │
│);                                                                          │
└──────────────────────────────────────┘
【非クラスタ化インデックス】
  ・「CREATE NONCLUSTERED INDEX」で生成
  ・主キー(クラスタ化インデックス)や一意キー(後述)とは逆に、
    一意性よりもヒット率が高い列を指定すると効果あり
    #なお、これとは別に「CREATE UNIQUE NONCLUSTERED INDEX」で
      一意キーとしても使える
【付加列インデックス】
  ・「INCLUDE()」で生成
  ・通常のキー(検索キー)とは違い、
    本体(テーブル)に参照しにいくのがめんどくさい列を付加するためのもの
    #カバリングインデックスの改良版

…という解釈でいいの?
(非クラスタ化インデックスが一意性よりもヒット率重視ってとこが特に)
分類:MSSQL
MSSQL/数値の文字列変換
2015年03月26日
数値を文字列に変換するには、以下の方法が考えられる。
┌──────────────────────────────────────┐
│(A-1) FORMAT(数値, '0')                                                     │
│(A-2) LTRIM(STR(数値)))                                                     │
├──────────────────────────────────────┤
│(B-1) CONVERT(varchar, 数値)                                                │
│(B-2) CAST(数値 AS varchar)                                                 │
└──────────────────────────────────────┘

但し、B系だと、推定実行プランにて以下の警告が発生するのだが。
┌──────────────────────────────────────┐
│式 (CONVERT(varchar(30),数値,0)) の型変換は、                               │
│クエリプランの選択の"CardinalityEstimate"に影響する可能性があります。       │
└──────────────────────────────────────┘

どれが最適なのだろうか?
分類:MSSQL
MSSQL/DBが知らぬ間に復旧中になっている
2015年03月24日
MSSQLのエラーログ(ERRLOG)に以下のようなメッセージが頻出している場合がある
「Starting up database '■■■■DB'.」
この時、DBは復旧中状態になる。

これは、「自動終了(AUTO_CLOSE)」設定が「ON(TRUE)」になっていると発生する。

「自動終了(AUTO_CLOSE)」とは、DB毎に設定するもので、
そのDBが誰からもアクセスされなくなった時点で自動的に終了(CLOSE)する機能。
これにより、メモリをこまめに解放する。

そして、再度、誰かがアクセスすると、再び起動(Starting up)する訳だ。

設定の変更は、以下の様に「ALTER DATABASE」文で行う。(以下はOFFにする例)
「ALTER DATABASE [■■■■DB] SET AUTO_CLOSE OFF;」
分類:MSSQL
MSSQL/エラーメッセージ(マルチパート識別子)
2015年03月23日
「マルチパート識別子をバインドできない」とは…

表を複数結合した場合に、列名が重複していて、上位表が明確でない場合

「SELECT 表1.列 FROM 表1,表2;」と書かなければならないところを
「SELECT     列 FROM 表1,表2;」と書いちゃった場合とか。

→「表2.列」があると、後者では区別がつかない
  もちろん「表2.列」がなければ問題にはならない。
分類:MSSQL
MSSQL/エラー
2015年03月22日
┌──────────────────────────────────────┐
│BEGIN TRY                                                                   │
│    SELECT 1/0;  --エラー発生                                               │
│END TRY                                                                     │
│BEGIN CATCH                                                                 │
│    SELECT                                                                  │
│        ERROR_NUMBER()    AS [エラー番号],                                  │
│        ERROR_SEVERITY()  AS [重大度],                                      │
│        ERROR_STATE()     AS [エラー状態],                                  │
│        ERROR_PROCEDURE() AS [ストアドプロシージャ名],                      │
│        ERROR_LINE()      AS [行],                                          │
│        ERROR_MESSAGE()   AS [本文];                                        │
│END CATCH;                                                                  │
│GO                                                                          │
└──────────────────────────────────────┘
上記のような感じで、エラー番号を取得できるわけだが、
その対応表を取得するには、以下のような感じでSELECT文を実行すればよい。
┌──────────────────────────────────────┐
│SELECT message_id AS [エラー番号],                                          │
│       text       AS [本文],                                                │
│       severity   AS [重大度],                                              │
│       CASE                                                                 │
│          WHEN is_event_logged = 1 THEN 'イベントログ記録'                  │
│          ELSE                          ''                                  │
│       END AS [備考]                                                        │
│    FROM sys.messages                                                       │
│    WHERE language_id = 1041  -- 日本語                                     │
│    ORDER BY message_id ASC;                                                │
└──────────────────────────────────────┘
分類:MSSQL
MSSQL/長文のデータ型
2015年03月16日
Q.データ型で「nvarchar(4000)」と「nvarchar(max)」の違いは?

A.いずれも長い文字列を格納する項目の場合に使用する型です
    「nvarchar()」に指定できる最大文字数は4000文字なので
    その指定での最大が「nvarchar(4000)」となります
    「nvarchar(max)」はさらに大きく2GB分になります
    但し、これについてはインデックス項目に含めない方がよいようです
分類:MSSQL
MSSQL/UNIONのCAST誤認
2015年03月15日
ものすごく話を単純化して説明すると、以下の様なSQL文を実行した場合…
┌──────────────────────────────────────┐
│SELECT NULL                                                                 │
│UNION ALL                                                                   │
│SELECT 'a'                                                                  │
└──────────────────────────────────────┘
以下のようなエラーが発生することがある。
┌──────────────────────────────────────┐
│nvarchar の値 'a' をデータ型 int に変換できませんでした。                   │
└──────────────────────────────────────┘
NULLをint型と誤認して、文字型(nvarchar型)と不整合となったようだ。

但し、これは上記をそのまま実行しても発生しない。
VIEWを介した時に発生するようだ。

とにかくこれを回避するには、以下のようにNULLをCASTすればいいようだ。
┌──────────────────────────────────────┐
│SELECT CAST(NULL AS nvarchar)                                               │
│UNION ALL                                                                   │
│SELECT 'a'                                                                  │
└──────────────────────────────────────┘
分類:MSSQL
前へ 1 2 3 4 5 6 7 8 9 10 11 12 13 次へ