09/10(火) SQLWorld★大阪#51 開催します #sqlworld

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

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

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

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

【参加費】
無料
 

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

【参加可能人数】
13 人
 

お題に沿って、SQL を書いてみようという勉強会です。是非ご参加を~。
開催回数は増えていっていますが、続き物というわけでは無いので初めて参加される方でもお気軽にどぞー。

LambdicSql で bit型(bool) をリテラルで指定する場合の対処法

LambdicSql でリテラルをパラメータ化したくない場合は DirectValue か N 使おう - お だ のスペース
で、DirectValue 使おうねーって書いたけど、bit型のカラム(.NET の型だと bool) は DirectValue をそのまま使うとエラーなクエリが吐かれます。

using LambdicSql;
using System;
using System.Data.SqlClient;
using static LambdicSql.SqlServer.Symbol;

public class table
{
  public int foo { get; set; }
  public int bar { get; set; }
  public bool IsValid { get; set; }
}
public class DB
{
  public table table { get; set; }
}

class Program
{

  static void Main(string[] args)
  {
    var query = Db<DB>.Sql(db => Select(new table
    {
      foo = db.table.foo,
      bar = db.table.bar
    }).
    From(db.table).
    Where(db.table.IsValid == true.DirectValue()));

    var qs = query.Build(typeof(SqlConnection)).Text;

    Console.WriteLine(qs);
/*
SELECT
   table.foo AS foo,
   table.bar AS bar
FROM table
WHERE table.IsValid = True
*/
  }
}

なクエリが吐かれてこのまま実行すると、

列名 'True' が無効です。

となってしまいます。
bit (Transact-SQL) - SQL Server | Microsoft Docs
bit 型の場合、0 (false) か 0以外 (true) という扱いなので、取り合えず 0 か 1 を渡したら良さげです。
※文字列 'TRUE'、'FALSE' でもクエリエラーにはなりませんが、前回も書いた暗黙の型変換(convert_implicit)が発生します。
では、table.IsValid == 1.DirectValue() と書きたいけどこうすると bool型 == int型 になってコンパイルエラーとなります。
なので、1.DirectValue() の結果を bool にキャストします。これも int型 を bool型にそのままキャスト出来ないのでobject型を経由します。

class Program
{

  static void Main(string[] args)
  {
    var query = Db<DB>.Sql(db => Select(new table
    {
      foo = db.table.foo,
      bar = db.table.bar
    }).
    From(db.table).
    Where(db.table.IsValid == (bool)(object)1.DirectValue()));

    var qs = query.Build(typeof(SqlConnection)).Text;

    Console.WriteLine(qs);
/*
SELECT
   table.foo AS foo,
   table.bar AS bar
FROM table
WHERE table.IsValid = 1
*/
  }
}

めんどくさー。

LambdicSql でリテラルをパラメータ化したくない場合は DirectValue か N 使おう

前回 LambdicSql ネタ書いたので、小ネタを何個か。

LambdicSql でリテラル値を使うと勝手にパラメータ化されます。
が、パラメータ化したくない時もあります。*1

using LambdicSql;
using System;
using System.Data.SqlClient;
using static LambdicSql.SqlServer.Symbol;

public class table
{
  public int foo { get; set; }
  public int bar { get; set; }
  public string 状態 { get; set; }
}
public class DB
{
  public table table { get; set; }
}

class Program
{

  static void Main(string[] args)
  {
    var query = Db<DB>.Sql(db => Select(new table
    {
      foo = db.table.foo,
      bar = db.table.bar
    }).
    From(db.table).
    Where(db.table.状態 == "有効"));

    var qs = query.Build(typeof(SqlConnection)).Text;

    Console.WriteLine(qs);
/*
SELECT
   table.foo AS foo,
   table.bar AS bar
FROM table
WHERE table.状態 = @p_0
*/
  }
}

[状態] の条件はリテラルで "有効" としているけど、@p_0 でパラメータ化されちゃう。
これを防ぐには DirectValue 使おうねー。

class Program
{

