Microsoft MVP アワード (Data Platform) を受賞させていただきました

今回で7回目(8年目)の受賞になりました。
今後もより一層のコミュニティ活動/情報発信していきますので、SqlWorld :: ホーム 共々宜しくお願いします。
どんどん新しい製品、サービスが出てますがおいてかれないように頑張りま~。

SSMS 18.1 Diagram なんか不安定ってか作ったファイルが開けず SSMS が落ちる。。

SSMS 18.1 で Diagram が復活した - お だ のスペース で復活したって書いたけど、動き怪しい。。

18.1 の Diagram で作成したダイアグラムが何かの拍子に開けなくなった。
開くと SSMS が落ちて、イベントビューアーに以下のログが2つ。

障害が発生しているアプリケーション名: Ssms.exe、バージョン: 2019.150.18131.0、タイム スタンプ: 0x5cf90d8b
障害が発生しているモジュール名: DataDesigners.dll、バージョン: 2019.150.18131.0、タイム スタンプ: 0x5cf90d9f
例外コード: 0xc0000005
障害オフセット: 0x00004bce
障害が発生しているプロセス ID: 0x2ba8
障害が発生しているアプリケーションの開始時刻: 0x01d527c6577363fb
障害が発生しているアプリケーション パス: C:\Program Files (x86)\Microsoft SQL Server Management Studio 18\Common7\IDE\Ssms.exe
障害が発生しているモジュール パス: C:\Program Files (x86)\Microsoft SQL Server Management Studio 18\Common7\IDE\Tools\VDT\DataDesigners.dll
レポート ID: 4636e7cd-14e3-4e46-8426-19349d2129d1
障害が発生しているパッケージの完全な名前: 
障害が発生しているパッケージに関連するアプリケーション ID: 
アプリケーション:Ssms.exe
フレームワークのバージョン:v4.0.30319
説明: ハンドルされない例外のため、プロセスが中止されました。
例外情報:System.AccessViolationException
   場所 Microsoft.VisualStudio.OLE.Interop.IOleCommandTarget.Exec(System.Guid ByRef, UInt32, UInt32, IntPtr, IntPtr)
   場所 Microsoft.VisualStudio.Platform.WindowManagement.DocumentObjectSite.Exec(System.Guid ByRef, UInt32, UInt32, IntPtr, IntPtr)
   場所 Microsoft.VisualStudio.Platform.WindowManagement.WindowFrame.Exec(System.Guid ByRef, UInt32, UInt32, IntPtr, IntPtr)
   場所 Microsoft.Internal.VisualStudio.Shell.Interop.IVsTrackSelectionExPrivate.Register()
   場所 Microsoft.VisualStudio.Platform.WindowManagement.WindowFrame.ConnectSelectionContext()
   場所 Microsoft.VisualStudio.Platform.WindowManagement.WindowFrame.Activate()
   場所 Microsoft.VisualStudio.Platform.WindowManagement.WindowManagerService.viewManager_ActiveViewChanged(System.Object, Microsoft.VisualStudio.PlatformUI.Shell.ActiveViewChangedEventArgs)
   場所 System.EventHandler`1[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].Invoke(System.Object, System.__Canon)
   場所 Microsoft.VisualStudio.PlatformUI.ExtensionMethods.RaiseEvent[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]](System.EventHandler`1<System.__Canon>, System.Object, System.__Canon)
   場所 Microsoft.VisualStudio.PlatformUI.Shell.ViewManager.SetActiveView(Microsoft.VisualStudio.PlatformUI.Shell.View, Microsoft.VisualStudio.PlatformUI.Shell.ActivationType)
   場所 Microsoft.VisualStudio.Platform.WindowManagement.WindowFrame.ShowInternal(ShowFlags)
   場所 Microsoft.VisualStudio.Platform.WindowManagement.WindowFrame.<Show>b__505_0()
   場所 Microsoft.VisualStudio.ErrorHandler.CallWithCOMConvention(System.Func`1<Int32>, Boolean, Boolean)
   場所 Microsoft.VisualStudio.Platform.WindowManagement.WindowFrame.Show()
   場所 Microsoft.VisualStudio.Platform.WindowManagement.WindowFrame+MarshalingWindowFrame.<Microsoft.VisualStudio.Shell.Interop.IVsWindowFrame.Show>b__12_0()
   場所 Microsoft.VisualStudio.Shell.ThreadHelper.Invoke[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]](System.Func`1<Int32>)
   場所 Microsoft.VisualStudio.Platform.WindowManagement.WindowFrame+MarshalingWindowFrame.Microsoft.VisualStudio.Shell.Interop.IVsWindowFrame.Show()
   場所 Microsoft.SqlServer.Management.UI.VSIntegration.Editors.VirtualProject.CreateDesigner(Microsoft.SqlServer.Management.Sdk.Sfc.Urn, Microsoft.SqlServer.Management.UI.VSIntegration.Editors.DocumentType, Microsoft.SqlServer.Management.UI.VSIntegration.Editors.DocumentOptions, Microsoft.SqlServer.Management.UI.VSIntegration.ObjectExplorer.IManagedConnection, System.String)
   場所 Microsoft.SqlServer.Management.UI.VSIntegration.Editors.VirtualProject.Microsoft.SqlServer.Management.UI.VSIntegration.Editors.ISqlVirtualProject.CreateDesigner(Microsoft.SqlServer.Management.Sdk.Sfc.Urn, Microsoft.SqlServer.Management.UI.VSIntegration.Editors.DocumentType, Microsoft.SqlServer.Management.UI.VSIntegration.Editors.DocumentOptions, Microsoft.SqlServer.Management.UI.VSIntegration.ObjectExplorer.IManagedConnection, System.String)
   場所 Microsoft.SqlServer.Management.UI.VSIntegration.Editors.ISqlVirtualProject.CreateDesigner(Microsoft.SqlServer.Management.Sdk.Sfc.Urn, Microsoft.SqlServer.Management.UI.VSIntegration.Editors.DocumentType, Microsoft.SqlServer.Management.UI.VSIntegration.Editors.DocumentOptions, Microsoft.SqlServer.Management.UI.VSIntegration.ObjectExplorer.IManagedConnection, System.String)
   場所 Microsoft.SqlServer.Management.UI.VSIntegration.Editors.VsDocumentMenuItem.CreateDesignerWindow(Microsoft.SqlServer.Management.UI.VSIntegration.ObjectExplorer.IManagedConnection, Microsoft.SqlServer.Management.UI.VSIntegration.Editors.DocumentOptions)
   場所 Microsoft.SqlServer.Management.UI.VSIntegration.Editors.VsDocumentMenuItem.InvokeDesigner(Microsoft.SqlServer.Management.UI.VSIntegration.ObjectExplorer.IManagedConnection)
   場所 Microsoft.SqlServer.Management.UI.VSIntegration.Editors.VsDocumentMenuItem.Invoke()
   場所 Microsoft.SqlServer.Management.UI.VSIntegration.ObjectExplorer.ToolsMenuItemBase.MenuInvokedHandler(System.Object, System.EventArgs)
   場所 System.ComponentModel.Design.MenuCommand.Invoke()
   場所 Microsoft.SqlServer.Management.UI.VSIntegration.ObjectExplorer.DefaultMenuHandler.DoDefaultAction()
   場所 Microsoft.SqlServer.Management.UI.VSIntegration.ObjectExplorer.ExplorerHierarchyNode.DoDefaultAction()
   場所 Microsoft.SqlServer.Management.UI.VSIntegration.ObjectExplorer.LazyTreeView.WmLButtonDblClk(System.Windows.Forms.Message ByRef)
   場所 Microsoft.SqlServer.Management.UI.VSIntegration.ObjectExplorer.LazyTreeView.WndProc(System.Windows.Forms.Message ByRef)
   場所 System.Windows.Forms.Control+ControlNativeWindow.OnMessage(System.Windows.Forms.Message ByRef)
   場所 System.Windows.Forms.Control+ControlNativeWindow.WndProc(System.Windows.Forms.Message ByRef)
   場所 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr, Int32, IntPtr, IntPtr)

