メモ:T-SQL 単一列の結果表をシンプルな JsonArray にしたい

create table [データ] (
  [Id] bigint not null identity(1, 1) primary key
  , [Name] nvarchar(20) not null
)
go
insert into [データ] ([Name]) values 
(N'あいうえお')
, (N'かきくけこ')

から

["あいうえお", "かきくけこ"]

にしたい場合のクエリ。

参考 SQL to JSON - array of objects to array of values in SQL 2016 - Stack Overflow

単純に for json だとダメ。

select [Name] from [データ] for json path
[{"Name":"あいうえお"},{"Name":"かきくけこ"}]

結果セットの行が配列の要素(object)になってしまう。
ojbect じゃなくて良ーんだよってことで、色々やります。

まず、'"' で囲って、 区切りの','付けて for xml で1行にまとめてしまう。

select concat(',', '"', [Name], '"') from [データ] for xml path('')
,"あいうえお","かきくけこ"

で、STUFF (Transact-SQL) - SQL Server | Microsoft Docs で 先頭の ',' を取る。

select stuff(
  (select concat(',', '"', [Name], '"') from [データ] for xml path(''))
  , 1, 1, '')
"あいうえお","かきくけこ"

後は、前後に '['、']' 付けたらOK!

select concat('[', stuff(
  (select concat(',', '"', [Name], '"') from [データ] for xml path(''))
  , 1, 1, ''), ']')
["あいうえお","かきくけこ"]

SQL Server 標準の JSON 機能使ってない?
では、正しい JSON かどうかだけチェックしときます。
JSON_QUERY (Transact-SQL) - SQL Server | Microsoft Docs

select json_query((select concat('[', stuff(
  (select concat(',', '"', [Name], '"') from [データ] for xml path(''))
  , 1, 1, ''), ']')))
["あいうえお","かきくけこ"]

JSON 機能素晴らしい?!

メモ:T-SQL OUTPUT 句使ったときに INTO 付けてないと TRIGGER あったら怒られる

OUTPUT 句 (Transact-SQL) - SQL Server | Microsoft Docs

トリガー 使ってたら怒られたのでドキュメントのメモ。

INTO キーワードを指定せずに OUTPUT 句を指定すると、DML 操作を行った先では、その DML アクションに対して定義されたトリガーを有効化できません。 たとえば、UPDATE ステートメント内で OUTPUT 句が定義されていると、対象のテーブルで UPDATE トリガーを有効化できません。

ほかにも注意点は、トリガーが実行される前のデータを返すって。

OUTPUT から返される列は、INSERT ステートメント、UPDATE ステートメント、または DELETE ステートメントが完了した後、トリガーが実行される前のデータを反映します。

今回はトリガーで自身のテーブル更新しないんで関係ないけど。
てか、トリガー実行前なら、INTO 無しでも返してくれてもいーのに。

コード例:面倒なので GitHub - DapperLib/Dapper: Dapper - a simple object mapper for .Net を使う前提で書いてます。

using var conn = new SqlConnection("~");
var id = await conn.ExecuteScalarAsync(
  "insert into [Table1] (~) output [inserted].[Id] values (~)"
  , new {~});

これがエラーになるので、こんな感じに書き換え。

using var conn = new SqlConnection("~");
var id = await conn.ExecuteScalarAsync(
  @"declare @t table (Id bigint not null);
insert into [Table1] (~) output [inserted].[Id] into @t values (~);
select * from @t;"
  , new {~});

テーブルの定義は OUTPUT で返す列を定義してください。
若干面倒だけど多分これが一番マシ。*1

トリガーで自身を更新してかつ timestamp あると大変だねーって投稿:
sql - Cannot use UPDATE with OUTPUT clause when a trigger is on the table - Stack Overflow

そもそも timestamp 関係なくトリガーで自身を更新するなら OUTPUT は使わんほうが良さげ。

*1:複文サポートされててよかったね

メモ:PowerShell 7 (Core) で bacpac を import する