  static void Main(string[] args)
  {
    var query = Db<DB>.Sql(db => Select(new table
    {
      foo = db.table.foo,
      bar = db.table.bar
    }).
    From(db.table).
    Where(db.table.状態 == "有効".DirectValue()));

    var qs = query.Build(typeof(SqlConnection)).Text;

    Console.WriteLine(qs);
/*
SELECT
   table.foo AS foo,
   table.bar AS bar
FROM table
WHERE table.状態 = '有効'
*/
  }
}

はい、パラメータ化されなくなった。
でも、nvarchar、nchar だと、暗黙の型変換(convert_implicit)が起きてパフォーマンスに悪影響?
そんなときは、N 使おうねー。

class Program
{

  static void Main(string[] args)
  {
    var query = Db<DB>.Sql(db => Select(new table
    {
      foo = db.table.foo,
      bar = db.table.bar
    }).
    From(db.table).
    Where(db.table.状態 == N("有効")));

    var qs = query.Build(typeof(SqlConnection)).Text;

    Console.WriteLine(qs);
/*
SELECT
   table.foo AS foo,
   table.bar AS bar
FROM table
WHERE table.状態 = N'有効'
*/
  }
}

暗黙の型変換のドキュメント
Data type conversion (Database Engine) - SQL Server | Microsoft Docs
パフォーマンスに影響するよーの記事
DO’s&DONT’s #2: 絶対にやらなければいけないこと – データ型を一致させる – Microsoft SQL Server Japan Support Team Blog
SQL Server のチューニングについてまとめてみる - その6 - ( CONVERT_IMPLICIT、暗黙の型変換の怖さを知ろう ) - 都内で働くSEの技術的なひとりごと / Technical soliloquy of System Engineer working in Tokyo

*1:実行プラン変わる可能性あるし

LambdicSql で共通な select from を使った union

GitHub - Codeer-Software/LambdicSql
GitHub - Codeer-Software/LambdicSql.SqlServer

を使ったサンプル。

元ネタ

SELECT
  foo, 
  bar
FROM
  table
WHERE 
  foo = 1
  AND bar = 2
UNION ALL
SELECT
  foo, 
  bar
FROM
  table
WHERE
  foo = 3
  AND baz = 4

select - from は共通してて、union all する時の where を変更したいみたいな感じ。

install-package LambdicSql.SqlServer
install-package System.Data.SqlClient

して、

using LambdicSql;
using System;
using System.Data.SqlClient;
using static LambdicSql.SqlServer.Symbol;

public class table
{
  public int foo { get; set; }
  public int bar { get; set; }
}
public class DB
{
  public table table { get; set; }
}

class Program
{

  static void Main(string[] args)
  {
    var selectfrom = Db<DB>.Sql(db => Select(new table
    {
      foo = db.table.foo,
      bar = db.table.bar
    }).From(db.table));

    var query = selectfrom +
      Db<DB>.Sql(db => Where(db.table.foo == 1 && db.table.bar == 2)) +
      Db<DB>.Sql(_ => Union(All())) +
      selectfrom +
      Db<DB>.Sql(db => Where(db.table.foo == 3 && db.table.bar == 4));

    var qs = query.Build(typeof(SqlConnection)).Text;

    Console.WriteLine(qs);
/*
SELECT
  table.foo AS foo,
  table.bar AS bar
FROM table
WHERE table.foo = @p_0 AND table.bar = @p_1
UNION ALL
SELECT
  table.foo AS foo,
  table.bar AS bar
FROM table
WHERE table.foo = @p_2 AND table.bar = @p_3
*/
  }
}

x64 な OSで Any CPU(32bit優先) な アプリを Friendly + nunit3-console でテストする

何も気にせず動かしたら、こんなエラーが出た。

Codeer.Friendly.FriendlyOperationException : プラットフォームターゲットがテスト対象とテストプロセスで異なります。合わせてください。

アプリが x86 で、nunit3-console が x64 やでーって感じっぽい。

nunit3-console.exe に x86 で動かすオプションあるからそれ指定でOKー。
Console Command Line · nunit/docs Wiki · GitHub

nunit3-console.exe --x86 Hoge.dll

結構前やけど、多分同じ感じなんちゃうかなー?
Friendly×Nunit3×Consoleの注意点 - Qiita

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 の中みてもさっぱり。
開けるダイアログもあるので、再現方法がわからん。。