sysdiagrams の中みてもさっぱり。
開けるダイアログもあるので、再現方法がわからん。。

SSMS 18.1 で Diagram が復活した

SSMS 18 で Diagram が無くなった - お だ のスペース
で Diagram が無くなったって書いてましたが、18.1 で復活しました。

Download SQL Server Management Studio (SSMS) - SQL Server | Microsoft Docs
New in this Release (SSMS 18.1) より抜粋

Database diagrams - Database diagrams were added back into SSMS. For details, see Database Diagrams.
SSBDIAGNOSE.EXE - The SQL Server Diagnose command line tool was added back into the SSMS package.

別のツールに移行しちゃったけど、どうしようかな。。

SQL であるグループの中で最小のものを取得する (複数あっても1つにしたい)

質問されたので…

create table [取引開始履歴] (
  [取引先] nvarchar(20),
  [取引先営業所] nvarchar(20),
  [開始日] date not null
)

insert into [取引開始履歴] values
(N'Foo財閥', N'大阪', '2016-04-01'),
(N'Foo財閥', N'東京第一', '2016-04-01'),
(N'Foo財閥', N'東京第二', '2018-07-01'),
(N'Bar商社', N'北海道', '2017-10-01'),
(N'Bar商社', N'東京', '2018-12-01'),
(N'Baz会社', N'京都', '2016-09-01')

