ブロッコリーを克服するまでプログラミング

プログラミングとか趣味とかを報告します。

SQLServer : XMLの値と属性を「replace value of」で改変する

いままでSQLServerXML操作については、SELECT + FOR XML PATHでXMLを作成したり、OPENXMLでSELECTしたりしかしてこなかった僕です。

 

まぁ必ずではなかったのですが、ストアド上でXMLの値とか属性とかを個別に操作したいという案件が発生。「SQLServer XML 操作」とか調べてみると、上述している案件ばかりでてくるので、DOM操作でやろうかなとあきらめてたところ、それっぽいドキュメントを発見。

 



docs.microsoft.com

 

何はともあれ、Management Studioで以下のSQLを試してみた。

XML型の@xmlを宣言して、2番目の<TEST>タグの値と属性を5に変更しました。

 

DECLARE @xml XML = '<ROOT><TEST attr="10">1</TEST><TEST attr="20">2</TEST></ROOT>'

SELECT @xml

SET @xml.modify('replace value of (/ROOT/TEST[2]/text())[1] with "5"')

SELECT @xml

SET @xml.modify('replace value of (/ROOT/TEST[2]/@attr)[1] with "5"')

SELECT @xml

 

結果が下図。値も属性も改変できることを確認できた。めでたしめでたし。

f:id:atwtama:20190227234622p:plain

 

自転車:GIANT REVOLT

現在3台の自転車を所有しているのですが、最近GIANT REVOLTばかり乗っているという記事です。

 

私は現在、以下3台の自転車を保有しております。

COLNAGO MASTER-X LIGHT

・GIANT REVOLT

・ママチャリ(ドンキの最安値レベル)

 

MASTER-XとREVOLTは室内保管していたので、近年では95%ママチャリしか使用していませんでした。ただ部屋から出すのが面倒くさいという理由で、ママチャリで数十キロの移動を行うこともザラにありました。しかし、正直2台自転車が室内にいるのは邪魔だということと、どうせ乗らないなら盗まれる覚悟で外に置いていたほうが使うしいいんじゃないか?と思い、再起動しました。

 

とりあえずREVOLTは前後パンクしていたので、タイヤのチューブだけアマゾンで買って交換しました。型式は2014年のREVOLT 1です。(だと思います)

www.giant.co.jp

 

正直、COLNAGOのほうはたまにつかっていたのですが、お尻もクッソいたいし、なんかウェアとか着ないとアレだし、車道怖いし(もう30歳になるので・・・。)、ビンディング履きたくないし、こういうにわかおじさんにはREVOLTみたいなチャリこそ向いているのでは、と思いました。そこで、今年の抱負として、我がREVOLT君を「最強のママチャリ」にしようと思います。

 

とりあえず以下は設置済みです。

・2年間保管したふわふわジェルのGIANTバーテープ

・型式不明SELLE ITALIAの、まるでママチャリサドルのような女性用?サドル

・古びたディスク用リアキャリアと日光によって変色したパニアバック

 

ちょっと使用した感じですが、最高です。リアが重いけどまぁまぁ早いしかっこいいし、荷物もよく入るママチャリみたいになりました。あと、タイヤが35Cなのでむちゃくちゃ安全です。サブブレーキもついてます。本当につよくてかっこいいママチャリです。あと、パニアバックつけてるとがんばって自転車こがなくても(自分の中では)OKなので、周りを気にせずゆくーりこげます。

 

今回REVOLTをママチャリ化しようとしてる件を記事にする気はなかったです。そもそも、ロードバイクをママチャリというとは何事だ!となりそうですし・・・。しかし、ネットで検索してもあまりREVOLT所持者がいない?ようだし、でもGIANTの2019ラインナップにはREVOLTがあったので、「REVOLTは何でもできるぞ!」というような何かしらのご助力になるかと思い、記事にしました。写真は後日あげます。(とおもいます)

 

SQLServer : FOR XML PATHについてあまり考えてこなかったかも

いままであまり深く考えていなかったけれども、SQLServerのFOR XML PATH句について、「タグは存在するけど、数値(文字列)がない」もしくは「タグ自体が存在しない」の2パターンについて考えてみた。

 

正直、いままでこれらの違いについて考えてたことなかった。しかしある時、いつも使用していたNULL判定について、挙動がおかしいことに気づいた。なので、それぞれについて以下のクエリで試してみた。

 

  -- テスト用XMLを定義。ARG1, ARG2タグには値を挿入し、ARG3は値無し、ARG4はタグ自体無しとした。

  DECLARE @xml XML =

  '<ROOT>

 <ARG1>1</ARG1>

 <ARG2>2</ARG2>

 <ARG3></ARG3>

  </ROOT>'

 

  DECLARE @xml_predoc INT
  EXEC sp_xml_preparedocument @xml_predoc OUTPUT, @xml

 

  -- ARG1, 2, 3, 4について同条件でSELECTする。

  SELECT
  ARG1 ,ARG2 ,ARG3, ARG4
  FROM OPENXML(@xml_predoc, '/ROOT', 2)
  WITH( ARG1 INT, ARG2 INT, ARG3 INT, ARG4 INT)
  FOR XML PATH('ROOT')

 

