SQL Serverで考える機会があったため、エントリー。
SQL Serverではストアドプロシージャを使用した複数レコードのファイル出力はコマンドレベルでサポートされていない。
sqlcmdを使用して出力できるのはPRINT文やメッセージ、あるいはSELECT文での結果の出力に限定される。
だがこれだと1レコード毎に処理しつつファイル出力できない。
カーソルを使用して処理を行い、正常処理されたレコードのみ出力するにはどうするか?
そんな時はファイル出力用のテーブルを用意しよう。
ストアドプロシージャで正常処理された結果のみそのテーブルに追加し、その後sqlcmdでselect文でファイル出力すれば良い。
処理中エラーが発生した時はエラーコードをかえしたり、エラーメッセージを返すストアドプロシージャを作成すればなお良い。
2010-04-11
SQLで複雑な条件で絞り込み
SQLで以下の問題を考えてみたのでメモ。
お題:人ごとに最高点のレコードのみ抽出する。最高点が複数あるときは受験日の最新のレコード1件のみとする。
ALL句でも同じことができる。でもそれ以上の条件をつけられない。
まず、人ごとの最高点で最新の日付項目で絞り込み。
それをキーとして使用して全フィールドを表示する。
できた!
お題:人ごとに最高点のレコードのみ抽出する。最高点が複数あるときは受験日の最新のレコード1件のみとする。
-- create table
create table record (
user_id varchar(8) not null,
record_date date not null,
score integer not null,
note text,
primary key (user_id, record_date));
-- 人ごとの最高点のみだが、同点の場合複数表示(max使用)
select * from record a
where score = (select max(score) from record b
where b.user_id = a.user_id);
ALL句でも同じことができる。でもそれ以上の条件をつけられない。
-- 人ごとの最高点のみだが、同点の場合複数表示(all句使用)
select * from record a
where score >= all(select score from record b
where b.user_id = a.user_id);
まず、人ごとの最高点で最新の日付項目で絞り込み。
select user_id,score,max(record_date) from record a
where (user_id,score) in (
select user_id,max(score) from record b group by user_id) group by user_id,score;
それをキーとして使用して全フィールドを表示する。
select * from record c
where (user_id,record_date) in
(select user_id,max(record_date) from record a
where (user_id,score) in (
select user_id,max(score) from record b group by user_id) group by user_id,score);
できた!
2010-03-08
Tomcat6.xでのマルチレベルコンテキストの設定
マルチレベルコンテキストとは以下のようなもの
ディレクトリ階層を深く指定したWeb Application。
フォルダの配置は以下の様にする。
warファイルの場合
コンテキストファイル(context.xml)は以下の様なファイル名とする。
コンテキストファイルの中身のパスは階層フォルダ構成で記載する。
親階層、子階層でWebApplicationを構成することも可能。
/parent/child1/
/parent/child2/
ディレクトリ階層を深く指定したWeb Application。
フォルダの配置は以下の様にする。
webapps/parent#child1/
webapps/parent#child2/
warファイルの場合
webapps/parent#child1.war
webapps/parent#child2.war
コンテキストファイル(context.xml)は以下の様なファイル名とする。
conf/Catalina/localhost/parent#child1.xml
conf/Catalina/localhost/parent#child2.xml
コンテキストファイルの中身のパスは階層フォルダ構成で記載する。
path="/parent/child1"
親階層、子階層でWebApplicationを構成することも可能。
webapps/parent#child/
webapps/parent/
conf/Catalina/localhost/parent#child.xml
conf/Catalina/localhost/parent.xml
2009-08-15
MySQLでリモート接続および日本語設定
Ubuntu(8.04, VMWare)でMySQLを立ち上げてホストOS側からアクセスできるようにしてみた。また日本語を扱う方法についてメモ。
/etc/mysql/my.cnf
あとはmysql再起動でOK
sudo /etc/init.d/mysql restart
参照:http://h50146.www5.hp.com/products/software/oe/linux/summary/reference/pdfs/mysql-50-japanese-v10.pdf
/etc/mysql/my.cnf
[mysqld]
...
#bind-address=127.0.0.1 (ローカルからのみとなっているのでコメントした)
...
character_set_server=utf8 (サーバー設定をUTF8にするように追加)
...
[mysql]
default-character-set=utf8 (コマンドラインをUTF8にするように追加)
...
あとはmysql再起動でOK
sudo /etc/init.d/mysql restart
参照:http://h50146.www5.hp.com/products/software/oe/linux/summary/reference/pdfs/mysql-50-japanese-v10.pdf
2009-07-27
SAStrutsでエラーメッセージを設定してエラー画面に遷移する方法 2
前回のSAStrutsでエラーメッセージを設定してエラー画面に遷移する方法だと記述量が多いので扱いにくい。
static importや可変長パラメータを使用して書きやすくしてみた。
ユーティリティクラス
使用クラスメソッド(ここではアクションクラスのメソッド)
static importや可変長パラメータを使用して書きやすくしてみた。
ユーティリティクラス
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
public class AppUtil {
public static ActionMessages getErrors(String msgKey, String ...args) {
ActionMessages errors = new ActionMessages();
errors.add(ActionMessages.GLOBAL_MESSAGE,
new ActionMessage(msgKey, args));
return errors;
}
}使用クラスメソッド(ここではアクションクラスのメソッド)
import static org.seasar.struts.util.ActionMessagesUtil.*;
import static org.seasar.struts.util.MessageResourcesUtil.*;
import org.seasar.struts.util.RequestUtil;
import static sample.AppUtil.*;
・・・
Integer id;
try {
id = Integer.parseInt(form.id);
} catch(NumberFormatException e) {
addErrors(RequestUtil.getRequest(),
getErrors("errors.integer", getMessage("labels.workstyleId")));
return "/error/";
}
・・・
2009-07-26
SAStrutsで時間の条件チェック
開始時間と終了時間の条件チェックを行う。
Validwhenで挑戦してみたが、できなかったのでメソッドを作成。
ミソは終了時間の最大を00:00としているところ。
画面表示時に24:00に書きかえる。
Validwhenで挑戦してみたが、できなかったのでメソッドを作成。
ミソは終了時間の最大を00:00としているところ。
画面表示時に24:00に書きかえる。
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.seasar.framework.beans.converter.TimeConverter;
public ActionMessages validate() {
ActionMessages errors = new ActionMessages();
if (!endTime.equals("00:00")) {
TimeConverter timeConverter = new TimeConverter("HH:mm");
java.sql.Time startTimeValue
= (java.sql.Time) timeConverter.getAsObject(startTime);
java.sql.Time endTimeValue
= (java.sql.Time) timeConverter.getAsObject(endTime);
if (!startTimeValue.before(endTimeValue)) {
errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
"errors.startTimeBeforeEndTime"));
}
}
return errors;
}
2009-07-20
s2jdbcでタイプセーフなクエリを実現。たとえば外部参照データで条件指定。
エンティティクラスを作成しておけば、s2jdbc-genでエンティティ参照用の*Namesクラスを自動作成できる。
target=gen-ddl(default)
これを使用して文字列に頼らず、タイプセーフなクエリを作成できる。
使用するNamesクラスをstatic importする。
これはXxxServiceでは、対応するXxxNamesがよい。
where句を構成するため、Operationsクラスもstatic importする。
結合したテーブルの情報を条件にしたいときはinnerJoin等でまず結合する。
関連が1対多で多側を参照するときはinnerJoin(viewGroupList())などとする。
(1側ならinnerJoin(dept())などになる。)
多側のIDで絞り込みたいなら以下のようにする。
.where(viewGroupList().id(), viewId))
ポイントはDeptNames内のviewGroupList()を使用するってことだろう。
以下作成したサンプル
target=gen-ddl(default)
これを使用して文字列に頼らず、タイプセーフなクエリを作成できる。
使用するNamesクラスをstatic importする。
これはXxxServiceでは、対応するXxxNamesがよい。
where句を構成するため、Operationsクラスもstatic importする。
結合したテーブルの情報を条件にしたいときはinnerJoin等でまず結合する。
関連が1対多で多側を参照するときはinnerJoin(viewGroupList())などとする。
(1側ならinnerJoin(dept())などになる。)
多側のIDで絞り込みたいなら以下のようにする。
.where(viewGroupList().id(), viewId))
ポイントはDeptNames内のviewGroupList()を使用するってことだろう。
以下作成したサンプル
import static org.seasar.extension.jdbc.operation.Operations.*;
import static sastrutsSample.entity.DeptNames.*;
import sastrutsSample.entity.Dept;
public class DeptService extends AbstractService {
public List findByViewId(String viewId) {
return jdbcManager.from(Dept.class).innerJoin(viewGroupList())
.where(eq(viewGroupList().id(), viewId))
.getResultList();
}
}
登録:
投稿 (Atom)