こんなデータがあったとして、
取引先の中で最初に取引を始めた営業所を取得したいというお題。
普通は 取引先毎の開始日が min の物でいいけど、min(開始日) が同じのあったらどうするの?
っていう質問。

rank 使って順位付けしましょうねーって感じです。
同じ時どっち取るかは好きな並び順指定してください。
※今回は取引先営業所の昇順にしてます。

select 
  [取引先]
  , [取引先営業所]
  , [開始日]
from (
  select 
    [取引先]
    , [取引先営業所]
    , [開始日]
    , rank() over (partition by [取引先] order by [開始日], [取引先営業所]) as [r]
  from
    [取引開始履歴]
) [data_]
where
  [r] = 1

f:id:odashinsuke:20190605054951j:plain
SQL Server で試してますが、Window 関数がサポートされてたらほぼ同じクエリでいけるんちゃうかなー。

SQL Server での更新ロックを使った排他制御

よくあるやつですが、諸々の事情で取り合えず書いときます。

めっちゃ簡略化したシナリオ
分離レベルはデフォルトの read committed

入庫と出庫 + 在庫を更新するケースで、
しかも update で現在値を計算するのではなく直接設定するケース。
※update 在庫 set 在庫数 = @計算後の値 where 商品Id = @商品Id みたいな update*1

1.お互いが関係無い商品なら

時系列 入庫 出庫
1 begin tran begin tran
2 在庫取得 在庫取得
3 入庫データ追加 出庫データ追加
4 在庫更新 在庫更新
5 commit commit

ちがう商品なのでロックの競合もなく、普通に正しく更新できる。

2.同じ商品なら

時系列 入庫 出庫
1 begin tran begin tran
2 在庫取得 (Sロック※すぐ外れる) 在庫取得 (Sロック同時OK + ※すぐ外れる)
3 入庫データ追加 出庫データ追加
4 在庫更新 (Xロック) 在庫更新 (Xロックは同時無理でロック待ち)
5 commit -
6 - 在庫更新 (入庫が終わったから処理出来る)
7 - commit

という流れになって、出庫での在庫更新が入庫の内容を反映せずに更新してしまう。。
※しつこく書くけど、update が 在庫数 = 在庫数 - @出庫数 なら問題ない!!

こういうのを防ぐには、検索時に更新ロック取ろうねって話しです。

3.同じ商品でも検索時に更新ロックを取ると…

