<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>SQL Serverでこんなこと。</title><link>http://blogs.sqlpassj.org/akiko/category/436.aspx</link><description>SQL Server2000/2005も含め、こんなふうに使っています、といったカテゴリです。</description><managingEditor>あきこ</managingEditor><dc:language>ja-JP</dc:language><generator>.Text Version 0.95.2004.102</generator><item><dc:creator>あきこ</dc:creator><title>PerlからADO</title><link>http://blogs.sqlpassj.org/akiko/archive/2008/01/04/24442.aspx</link><pubDate>Fri, 04 Jan 2008 09:44:00 GMT</pubDate><guid>http://blogs.sqlpassj.org/akiko/archive/2008/01/04/24442.aspx</guid><wfw:comment>http://blogs.sqlpassj.org/akiko/comments/24442.aspx</wfw:comment><comments>http://blogs.sqlpassj.org/akiko/archive/2008/01/04/24442.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.sqlpassj.org/akiko/comments/commentRss/24442.aspx</wfw:commentRss><trackback:ping>http://blogs.sqlpassj.org/akiko/services/trackbacks/24442.aspx</trackback:ping><description>&lt;P&gt;
&lt;HR id=null&gt;
最近、&lt;STRONG&gt;Perl&lt;/STRONG&gt;からSQL Serverへの接続を行うコードを書いていたので、その覚え書きです。 
&lt;HR id=null&gt;

