WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

SQL Server の IN 演算子の利用

by WebSurfer 2010年8月5日 12:31

DB のテーブルから一つの項目を選び、その項目の詳細を表示するというケースはよくあると思います。そのようなサンプルは Web から容易に見つかると思います。

では、一度に複数の項目を選んで、複数の項目の詳細を同時に表示するにはどうすればいいでしょうか?

SQL Server には IN 演算子というものがあって、それを利用するのがよさそうです。以下は SQL Server 2005 Online Book のサンプルです。

SELECT FirstName, LastName, e.Title
FROM HumanResources.Employee AS e
    JOIN Person.Contact AS c 
    ON e.ContactID = c.ContactID
WHERE e.Title IN ('Design Engineer', 'Tool Designer', 'Marketing Assistant');

ASP.NET のアプリでは、CheckBoxList で複数の項目を選んで、Button クリックで GridView に選んだ項目の詳細を表示することを考えます。

ユーザーの選択結果によって動的にクエリ(上記で言うと、IN (...) の ... の部分)を変える必要があります。

他にもっとスマートなやり方があるかもしれませんが、プログラムで SELECT クエリを組み立てて処置するサンプルを書いておきます。

DB は Microsoft が無償提供している Northwind サンプルデータベースの Orders テーブルを使用しました。

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

  protected void Button1_Click(object sender, EventArgs e)
  {
    string selectedItems = "(";
    int count = 0;

    for (int i = 0; i < CheckBoxList1.Items.Count; i++)
    {
      if (CheckBoxList1.Items[i].Selected)
      {
        selectedItems += CheckBoxList1.Items[i].Value + ", ";
        count++;
      }
    }

    if (count > 0)
    {
      selectedItems = 
        selectedItems.TrimEnd(new char[] { ',', ' ' });
      selectedItems += ")";
      SqlDataSource2.SelectParameters.Clear();
      SqlDataSource2.SelectCommand = 
        "SELECT * FROM [orders] WHERE [EmployeeID] IN "
        + selectedItems + " ORDER BY [EmployeeID]";
    }
    else
    {
      SqlDataSource2.SelectParameters.Clear();
    }       
  }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title>無題のページ</title>
</head>
<body>
  <form id="form1" runat="server">
  <div>
    <asp:SqlDataSource ID="SqlDataSource1" 
      runat="server"
      ConnectionString="<%$ ConnectionStrings:Northwind %>"
      SelectCommand="SELECT DISTINCT [EmployeeID] FROM [Orders] ORDER BY [EmployeeID]">
    </asp:SqlDataSource>
    <asp:CheckBoxList ID="CheckBoxList1" 
      runat="server"
      DataSourceID="SqlDataSource1" 
      DataTextField="EmployeeID"
      DataValueField="EmployeeID">
    </asp:CheckBoxList>
   
    <asp:Button ID="Button1" 
      runat="server" 
      Text="Show Selected Data"
      onclick="Button1_Click" />
       
    <asp:SqlDataSource ID="SqlDataSource2" 
      runat="server"
      ConnectionString="<%$ ConnectionStrings:Northwind %>" >
    </asp:SqlDataSource>
    <asp:GridView ID="GridView1" 
      runat="server" 
      DataSourceID="SqlDataSource2">
    </asp:GridView>   
  </div>
  </form>
</body>
</html>

Tags: ,

ASP.NET

SqlDataSource と楽観的同時実行制御

by WebSurfer 2010年8月5日 12:28

VS2005 (Visual Studio 2005) で作る SqlDataSource の楽観的同時実行制御用クエリは、NULL に対応できないという問題があります。

すでに VS2010 がリリースされている 2010 年 8 月現在、2 世代前の VS2005 を使っている方はそれほど多くないと思いますが、念のため書いておきます。

VS2005 の SqlDataSource 作成ウィザードで、楽観的同時実行制御オプションを有効にしてクエリを自動生成した際、UPDATE, DELETE クエリが NULL に対応できていません。

例えば、memo というフィールドが NULL 許容の場合、以下のようになるべきところ、

WHERE (([memo] = @original_memo) OR ([memo] IS NULL AND @original_memo IS NULL)) ...

VS2005 では以下のようになってしまいます。

WHERE [memo] = @original_memo ...

SQL Server では、= や != などの比較演算子では、引数のいずれかまたは両方が NULL の場合、UNKNOWN が返されます。

従って、DB のフィールドに NULL があると、WHERE 句の条件が成立せず、クエリが実行されない(更新/削除に失敗する)という問題があります。

この問題に対応するには、手作業で、上記のように IS NULL を使って、クエリを書き直してやる必要があります。

VS2008 ではこのあたりは改善されています。VS2010 は未確認です(まさか元に戻っているようなことはないと思いますが)。

なお、型付 DataSet + TableAbapter を、Visual Studio のウィザードを利用して作る場合は、VS2005 でも上記のような問題はありません。

Tags: , ,

ASP.NET

ハイパーリンクで window.open

by WebSurfer 2010年8月4日 12:18

ハイパーリンク(html の a 要素)を利用して小窓を開く場合、以下の例のようにするのがアクセシビリティの面で好ましいそうです。

<a href="xxx.html" 
  onclick="window.open(this.href, ...); return false;">
  小窓を開いて表示
  </a>

window.open(this.href, ...) の ... の部分には第 2, 3 引数が入ります。

第 2 引数は MDN の記事「window.open」によると以下のように設定するそうです。(以前は、特に指定する必要がなければ null で良いと思っていたのですが、'_blank' とした方がよさそうです)

  1. 新しいウィンドウの名前
  2. 既存のウィンドウに第 1 引数の url をロードしたい場合は既存のウィンドウの名前
  3. window.open で常に新しいウィンドウを開きたい場合は '_blank'

第 3 引数は、ウィンドウの大きさや、メニューバーの有無などを指定します。以下のような感じです。

'width=400, height=300, menubar=no, toolbar=no, location=no'

なお、href="window.open(...);" とするのはうまくいきません。小窓が開いた後、元ページは window.open(...) を表示しようとするからです。そういえば、昔、元ウィンドウが [object] という表示になってしまう理由が分からず、かなり悩んだことがありました。(汗)

href="window.open(...); retrun false;" とすれば上記の問題は避けられますが、JavaScript が無効だと小窓どころか何も表示されないので、アクセシビリティの面で好ましくないそうです。

表題とは関係ない話ですが、昔、上記の例のとおり DataGrid コントロールの HyperLinkColumn に設定するにはどうしたらいいか悩んだこともありました(特に onclick 属性の設定)。

調べてみると、HyperLinkColumn の中にできるのは HyperLink オブジェクトなので、DataGrid の ItemDataBound イベントのハンドラで HyperLink を探して、Attributes["onclick"] に無理やり window.open を設定した記憶があります。

そんな面倒なことをしなくても、ItemTemplate に HyperLink コントロールを配置すれば簡単にできたのに・・・いろいろと未熟だったなぁ。まぁ、今でもそうですけど。(苦笑)

Tags:

ASP.NET

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年5月  >>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

View posts in large calendar