<?xml version="1.0" encoding="UTF-8" ?> <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>Database</title><link>http://blogs.wankuma.com/nakap/category/1882.aspx</link><description>Database</description><managingEditor>nakaP</managingEditor><dc:language>ja-JP</dc:language><generator>.Text Version 0.95.2004.102</generator><item><dc:creator>nakaP</dc:creator><title>インラインユーザー定義関数</title><link>http://blogs.wankuma.com/nakap/archive/2009/09/03/180818.aspx</link><pubDate>Thu, 03 Sep 2009 15:34:00 GMT</pubDate><guid>http://blogs.wankuma.com/nakap/archive/2009/09/03/180818.aspx</guid><wfw:comment>http://blogs.wankuma.com/nakap/comments/180818.aspx</wfw:comment><comments>http://blogs.wankuma.com/nakap/archive/2009/09/03/180818.aspx#Feedback</comments><slash:comments>28</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nakap/comments/commentRss/180818.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nakap/services/trackbacks/180818.aspx</trackback:ping><description>&lt;P&gt;[@IT]&lt;A href="http://ap.atmarkit.co.jp/bbs/core/fdb/15979"&gt;ユーザー定義関数から正しくない答えが返される&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;SQLServerでは、テーブル型を返すユーザー定義関数をインラインユーザー定義関数と呼ぶそうです。&lt;/P&gt;
&lt;P&gt;例えば、以下のようなテーブルを作り、データを格納します。&lt;/P&gt;
&lt;P&gt;(環境：SQL Server 2005 Express Edition)&lt;/P&gt;&lt;PRE class=code&gt;[テーブル]
member_table
member_code int
member_name nvarchar(50)
[データ]
member_code member_name
1           中博俊
2           じゃんぬねっと
3           nakaP&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;member_codeを指定して、該当する行を返すユーザー定義関数を作ります。&lt;/P&gt;&lt;PRE class=code&gt;CREATE FUNCTION dbo.Test(@code INT)
RETURNS TABLE
AS RETURN (SELECT * FROM member_table WHERE member_code = @code)
GO&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;そしてユーザー定義関数を実行すると、以下のような結果が返ります。 &lt;PRE class=code&gt;SELECT * FROM Test(1)
[結果]
member_code member_name
1           中博俊&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;ここでテーブルに列を追加し、データを編集します。&lt;/P&gt;&lt;PRE class=code&gt;[テーブル]member_table
member_code  int
memver_class nvarchar(50)
member_name  nvarchar(50)
[データ]
member_code member_class member_name
1           代表         中博俊
2           代表         じゃんぬねっと
3           下っ端       nakaP&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;そして再度ユーザー定義関数を実行すると、以下のような結果に変わります。&lt;/P&gt;&lt;PRE class=code&gt;SELECT * FROM Test(1)
[結果]
member_code member_name
1           代表&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;列名と内容が一致していません。なぜでしょうか。&lt;/P&gt;
&lt;P&gt;まず、sys.objectsのid列を利用して、sys.columnsの情報を取得します。&lt;/P&gt;
&lt;P&gt;(SQL Server 2000 ではsysobjects、syscolumns)&lt;/P&gt;
&lt;P&gt;それぞれの詳細は以下をご覧ください。&lt;/P&gt;
&lt;P&gt;&lt;A href="http://msdn.microsoft.com/ja-jp/library/ms190324(SQL.90).aspx"&gt;sys.objects&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://msdn.microsoft.com/ja-jp/library/ms176106(SQL.90).aspx"&gt;sys.columns&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;なお参考にsys.parametersもご覧になられるといいかもしれません。&lt;/P&gt;
&lt;P&gt;(SQL Server 2000 ではsysparameters)&lt;/P&gt;
&lt;P&gt;&lt;A href="http://msdn.microsoft.com/ja-jp/library/ms176074(SQL.90).aspx"&gt;sys.parameters&lt;/A&gt;&lt;/P&gt;&lt;PRE class=code&gt;SELECT * FROM sys.columns WHERE object_id = (SELECT object_id FROM sys.objects WHERE name = 'Test')
object_id name column_id ･･･
*******   id   1
*******   name 2&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;項目数は多いですが、member_code列とmember_name列が返されることが分かります。&lt;/P&gt;
&lt;P&gt;ここでも列名と内容が一致していません。&lt;/P&gt;
&lt;P&gt;次にsp_sproc_columnsの情報を見てみます。&lt;/P&gt;
&lt;P&gt;&lt;A href="http://msdn.microsoft.com/ja-jp/library/ms182705(SQL.90).aspx"&gt;sp_sproc_columns&lt;/A&gt;&lt;/P&gt;&lt;PRE class=code&gt;EXEC sp_sproc_column @procedure_name = 'Test'&lt;/PRE&gt;
&lt;P&gt;この結果のTYPE_NAME列を見ると、「table」となっています。&lt;/P&gt;
&lt;P&gt;以上の結果より、インラインユーザー定義関数はテーブルを返しますが、戻り値の列数は２つしかないことが分かります。&lt;/P&gt;
&lt;P&gt;つまり、テーブル定義の変更後は、３列の結果を２列のテーブルとして返しているのです。&lt;/P&gt;
&lt;P&gt;そして、戻り値の列名は便宜上の列名であり、必ずしも元テーブルの列名と同期が取られているわけではないようです。&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;この問題を解決するには、&lt;/P&gt;
&lt;P&gt;１．インラインユーザー定義関数で個別に列名を指定しておく&lt;/P&gt;
&lt;P&gt;２．sp_refreshsqlmoduleを実行する&lt;/P&gt;
&lt;P&gt;ことになります。&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;これがバグなのか仕様なのかは分かりませんが、知っていないとハマりそうですね。&lt;/P&gt;
&lt;P&gt;「select * は便利だけど便利じゃないよ」&lt;/P&gt;
&lt;P&gt;ってことですね。&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/nakap/aggbug/180818.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>nakaP</dc:creator><title>SQL Server 2008 Express 3つの種類</title><link>http://blogs.wankuma.com/nakap/archive/2009/06/12/175000.aspx</link><pubDate>Fri, 12 Jun 2009 16:46:00 GMT</pubDate><guid>http://blogs.wankuma.com/nakap/archive/2009/06/12/175000.aspx</guid><wfw:comment>http://blogs.wankuma.com/nakap/comments/175000.aspx</wfw:comment><comments>http://blogs.wankuma.com/nakap/archive/2009/06/12/175000.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nakap/comments/commentRss/175000.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nakap/services/trackbacks/175000.aspx</trackback:ping><description>&lt;P&gt;ネタ元：&lt;A href="http://blogs.wankuma.com/ogiogi/archive/2009/06/12/174949.aspx"&gt;おぎわらさんとこ&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;「SQL Server 2008 Expressに3つの種類がある」って書かれてたので、気になって調べてみました。&lt;/P&gt;
&lt;P&gt;・&lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyID=58ce885d-508b-45c8-9fd3-118edd8e6fff&amp;amp;DisplayLang=ja"&gt;Microsoft SQL Server 2008 Express&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;・&lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyID=7522a683-4cb2-454e-b908-e805e9bd4e28&amp;amp;DisplayLang=ja"&gt;Microsoft SQL Server 2008 Express with Tools&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;・&lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyID=b5d1b8c3-fda5-4508-b0d0-1311d670e336&amp;amp;DisplayLang=ja"&gt;Microsoft SQL Server 2008 Express with Advanced Services&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;with Tools、with Advancedに付いているグラフィカル管理ツールはSQL Server 2008 Management Studio Basicという名前だそうで。&lt;/P&gt;
&lt;P&gt;with AdvancedにはさらにReporting Servicesが付いてるみたいです。&lt;/P&gt;
&lt;P&gt;どんどんリッチな環境になってきてるのでうれしいかもｗ&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/nakap/aggbug/175000.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>nakaP</dc:creator><title>テーブルの主キー</title><link>http://blogs.wankuma.com/nakap/archive/2009/05/01/172315.aspx</link><pubDate>Fri, 01 May 2009 00:35:00 GMT</pubDate><guid>http://blogs.wankuma.com/nakap/archive/2009/05/01/172315.aspx</guid><wfw:comment>http://blogs.wankuma.com/nakap/comments/172315.aspx</wfw:comment><comments>http://blogs.wankuma.com/nakap/archive/2009/05/01/172315.aspx#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nakap/comments/commentRss/172315.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nakap/services/trackbacks/172315.aspx</trackback:ping><description>&lt;P&gt;テーブルにはほぼ主キー(Primary Key)が設定されていると思うのですが。&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE class=code&gt;column_1  Key_1
column_2  Key_2
column_3
column_4
・
・
・
&lt;/PRE&gt;
&lt;P&gt;こんな風に先頭の列からキーになってるのは特に問題ないのですが、&lt;/P&gt;&lt;PRE class=code&gt;column_1
column_2  Key_2
column_3
column_4  Key_1
・
・
・
&lt;/PRE&gt;
&lt;P&gt;みたいに途中の列にキーが設定されているとものすっっっごく違和感を感じます。&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;これってCOBOLerの感覚・・・なのかな・・・？&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/nakap/aggbug/172315.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>nakaP</dc:creator><title>SQL Server 2005 Express Editionの容量制限</title><link>http://blogs.wankuma.com/nakap/archive/2008/08/06/151933.aspx</link><pubDate>Wed, 06 Aug 2008 11:36:00 GMT</pubDate><guid>http://blogs.wankuma.com/nakap/archive/2008/08/06/151933.aspx</guid><wfw:comment>http://blogs.wankuma.com/nakap/comments/151933.aspx</wfw:comment><comments>http://blogs.wankuma.com/nakap/archive/2008/08/06/151933.aspx#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nakap/comments/commentRss/151933.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nakap/services/trackbacks/151933.aspx</trackback:ping><description>&lt;P&gt;・&lt;A href="http://cs.albis.jp/blogs/ms-18e/archive/2006/09/20/SQL-Server-2005-Express-Edition-_3A00_-_C730FC30BF30D930FC30B9306E30B95BCF914C30_-4GB-_6B303652509655308C308B30_.aspx"&gt;[Hello Another World!]SQL Server 2005 Express Edition : データベースの容量が 4GB に制限される&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;・&lt;A href="http://cs.albis.jp/blogs/ms-18e/archive/2006/03/30/90.aspx"&gt;[Hello Another World!]SQL Server 2005 Express Edition でデータベースの容量が4GBを超えたときの挙動&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;・&lt;A href="http://cs.albis.jp/blogs/ms-18e/archive/2007/01/19/1207.aspx"&gt;[Hello Another World!]SQL Server 2005 Express Edition : データベースの容量が 4GB に制限される その2&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;ueさんとこ。ちょっと必要になるかもしれないのでメモ。&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;現在のところは、&lt;/P&gt;
&lt;P&gt;・データベース毎の容量の制限が 4GB である&lt;/P&gt;
&lt;P&gt;・データベースとはPRIMARYファイルグループのことを指す&lt;/P&gt;
&lt;P&gt;という認識です。&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;これは・・・&lt;/P&gt;
&lt;P&gt;・「HANBAI」と「KAIKEI」というデータベースがあった場合、それぞれが 4GB まで容量を増やすことが出来る？&lt;/P&gt;
&lt;P&gt;・PRIMARYじゃないファイルグループを追加すれば 4GB を超えられる？&lt;/P&gt;
&lt;P&gt;ということなのかな？&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;むー。その他の機能制限が気にならないなら、業務でExpress Editionという選択も有りなのかも。&lt;BR&gt;&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/nakap/aggbug/151933.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>nakaP</dc:creator><title>SQLServer 2008 日本語版 出荷開始</title><link>http://blogs.wankuma.com/nakap/archive/2008/08/02/151492.aspx</link><pubDate>Sat, 02 Aug 2008 08:17:00 GMT</pubDate><guid>http://blogs.wankuma.com/nakap/archive/2008/08/02/151492.aspx</guid><wfw:comment>http://blogs.wankuma.com/nakap/comments/151492.aspx</wfw:comment><comments>http://blogs.wankuma.com/nakap/archive/2008/08/02/151492.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nakap/comments/commentRss/151492.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nakap/services/trackbacks/151492.aspx</trackback:ping><description>&lt;P&gt;&lt;A href="http://www.microsoft.com/japan/sqlserver/2008/default.mspx"&gt;http://www.microsoft.com/japan/sqlserver/2008/default.mspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;SQLServer2008日本語版の提供が８／１より開始されたそうです。&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;#我が社もそろそろ導入・・・か？&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/nakap/aggbug/151492.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>nakaP</dc:creator><title>テーブルのキー設定</title><link>http://blogs.wankuma.com/nakap/archive/2008/07/01/146423.aspx</link><pubDate>Tue, 01 Jul 2008 01:01:00 GMT</pubDate><guid>http://blogs.wankuma.com/nakap/archive/2008/07/01/146423.aspx</guid><wfw:comment>http://blogs.wankuma.com/nakap/comments/146423.aspx</wfw:comment><comments>http://blogs.wankuma.com/nakap/archive/2008/07/01/146423.aspx#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://blogs.wankuma.com/nakap/comments/commentRss/146423.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/nakap/services/trackbacks/146423.aspx</trackback:ping><description>&lt;P&gt;ネタ元：&lt;A href="http://bbs.wankuma.com/index.cgi?mode=al2&amp;amp;namber=21230"&gt;http://bbs.wankuma.com/index.cgi?mode=al2&amp;amp;namber=21230&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;#多分思いっきり勘違いしていたわけですが(^^;&lt;/P&gt;
&lt;P&gt;例えば発注システムを作ろうとした場合、以下のようなテーブルを持つ必要があります。&lt;BR&gt;(簡易すぎると思いますが)&lt;/P&gt;
&lt;P&gt;・取引先マスタ・・・取引先コード、名称、・・・&lt;BR&gt;・商品マスタ　・・・商品コード、商品名、単価、・・・&lt;BR&gt;・発注データ　・・・伝票番号、取引先コード、商品コード、単価、数量、・・・&lt;/P&gt;
&lt;P&gt;各マスタに関しては、コード自体の変更が起こったり、マスタの変更履歴を取りたいという要望がある可能性があるので、サロゲートキーを用意するという人が多いと思います。&lt;BR&gt;また、発注データに関しても、変更履歴を残すなどの理由でサロゲートキーを用意することがあります。&lt;BR&gt;この辺は、履歴も同一テーブル内で保持していたほうが便利な場面が多いと思いますので、サロゲートキーは有効だと思います。&lt;/P&gt;
&lt;P&gt;この場合、発注データと各マスタの紐づけはＩＤで行うようになります。&lt;/P&gt;
&lt;P&gt;・取引先マスタ・・・ＩＤ、取引先コード、名称、・・・&lt;BR&gt;・商品マスタ　・・・ＩＤ、商品コード、商品名、単価、・・・&lt;BR&gt;・発注データ　・・・ＩＤ、伝票番号、取引先ＩＤ、商品ＩＤ、単価、数量、・・・&lt;/P&gt;
&lt;P&gt;ここで、商品に対して単価が１：１であれば楽なのですが、そういう場面はほとんどないでしょう。&lt;BR&gt;同じ商品に対して複数の取引先があり、取引先ごとに単価も違ってくると思います。&lt;BR&gt;そうした場合、取引先・商品別の単価を持つ必要がでてきます。&lt;/P&gt;
&lt;P&gt;・取引先別商品別単価テーブル・・・取引先ＩＤ、商品ＩＤ、単価・・・&lt;/P&gt;
&lt;P&gt;この場合、取引先ＩＤと商品ＩＤの２つでユニークなレコードとなります。&lt;BR&gt;この「取引先別商品別単価テーブル」にサロゲートキー（ネタ元でいう人口キー）が必要なのかということだと思ったのですが・・・。&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;結論としては、僕は「要らない」と判断します。&lt;BR&gt;このテーブルの場合だと、伝票を作成する際に単価を取得するだけです。&lt;BR&gt;単価という項目は、発注データの中にも保持されます。&lt;BR&gt;そして、単価が変更されたからと言って、過去の発注データ内の単価まで影響を及ぼすことはありません。&lt;BR&gt;その時点で設定されている単価を保有していれば良いだけなのです。&lt;BR&gt;履歴も保持したい、という要望もあるかもしれませんが、同一テーブルに保持する必要もないしメリットも感じませんので、トリガなどを使用して別テーブルに保存していけばよいと思います。&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;すべての場合で、とは言いませんが、このような場合だと複合キーであってもよいと思います。&lt;BR&gt;なので、今のところの僕のスタンスは以下のとおり。&lt;/P&gt;
&lt;P&gt;・ナチュラルキーよりはサロゲートキーを使う&lt;BR&gt;・履歴の必要性が低ければサロゲートキーは必要なし、トリガで別テーブルに保存する&lt;BR&gt;・サロゲートキー同士の複合キーなら有り&lt;BR&gt;&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/nakap/aggbug/146423.aspx" width = "1" height = "1" /&gt;</description></item></channel></rss>