&lt;P&gt;&lt;/P&gt;
&lt;P&gt;実は、ストアドや.NET系のコーディングを始める前は、PerlやJavaがメインで、DB操作のためのSQLは、コードや設定ファイルの中に書くことが中心でした。(ただしOracleとかでした)&lt;/P&gt;
&lt;P&gt;その後、SQL Serverを中心にお仕事をするようになってから、ストアドを多用するようになり、コードもC#などで書くようになっていきました。&lt;/P&gt;
&lt;P&gt;さて今回、XML-RPCで外部APIと連携を行う必要が出たので、PerlでSQL Serverの操作を行うことになりました。（C#でもXML-RPCは実装可能だったのですが、私以外のメンテナーがいないので、同僚がメンテナンスしやすいPerlで行きましょう、ということになったのでした...）&lt;/P&gt;
&lt;P&gt;ただ、私としては、できるだけ面倒なSQLはコードに書かず、サーバ側のストアドでカバーしたいというのが希望でした。同僚も、SQL(ストアド）の方は操作/修正には問題無いので、この方針で。&lt;/P&gt;
&lt;UL&gt;
&lt;UL&gt;
&lt;LI&gt;ストアドを使うメリットは、まずは、Perl中にSQLを書かなくて済むこと。（コード内で、@や\といった特殊文エスケープしたりするのが面倒なんですよね....） 
&lt;LI&gt;同じストアドは（データ取得用ですけど）、ManagementStudioからも呼べるし、WebServiceでも呼び出せます。JavaのJDBCでも呼べますね。 &lt;/LI&gt;&lt;/UL&gt;&lt;/UL&gt;
&lt;P&gt;さて、問題は、PerlのDBIで、SELECTステートメントを返すストアドをどう実行するか、ということと、複数SELECTの結果が返る場合、値をどうやって取得するかです。&lt;/P&gt;
&lt;UL&gt;
&lt;UL&gt;
&lt;LI&gt;どうやらDBI + ODBCだとうまくできません....。（というか、とんでもなく久しぶりなので、よく分らない） 
&lt;LI&gt;かと言って、またもPerl中に長～いSQLは書きたくない。&lt;/LI&gt;&lt;/UL&gt;&lt;/UL&gt;
&lt;P&gt;一方、ADO .NETだと、SELECT結果は、複数STATEMENTも含め、DataSetというオブジェクトで返してくれるので、それぞれテーブル名や順番に取り出すことができます。（ここが、私が.NETのASPにしたいよ～と言った理由のひとつでした）&lt;/P&gt;
&lt;P&gt;で、かなり時間がかかってしまったのですが、調べた結果、&lt;STRONG&gt;Win32::OLE&lt;/STRONG&gt;を使うと、&lt;STRONG&gt;ADOを用できることが判明&lt;/STRONG&gt;。&lt;/P&gt;
&lt;P&gt;若干C#などで扱うのよりは面倒ではありますが、これでいくらか幸せになりました。&lt;/P&gt;
&lt;P&gt;
&lt;HR id=null&gt;

&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#000080 size=2&gt;use strict;&lt;BR&gt;use Win32::OLE;&lt;BR&gt;use vars qw($dsn);&lt;BR&gt;&lt;BR&gt;# Data Source Setting&lt;BR&gt;$dsn = "driver=SQL Server;".&lt;BR&gt;&amp;nbsp;"Server=localhost;".&lt;BR&gt;&amp;nbsp;"database=TestDB;".&lt;BR&gt;&amp;nbsp;"Trusted_Connection=no;".&lt;BR&gt;&amp;nbsp;"AutoTranslate=No;";&lt;BR&gt;&lt;BR&gt;# Connection Open&lt;BR&gt;my $Conn = Win32::OLE-&amp;gt;new("ADODB.Connection");&lt;BR&gt;$Conn-&amp;gt;{CursorLocation} = 3;? # the same as adUseClient&lt;BR&gt;$Conn-&amp;gt;{Open} = $dsn;&lt;BR&gt;&lt;BR&gt;if (Win32::OLE-&amp;gt;LastError() != 0) {&lt;BR&gt;&amp;nbsp; print "Failed creating ADODB.Connection object -&amp;gt; "&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; . Win32::OLE-&amp;gt;LastError();&lt;BR&gt;&amp;nbsp; exit 0;&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;my $Cmd = Win32::OLE-&amp;gt;new("ADODB.Command");&lt;BR&gt;&lt;BR&gt;if (Win32::OLE-&amp;gt;LastError() != 0) {&lt;BR&gt;&amp;nbsp;&amp;nbsp; print "Failed creating ADODB.Command object -&amp;gt; "&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; . Win32::OLE-&amp;gt;LastError();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;exit 0;&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;my $Id;&lt;BR&gt;my $ReferenceId;&lt;BR&gt;&lt;BR&gt;####&lt;BR&gt;# For Test&lt;BR&gt;#&lt;BR&gt;# 実際は、CGIのRequest Parameterやコマンドライン引数などから受け取ります。&lt;BR&gt;#&lt;BR&gt;###&lt;BR&gt;$Id = 8;&lt;BR&gt;$ReferenceId= 300;&lt;BR&gt;&lt;BR&gt;# Command Execute&lt;BR&gt;$Cmd-&amp;gt;{CommandType} = 4; # Execute as Stored&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#000080 size=2&gt;# Prepared Statementを使わない場合はこんなかんじ。&lt;BR&gt;$Cmd-&amp;gt;{CommandText} = &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "dbo.getSampleData ($Id, $ReferenceId )";&lt;BR&gt;$Cmd-&amp;gt;{CursorLocation} = 3;&lt;BR&gt;$Cmd-&amp;gt;{ActiveConnection} = $Conn;&lt;BR&gt;&lt;BR&gt;$Cmd-&amp;gt;{Prepared} = 1;&lt;BR&gt;$Cmd-&amp;gt;{CommandTimeout} = 15;&lt;BR&gt;&lt;BR&gt;my $rs = $Cmd-&amp;gt;Execute();&lt;BR&gt;&lt;BR&gt;if (Win32::OLE-&amp;gt;LastError() != 0) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print "Failed opening ADODB.Recordset object for Command -&amp;gt; ". Win32::OLE-&amp;gt;LastError();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; exit 0;&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;my $rs_count = $rs-&amp;gt;{RecordCount};&lt;BR&gt;print $rs_count . "\n";&lt;BR&gt;if (!$rs_count) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print "Record not found to post or close.\n";&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; exit 0;&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;print "\n------------1st SELECT Result-------------\n";&lt;BR&gt;while ($rs-&amp;gt;EOF != 1) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print "Id = ". $rs-&amp;gt;Fields('Id')-&amp;gt;{Value}."\n";&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print "Name = ". $rs-&amp;gt;Fields('Name')-&amp;gt;{Value}."\n";&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $rs-&amp;gt;MoveNext();&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;my $rs1 = $rs-&amp;gt;NextRecordSet();&lt;BR&gt;&lt;BR&gt;print "\n------------2nd SELECT Result-------------\n";&lt;BR&gt;while ($rs1-&amp;gt;EOF != 1) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print "ReferenceId = ". $rs-&amp;gt;Fields('ReferenceId')-&amp;gt;{Value}."\n";&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print "ProductName = ". $rs-&amp;gt;Fields('ProductName')-&amp;gt;{Value}."\n";&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#000080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#000080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#000080 size=2&gt;$rs1-&amp;gt;MoveNext();&lt;BR&gt;}&lt;BR&gt;$rs-&amp;gt;Close();&lt;BR&gt;$Conn-&amp;gt;Close();&lt;BR&gt;exit 0;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;
&lt;HR id=null&gt;

&lt;P&gt;&lt;/P&gt;
&lt;P&gt;Prepared Statementを使ってストアド実行時の引数を渡したい場合は、こんな感じ。&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#000080 size=2&gt;$Cmd-&amp;gt;{Prepared} = 1;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#000080 size=2&gt;#ストアドの戻り値を指定する場合　（Direction = 4）&lt;BR&gt;$Cmd-&amp;gt;Parameters-&amp;gt;Append(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $Cmd-&amp;gt;CreateParameter(&lt;/FONT&gt;&lt;A href="mailto:'@retval'"&gt;&lt;FONT color=#000080 size=2&gt;'@retval'&lt;/FONT&gt;&lt;/A&gt;&lt;FONT color=#000080 size=2&gt;, 3, 4));&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#000080 size=2&gt;# ストアドへの引数はこちら&lt;BR&gt;$Cmd-&amp;gt;Parameters-&amp;gt;Append($Cmd-&amp;gt;CreateParameter(&lt;/FONT&gt;&lt;A href="mailto:'@Id'"&gt;&lt;FONT color=#000080 size=2&gt;'@Id'&lt;/FONT&gt;&lt;/A&gt;&lt;FONT color=#000080 size=2&gt;, 3, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1, , $Id));&lt;BR&gt;$Cmd-&amp;gt;Parameters(&lt;/FONT&gt;&lt;A href="mailto:'@Id')-&gt;{Value"&gt;&lt;FONT color=#000080 size=2&gt;'@Id')-&amp;gt;{Value&lt;/FONT&gt;&lt;/A&gt;&lt;FONT color=#000080 size=2&gt;} = $Id; &lt;BR&gt;　　:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#000080 size=2&gt;my $rs = $Cmd-&amp;gt;Execute();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#000080 size=2&gt;if (Win32::OLE-&amp;gt;LastError() != 0) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; adoError(Win32::OLE-&amp;gt;LastError());&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#000080 size=2&gt;# 戻り値を取得します&lt;/FONT&gt;&lt;FONT color=#000080 size=2&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#000080 size=2&gt;$retval = $Cmd-&amp;gt;Parameters(&lt;A href="mailto:'@retval')-&gt;{Value"&gt;'@retval')-&amp;gt;{Value&lt;/A&gt;};&lt;BR&gt;&lt;/FONT&gt;
&lt;HR id=null&gt;

&lt;P&gt;&lt;/P&gt;
&lt;P&gt;ただ、通常のADOのように、PerlからでもResultSetにテーブル名を付けて、明示的にアクセスできるのかは、まだ分りませんでした....。&lt;/P&gt;
&lt;P&gt;また、ストアドへのパラメータを指定する部分は、Win32::OLE::Variantを使えばもっといいのかもしれませんが、うまく動かなかったので、以下のサイトを参考に直接値を指定しました。&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/jpdnvid/htm/VintrDev/VISQL/visql.asp"&gt;http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/jpdnvid/htm/VintrDev/VISQL/visql.asp&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;また、コーディングの際は、ActivePerlを使い、eclipse + Perl EPICというPerl用のプラグインを使ってみました。これもなかなか便利でした。(Visual Perlっていうのもあるんですね)&lt;/P&gt;&lt;img src ="http://blogs.sqlpassj.org/akiko/aggbug/24442.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>あきこ</dc:creator><title>FOR XML PATHモード。</title><link>http://blogs.sqlpassj.org/akiko/archive/2007/11/13/24258.aspx</link><pubDate>Tue, 13 Nov 2007 16:57:00 GMT</pubDate><guid>http://blogs.sqlpassj.org/akiko/archive/2007/11/13/24258.aspx</guid><wfw:comment>http://blogs.sqlpassj.org/akiko/comments/24258.aspx</wfw:comment><comments>http://blogs.sqlpassj.org/akiko/archive/2007/11/13/24258.aspx#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://blogs.sqlpassj.org/akiko/comments/commentRss/24258.aspx</wfw:commentRss><trackback:ping>http://blogs.sqlpassj.org/akiko/services/trackbacks/24258.aspx</trackback:ping><description>&lt;DIV class=entryBody&gt;
&lt;P class=plain&gt;覚え書きのようなものですが....。&lt;/P&gt;
&lt;P class=plain&gt;SQL Server 2005では、FOR　XMLの機能が、かなり良くなっていました。（私個人的には、『とっても』でした）&lt;/P&gt;
&lt;P class=plain&gt;SQL Server 2000の時と同じ、&lt;STRONG&gt;FOR XML Auto　&lt;/STRONG&gt;とか &lt;STRONG&gt;RAW&lt;/STRONG&gt;モードももちろん使えます。&lt;BR&gt;ただし、上記のモードだと、お手軽ではあるんですが、Viewや一時テーブル、テーブル変数を使ったSELECTが、思いもよらないXMLで出力されることがありました。&lt;/P&gt;
&lt;P class=plain&gt;でも、2005だと、PATHモードのおかげで、かなり自分の希望に近い形で、XMLを出力させることができるようになりました。&lt;/P&gt;
&lt;DIV class=plain&gt;
&lt;HR&gt;
&lt;/DIV&gt;
&lt;P class=plain&gt;[今までのパターン]&lt;/P&gt;
&lt;P class=plain&gt;SELECT Id AS Id, Name AS Name, ISNULL(NickName, Name) AS NickName&lt;BR&gt;&amp;nbsp;&amp;nbsp; FROM [Test].[DocumentType]&amp;nbsp; AS "DocumentType"&lt;BR&gt;&amp;nbsp; WHERE IsEnabled = 1&lt;BR&gt;&amp;nbsp; &lt;FONT color=#000080&gt;FOR XML Auto, Elements&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=plain&gt;-- 実行結果&lt;/P&gt;
&lt;P class=plain&gt;&amp;lt;DocumentType&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;Id&amp;gt;1&amp;lt;/Id&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;Name&amp;gt;見積り&amp;lt;/Name&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;NickName&amp;gt;みつもり&amp;lt;/NickName&amp;gt;&lt;BR&gt;&amp;lt;/DocumentType&amp;gt;&lt;BR&gt;&amp;lt;DocumentType&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;Id&amp;gt;3&amp;lt;/Id&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;Name&amp;gt;交通費精算&amp;lt;/Name&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;NickName&amp;gt;こうつうひ&amp;lt;/NickName&amp;gt;&lt;BR&gt;&amp;lt;/DocumentType&amp;gt;&lt;/P&gt;
&lt;P class=plain&gt;上記は、FOR　XML Autoモードの場合ですが、SELECT結果が複数あった場合は、1行につき1つのXMLで、複数のXMLが返ります。(e4x的に言うと、XMLListという感じでした。)&lt;/P&gt;
&lt;P class=plain&gt;この場合、私が直面した困った点は、以下の通りです。&lt;/P&gt;
&lt;DIV class=plain&gt;
&lt;UL&gt;
&lt;LI&gt;ドキュメントルートのタグ（たとえば&amp;lt;root&amp;gt;...&amp;lt;/root&amp;gt;）タグは自分でつけないといけませんでした。 
&lt;LI&gt;また、要素と属性を混在したXMLにするには、&lt;STRONG&gt;EXPLICITモード&lt;/STRONG&gt;とかを使わないといけなかったのですが、これが非常にわかりづらいものでした。 
&lt;LI&gt;Viewを連結させた場合は、予想外の入れ子構造になっていたりしました。&lt;/LI&gt;&lt;/UL&gt;&lt;/DIV&gt;
&lt;DIV class=plain&gt;なんとかあれこれ操作して、解決はできていたのですが、制限があって断念していたことも、いくつかありました。&lt;/DIV&gt;
&lt;DIV class=plain&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;HR&gt;

&lt;P&gt;&lt;STRONG&gt;[PATHモード利用]&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;さて、2005のドキュメントを見ると、PATHモードというものがあるのに、遅ればせながら気が付きました。&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;PATHモードを利用すると、わりと理解しやすいSQLで、XMLの出力をコントロールできるようになります。 
&lt;LI&gt;EXPLICITモードというのが2000から使えたので、試してみたのですが、上記の通り、これが超理解に苦しみました。PATHモードを知った時、先にこっちを知っていれば...と、すくなからず後悔しました。&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;さて、SQLはこんな感じに指定しました。AS -&amp;gt; 要素名、@ -&amp;gt; 属性名になり、データは要素/属性のテキストノードとして格納されます。&lt;/P&gt;
&lt;P&gt;SELECT (SELECT [Id] AS "@Id",&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Name] AS "@Name"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ISNULL([NickName], [Name]) AS "@NickName"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;FROM [Test].[DocumentType] &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE IsEnabled = 1&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#a52a2a&gt;FOR XML PATH('Item'),&lt;/FONT&gt; TYPE) AS "DocumentType"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#a52a2a&gt;FOR XML PATH(''), ROOT('root')&lt;/FONT&gt; -- root要素を追加&lt;/P&gt;
&lt;P&gt;-- 実行結果&lt;/P&gt;
&lt;P&gt;&amp;lt;root&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;DocumentType&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Item Id="1" Name="見積り" NickName="みつもり" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Item Id="3" Name="交通費精算" NickName="こうつうひ" /&amp;gt;&lt;BR&gt;　　　　　　　　　　　：&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Item Id="5" Name="顧客見積もり" NickName="こきゃくみつもり" /&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;/DocumentType&amp;gt;&lt;BR&gt;&amp;lt;/root&amp;gt;&lt;/P&gt;
&lt;P&gt;今度は、root要素も指定できるし、要素と属性を混在させたりできます。&lt;/P&gt;
&lt;P&gt;※ Namespace付きにする場合は、こんな感じで指定できました。&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#a52a2a&gt;WITH XMLNAMESPACES&lt;/FONT&gt; (&lt;BR&gt;&amp;nbsp;&amp;nbsp; 'http://blogs.passj.org/akiko' as Akiko)&lt;BR&gt;　SELECT (SELECT [Id] AS "@Id"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ,[Name] AS "@Name"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ,ISNULL([NickName], [Name]) AS "@NickName"&lt;BR&gt;&amp;nbsp; FROM [Test].[DocumentType] &lt;BR&gt;&amp;nbsp;WHERE IsEnabled = 1&lt;BR&gt;&amp;nbsp;FOR XML PATH('Akiko:Item'), TYPE) AS "Akiko:DocumentType"&lt;BR&gt;FOR XML PATH(''), ROOT('Akiko:root')&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#a52a2a&gt;※WITH XMLNAMESPACES (....)&lt;/FONT&gt;がポイント。&lt;/P&gt;
&lt;P&gt;結果はこんな感じになります。&lt;/P&gt;
&lt;P&gt;&amp;lt;Akiko:root xmlns:Charon="http://blogs.passj.org/akiko"&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;Akiko:DocumentType&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Akiko:Item xmlns:Akiko="http://blogs.passj.org/akiko" Id="1" Name="見積り" NickName="みつもり" /&amp;gt;&lt;BR&gt;　　　　　:&lt;/P&gt;
&lt;P&gt;&amp;nbsp; &amp;lt;/Akiko:DocumentType&amp;gt;&lt;BR&gt;&amp;lt;/Akiko:root&amp;gt;&lt;/P&gt;&lt;A name=more&gt;&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV class=visualClear&gt;&lt;!-- --&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;
&lt;HR id=null&gt;
&lt;/FONT&gt;もしかして、使い方を間違っていたり、まだまだ分っていないことがたくさんありそうですが、私には嬉しい機能でした。&lt;/P&gt;
&lt;P&gt;そんなことを書いているうちに、もう2008....。いったいどうなるのでしょうか、楽しみです。&lt;/P&gt;&lt;img src ="http://blogs.sqlpassj.org/akiko/aggbug/24258.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>あきこ</dc:creator><title>いまごろですが、CTE。</title><link>http://blogs.sqlpassj.org/akiko/archive/2007/08/24/23943.aspx</link><pubDate>Fri, 24 Aug 2007 16:51:00 GMT</pubDate><guid>http://blogs.sqlpassj.org/akiko/archive/2007/08/24/23943.aspx</guid><wfw:comment>http://blogs.sqlpassj.org/akiko/comments/23943.aspx</wfw:comment><comments>http://blogs.sqlpassj.org/akiko/archive/2007/08/24/23943.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.sqlpassj.org/akiko/comments/commentRss/23943.aspx</wfw:commentRss><trackback:ping>http://blogs.sqlpassj.org/akiko/services/trackbacks/23943.aspx</trackback:ping><description>&lt;P&gt;部署の情報を格納したテーブルを作っています。&lt;/P&gt;
&lt;P&gt;ここには、ParentIdという列に、1つ上の親の部署Idを格納しています。ここから、上下の関係を導出する...という具合に考えているのですが、この方法だと、どうしても再帰クエリになってしまいます。&lt;/P&gt;
&lt;P&gt;Oracleでは、CONNECTというのを使うとうまくできそうなんですが、SQL Serverだとどうしていいのか分かりません...。&lt;/P&gt;
&lt;P&gt;（階層は深くても4階層くらいまでなので、固定のSQLでも頑張ればいいのですが）&lt;/P&gt;
&lt;P&gt;また、データはDBはRDBにフラットに定義しておいて、実際にアプリケーションに渡す場合は、XMLに加工して使おうと思っています。&lt;/P&gt;
&lt;P&gt;色々探していたら、CTEというのが使えるんですね。&lt;/P&gt;
&lt;P&gt;正しい方法じゃないかもしれませんが、とりあえず、やってみると....。&lt;/P&gt;
&lt;P&gt;
&lt;HR id=null&gt;

&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff&gt;&lt;PRE&gt;USE Common&lt;/PRE&gt;&lt;PRE&gt;GO
WITH Recursive (ParentId, Id, Code, Name, Level)
AS
(
-- Divisionの定義
    SELECT D.ParentId, D.Id, D.Code, D.Name, 
        0 AS Level
    FROM Division AS D
    WHERE ParentId IS NULL
	AND IsEnabled = 1
    UNION ALL
-- 再帰の定義
    SELECT D.ParentId, D.Id, D.Code, D.Name, 
        Level + 1
    FROM Division AS D
    INNER JOIN Recursive AS R
        ON D.ParentId = R.Id
	AND IsEnabled = 1
)
-- 再帰テーブルから取り出し
SELECT ParentId, Id, Code, Name, Level, replicate('-', (Level)* 10) + Code 
FROM Recursive&lt;/PRE&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;&lt;FONT face="Courier New" size=2&gt;
&lt;P&gt;
&lt;HR id=null&gt;

&lt;P&gt;&lt;/P&gt;
&lt;P&gt;結果。個人的に、かなり感動しました(^^;&lt;/P&gt;
&lt;P&gt;FOR XML, PATHモードを使えば、そこそこ希望しているものが作れるかもしれません...。&lt;/P&gt;&lt;/FONT&gt;&lt;img src ="http://blogs.sqlpassj.org/akiko/aggbug/23943.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>あきこ</dc:creator><title>硬直の瞬間。</title><link>http://blogs.sqlpassj.org/akiko/archive/2007/02/18/20679.aspx</link><pubDate>Sun, 18 Feb 2007 15:21:00 GMT</pubDate><guid>http://blogs.sqlpassj.org/akiko/archive/2007/02/18/20679.aspx</guid><wfw:comment>http://blogs.sqlpassj.org/akiko/comments/20679.aspx</wfw:comment><comments>http://blogs.sqlpassj.org/akiko/archive/2007/02/18/20679.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.sqlpassj.org/akiko/comments/commentRss/20679.aspx</wfw:commentRss><trackback:ping>http://blogs.sqlpassj.org/akiko/services/trackbacks/20679.aspx</trackback:ping><description>&lt;P&gt;またしてもずいぶん間が開いてしまいました...。 &lt;BR&gt;相変わらず、仕事も育児も家事も、&lt;STRONG&gt;全部中途半端&lt;/STRONG&gt;で、あくせくと過ごしております...。?&lt;/P&gt;
&lt;P&gt;さて、昨年の最後の書き込みで、『&lt;EM&gt;年内に受験しないと～&lt;/EM&gt;』と表明したにもかかわらず、その後の進展も報告も放置してしまいました。（皆さまからも励ましのお言葉をいただいたにもかかわらず、申し訳ありません....）&lt;/P&gt;
&lt;P&gt;11月に入ってから、さらに忙しさを理由にしてしまい、実際に受験の時間が取れたのは、師走のクリスマス前でした。今回受験したのは&lt;STRONG&gt;試験番号：70-431&lt;/STRONG&gt;(データベースの保守と実装）。しかも、受験申し込みは、受験日の3日前という、自分でも情け無いスケジュールでした。&lt;/P&gt;
&lt;P&gt;日々SQL Serverでのお仕事をしつつも、実際に受験本を読むと、判らないことだらけ...。しかも使ったことのない機能ばかり。通勤時間になんとか赤本をめくるくらいしかできず、当日になってしまいました。&lt;/P&gt;
&lt;P&gt;そして当日。通勤途上の試験会場での受験となりました。&lt;/P&gt;
&lt;HR&gt;

&lt;P&gt;&lt;IMG alt=硬直の瞬間。 src="/images/blogs_sqlpassj_org/akiko/451/o_20070218.jpg" align=left&gt;&lt;/P&gt;
&lt;P&gt;メモ書き用のホワイトボードに、自身の無い問題の番号を書き写して、なんとか問題を進めていき、最後までたどり着きました。でも、とっても怪しいと思った問題の数は20問近く(^^;これでは絶対に受かりません...。&lt;/P&gt;
&lt;P&gt;再度見直しを進めたのですが、それでもまだ怪しい。『これ以上見直しても、もう無理だ～』と思ったところで、終了のボタンをクリックしました。&lt;/P&gt;
&lt;P&gt;ボタンをクリックすると、その場で採点され、結果が出ます。この判定までの、&lt;STRONG&gt;ほんの少しの間が&lt;/STRONG&gt;、非常に精神衛生上宜しくない時間でした。（運転免許の試験の時に、電光掲示板に自分の番号がめぐって来るかどうかを待っていた時と同じくらい、ドキドキしていました）&lt;/P&gt;
&lt;P&gt;その結果。ここで書くのも非常にお恥ずかしいのですが、ボーダーライン.....。700点丁度という結果でした(^^;;;後学のために、もう一回どんな問題が出たのか見直したいくらい、迷うものが多くて自分でもホトホト困りました。そして、帰ってから、参考書を読み直したのは言うまでもありません...。&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#a9a9a9&gt;＃こんな状態なので、他のネットで『満点で合格』とか高得点で合格しましたという書き込みを見ると、本当に済みませんという気持ちです。&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;個人的には、レプリケート、リンクサーバなどの設定を、自分の環境に取り入れることが出来たので、『勉強したこと自体は、やっぱり良かった』のに相違ございませんが。&lt;/P&gt;
&lt;P&gt;
&lt;HR id=null&gt;

&lt;P&gt;&lt;/P&gt;
&lt;P&gt;そうこう言っている間に、VistaやらSQL Server 2005のR2 やらが出てくるんですね。なんとかがんばろう...。&lt;/P&gt;
&lt;P&gt;最後に、コメントや励ましのお言葉を下さった皆様、ありがとうございました!こんな結果で恐縮なのですが、まずはご報告とさせていただきます。&lt;/P&gt;&lt;img src ="http://blogs.sqlpassj.org/akiko/aggbug/20679.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>あきこ</dc:creator><title>SQL Server + IISでSOAP &amp; Flex</title><link>http://blogs.sqlpassj.org/akiko/archive/2005/07/15/12239.aspx</link><pubDate>Fri, 15 Jul 2005 16:08:00 GMT</pubDate><guid>http://blogs.sqlpassj.org/akiko/archive/2005/07/15/12239.aspx</guid><wfw:comment>http://blogs.sqlpassj.org/akiko/comments/12239.aspx</wfw:comment><comments>http://blogs.sqlpassj.org/akiko/archive/2005/07/15/12239.aspx#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://blogs.sqlpassj.org/akiko/comments/commentRss/12239.aspx</wfw:commentRss><trackback:ping>http://blogs.sqlpassj.org/akiko/services/trackbacks/12239.aspx</trackback:ping><description>&lt;P&gt;&lt;A href="http://www.macromedia.com/jp/software/flex/"&gt;Flex&lt;/A&gt;についてコメントをいただいたりしましたので、私がどんな風に使っているのかということだけ、少しお話させていただきます。&lt;/P&gt;
&lt;P&gt;Webのインタフェースを作る際、どうしても「クロスブラウザ」なものを用意しないといけませんでした。操作性を考えるとJavaScriptやDHTMLを使うと良いのですが、ユーザの皆さんが使っているのが、IEだけでなく、OperaやMozilla、FireFoxが混在している環境だったので、それを思うととても頭の痛い状況に...。&lt;/P&gt;
&lt;P&gt;それなら、ということで、Flashの技術を使おうということになったのです。Flashと、データソースとのやりとりは、SOAPを使っています。&lt;/P&gt;
&lt;P&gt;さて、SQL Serverがどう関わったのかと言いますと、このSOAPの部分です。&lt;/P&gt;
&lt;P&gt;そもそもSQL Serverや.NETの開発環境自体、触れたのが昨年冬ぐらいだったので、まだまだVisual Studioの使い方や、WEBアプリケーションの作り方も良くわからない時期でした。かろうじて判るのは、SQLと、Javaに近い（と感じられた）C#。&lt;/P&gt;
&lt;P&gt;その後、どうやって書けば良いかなあ、と思っているときに、PASSJアフタースクールのご縁で、藤代さんからWebMatrixのことを教えていただき、なんちゃってASPなものを作ることができました。少しは.NETな環境に慣れていったので、希望の光は見えつつも、やはりコーディングに四苦八苦する日々。&lt;/P&gt;
&lt;P&gt;上司も実は.NETな環境は初めてで、共に判るのはSQLだけでした。「なんとか楽をできないかなあ」と、上司と話していた時に、SQL Serverに加えて、&lt;STRONG&gt;IISとSOAP ToolKitを使えば、Stored ProcedureをSOAPとして利用できる&lt;/STRONG&gt;ことを耳にしました。&lt;/P&gt;
&lt;P&gt;早速やってみると、なるほど、とても作りやすい！&lt;/P&gt;
&lt;P&gt;おかげさまで、「C#で書かなくちゃ。トホホ....。」と思っていた部分を、ほとんどStored Procedure内で処理できてしまい、かなり速いペースで目的のものを作ることができました。また、Flashで表示させるのには向いていない、表データを一覧で見せたり、CSVで提供するようなものは、同じくSOAP ToolKitを使い、templateを応用したりして、こちらも大変助かりました。&lt;/P&gt;
&lt;P&gt;Stored ProcedureやSOAP Toolkitなどの情報は、やはり、PASSJのMLや掲示板などに大変お世話になりました。ですから、とても足を向けては眠れません。&lt;/P&gt;
&lt;P&gt;SQL Server 2005ではどうやって作ればいいのか、まだ良くわかっていないのですけれど、うまく移行できたらなあと思っています。&lt;/P&gt;&lt;img src ="http://blogs.sqlpassj.org/akiko/aggbug/12239.aspx" width = "1" height = "1" /&gt;</description></item></channel></rss>