NuGet Gallery | Microsoft.SqlServer.DACFx 150.4897.1

NuGet Gallery | Microsoft.Data.SqlClient 2.0.1
が必要。

で、PowerShell 7 で Microsoft.Data.SqlClient を使うには、ちょい注意が。
PowerShell (7.0.2) で Microsoft.Data.SqlClient 2.0 を使用する at SE の雑記
を参考に。

2020/11/16 追記
出なさそう。
違うアセンブリ参照してたみたい。
ちなみに PowerShell 7.0.3 では netcoreapp3.1 の dll を使うと

~ is not supported on this platform.

が出るので注意!

Azure Pipelines の Windows Agent で SQL Server 2019 Local DB を使う

前にこんなの書いてたんですが、Pipelines に代わってから使うの初ということで試してました。
VSTS の ビルドで SQL Server LocalDB を使ってテストしたい - お だ のスペース

んで、今の最新の Windows Agent でバージョン調べてみると…


変わらず 2016SP1 相当。。

前は 2016 でも良かったんですが、今回は 2019 が必要なのでちょい調べてみました。

ここから、Microsoft-hosted agents for Azure Pipelines - Azure Pipelines | Microsoft Docs、こっちに飛んで virtual-environments/Windows2019-Readme.md at main · actions/virtual-environments · GitHub
中身見ると SQL Server インストールされてないみたいです。
Visual Studio 2019 Ent 付属の Local DB なんですかね。

若干諦めてたら、教えてもらいましたー。

Restore SQL Server Express 2019 · Issue #1282 · actions/virtual-environments · GitHub より引用

- task: PowerShell@2
  displayName: Install SQL 2019 Localdb
  inputs:
    targetType: 'inline'
    script: |
      Write-Host "Downloading"
      Import-Module BitsTransfer
      Start-BitsTransfer -Source https://download.microsoft.com/download/7/c/1/7c14e92e-bdcb-4f89-b7cf-93543e7112d1/SqlLocalDB.msi -Destination SqlLocalDB.msi
      Write-Host "Installing"
      Start-Process -FilePath "SqlLocalDB.msi" -Wait -ArgumentList "/qn", "/norestart", "/l*v SqlLocalDBInstall.log", "IACCEPTSQLLOCALDBLICENSETERMS=YES";
      Write-Host "Checking"
      sqlcmd -l 60 -S "(localdb)\MSSQLLocalDB" -Q "SELECT @@VERSION;"

これで 無事 Local DB のバージョンが 2019 になりました。
ダウンロード先が変わらない限りはこれで何とかなりそうですね。

追記 2020/11/13

メモ:Swashbuckle Swagger hide property

How to hide property from displaying in Swagger? · Issue #1230 · domaindrivendev/Swashbuckle.WebApi · GitHub

Query String は、[BindNever] 、他は、[JsonIgnore] でOK。

リクエストのパラメータで、getter しかなくて readonly なのに、readonly として認識してくれない場合は ↓で。
Ignore read only/private setter properties for a POST/PATCH · Issue #138 · domaindrivendev/Swashbuckle.WebApi · GitHub
※readonly なら、UI で実行する時にパラメータに表示されない。

メモ:Dot-Sourcing PowerShell

スクリプト モジュール - PowerShell | Microsoft Docs

Dot-Sourcing って単語がなかなか思い出せないのでメモ。
同じスコープ でそのまま実行する感じ。

$a = "aaa"

# hoge.ps1 で $a = "bbb" と書いてると…
. ./hoge.ps1

# bbb って出る
Write-Host $a

別スコープ(child) で実行するのは、 & Call operator
about_Operators - PowerShell | Microsoft Docs

$a = "aaa"

# hoge.ps1 で $a = "bbb" と書いてても…
&./hoge.ps1

# aaa って出る (child scope で書き換えても変わらない)
Write-Host $a

Dot-Sourcing のスコープについては、
about_scopes - PowerShell | Microsoft Docs