このクエリを実行すると、結果は以下となる。

<ROOT>

 <ARG1>1</ARG1>

 <ARG2>2</ARG2>

 <ARG3>0</ARG3>

</ROOT>

 

 つまり、

1, タグはあるけど値を記載していない = 整数型なら0 。文字列型なら空文字。

2, タグ自体ないものに対してSELECTする = NULL

 

本当にあまり考えてこなかったけれども、パターン1については0になると考えると、条件文など適当に書くとエラーが出そう。

 

もしかしたら基礎なのかもしれないけれども、備忘録として。

 

 

「天橋立」とか、「かやぶきの里」とか

GW初日、妻と二人レンタカーにて行ってきました。最高の快晴でした。

京都にきて早数年が経ちますが、「天橋立」というと、なぜか口をそろえて「きれいだけどまぁまぁ」みたいな回答が目立つイメージでした。なので妻には、「あまり期待せずに行こう」と話していました。

 

到着早々、とりあえずレンタサイクル(2時間 400円)しました。2時間で足りるのかな、と思っていましたが、天橋立を往復 + ちょっとおやつ + ちょっと遊ぶ でちょうど2時間ぐらいでした。お昼ごはんを途中でとった場合微妙ですが、通常経路だと全く問題ありません。

 

f:id:atwtama:20180429215830j:plain

 

私は自転車が趣味なのもあるかもしれませんが、快晴の天橋立を自転車で走行することは最高に楽しかったです。

 

f:id:atwtama:20180429220010j:plain

f:id:atwtama:20180429215451j:plain

 

天橋立は、全然、がっかりスポットではありませんでした。ただし、快晴であるとか、レンタサイクルで天橋立を渡るとか、そういう前提はあるのかなと思いました。

(曇っていたり、メンバーのだれかが「自転車乗りたくない」、というと、ちょっとがっかりしそうな気がしました。)

 

 

 

帰りに、「かやぶきの里」というところに行きました。案外、山道というほどの道でもなく、ストレスフリーでたどり着けました。天橋立がすごすぎて見劣りするかな、と思っていましたが、そんなこと、まるでなかったです。

京都美山 かやぶきの里北村

 

f:id:atwtama:20180429220536j:plain

f:id:atwtama:20180429220621j:plain

f:id:atwtama:20180429220715j:plain

 

GW初日に小旅行してしまったから、暇なう。

 

SQLServer : エラーが出ていないのにストアドプロシージャの処理が止まっている?

スレッド内でSQLServerのストアドプロシージャを SQLExecDirect / SQLExecute で実行するサービスプログラムを作成した。だがしかし、なぜかストアドプロシージャの実行がうまくいっていないようであった。

ストアドプロシージャはデータの集計 + INSERTしか行っておらず、SQLServer Management Studio上で当該のストアドプロシージャを実行しても、エラーが一切確認できなかった。

 

ログやイベントビューアーなどから始まり、怪しい行を消したりCURSORをいじったり、SQLSetStmtAttrをいじったり、早3時間・・・。いろいろ行って分かったのは、「CURSORループ内でINSERTを使用すると止まる」ということであった。

 

INSERT特有といえば、Management Studio上でINSERT構文を実行すると以下のメッセージが現れることくらいである。

 

f:id:atwtama:20180418214134p:plain

 

これやろ!!!!!なんとなくやけどこの(1行処理されました)という処理行数メッセージ!!!Management Studio上では自然におるけど、絶対に悪い奴やろ!!!とりあえず、ストアドプロシージャ内に「SET NO COUNT ON」を記述すれば消えます。この1行を追加するだけで、(1行処理されました)と出力されていた状態から、以下のように「コマンドは正常に完了しました。」という文字列に変わりました。

 

f:id:atwtama:20180418214407p:plain

 

まじで、これだけで、正常にサービスからストアドプロシージャが実行されるようになりました。めでたしめでたし。

 

 

 

その後、突然のデジャブから、一年前に作成した同様の処理を行うストアドプロシージャを確認すると、SET NO COUNT ONが記述されていた。つまり、私は当該問題に一度ぶちあたり、解決していたのにもかかわらず、忘れていたのである。

 

なので、備忘録としてここに記す。