時系列 入庫 出庫
1 begin tran begin tran
2 在庫取得 (Uロック) 在庫取得 (Uロックは同時無理でロック待ち)
3 入庫データ追加 -
4 在庫更新 (Xロック) -
5 commit -
6 - 在庫取得 (入庫が終わったからUロック取れる)
7 - 出庫データ追加
8 - 在庫更新 (Xロック)
9 - commit

これで競合せずに出来るよねー
ドキュメントはここらへんで
SQL Server トランザクションのロックおよび行のバージョン管理ガイド - SQL Server | Microsoft Docs

*1:在庫数 = 在庫数 - @出庫数 なら問題でない

SQL Server 2019 の _UTF8 照合順序は日本語ではサイズ増える?

SQL Server 2019 CTP3.0 時点の情報です

SQL Server 2019 の新機能 - SQL Server | Microsoft Docs
見てたら char/varchar でも UTF-8 がサポートされたよーってあったので見てみました。

照合順序と Unicode のサポート - SQL Server | Microsoft Docs
より抜粋

使用されている文字セットによっては、この機能によりストレージを大幅に節約できます。 たとえば、ASCII (ラテン) 文字列の既存の列データ型を、UTF-8 対応の照合順序を使用して NCHAR(10) から CHAR(10) に変更すると、必要なストレージが 50% 削減されます。 このように減るのは、NCHAR(10) を保存するには 20 バイト必要であるのに対し、CHAR(10) では同じ Unicode 文字列に 10 バイトしか必要ないためです。

日本語やとどうやろ?っていうので、
DATALENGTH (Transact-SQL) - SQL Server | Microsoft Docs
でちょっと試しました。

いつもの 森鷗外 です。

create table UTF8照合順序 (
  NonUTF8Char varchar(10) collate Japanese_XJIS_140_CI_AS,
  UTF8Char varchar(10) collate Japanese_XJIS_140_CI_AS_UTF8,
  NonUTF8NChar nvarchar(10) collate Japanese_XJIS_140_CI_AS,
  UTF8NChar nvarchar(10) collate Japanese_XJIS_140_CI_AS_UTF8
)

insert into UTF8照合順序 values
('あいう', 'あいう', 'あいう', 'あいう'),
(N'森鷗外', N'森鷗外', N'森鷗外', N'森鷗外')

select 
  NonUTF8Char, datalength(NonUTF8Char), 
  UTF8Char, datalength(UTF8Char), 
  NonUTF8NChar, datalength(NonUTF8NChar), 
  UTF8NChar, datalength(UTF8NChar)
from UTF8照合順序

f:id:odashinsuke:20190602095438j:plain
nvarchar は 2017 から何も変わらないはずで問題無し。
varchar で UTF8 指定していない場合は、当然文字化けでこれもOK。
varchar で
UTF8 指定してると、文字化けせずですが、バイト数が nvarchar より増えてる。

使いどころあるかな?

06/18(火) SQLWorld★大阪#50 開催します #sqlworld

令和最初の SqlWorld :: SQLWorld★大阪#50 開催します! 32回目の平日夜開催で、前回同様 ハンズオン 形式行う予定です。

【日時】
2019年06月18日(火曜日) 19:00~21:00
 

【イベント概要】
令和最初の SQLWorld、今回で32回目の平日夜開催~。今回も、みんなで SQL を書いてみようというハンズオン企画です!ブラウザがあれば参加出来るようにしていますので、iPad 等のタブレットでも大丈夫です。
 

【会場】
フェンリル株式会社さま大阪本社 http://www.fenrir-inc.com/
〒530-0011 大阪府大阪市北区大深町 3番1号 グランフロント大阪タワーB(オフィス)
 

【参加費】
無料
 

【持ち物】
パソコン/タブレット (DB のインストールは不要です。)
 

【参加可能人数】
13 人
 

お題に沿って、SQL を書いてみようという勉強会です。是非ご参加を~。

なんやかんやで SQLWorld も 50回目です。
開催回数は増えていっていますが、続き物というわけでは無いので初めて参加される方でもお気軽にどぞー。