2010/04/24

EOS KISS X2の内蔵ストロボと、EF 50mm F1.4 USMレンズで撮る、夕焼けの中の桜




夕焼けの中、桜を撮影しました。
前回は、完全なシルエットで撮影した写真を掲載させて頂きましたが、今回は、あえてシルエットは狙わずに、EOS KISS X2の内蔵ストロボを桜にパチッと当ててみました。

レンズはもちろん題名通りEF 50mm F1.4 USM。
撮影モードは全ていつも通りマニュアルです。

場所はなんてことのない通り道でしたが、とても惹きつけられました・・・。

EF 50mm F1.4 USMで撮る、夕焼けシルエットの桜と雨の中の桜




夕焼けの中、桜を完全なシルエットで撮影してみました。
カメラはEOS KISS X2。レンズはEF 50mm F1.4 USM。
撮影モードは全てマニュアル。

それと、雨の日に撮影した桜も掲載させて頂きます。
雨の日独特の、拡散した空気感を出そうとして、あえて絞り開放F/1.4に設定しました。

少しづつ桜の写真が撮れて嬉しい。あと、色々な事を考える・・・





待望の桜の季節到来。少しづつですが桜の写真も撮れて来て、ほんと嬉しい。
一枚、我が家のテーブルの上にて、開花し始めた蘭の写真も掲載させて頂きます。

でもまだ寒くて辛いですねぇ・・・。
春の陽気が欲しい。
今回は写真見ながら、色々な事を、つらつらと考えてみる回にさせて下さい。


■カメラについて考える■

EOS 7D欲しいけど、今年の桜の季節は、もう完全に手持ちのEOS KISS X2だけで行きます。
もしも、桜の季節が終わってなお欲しい気持が弱まらなければ、その時こそって思う。
こんだけ引っ張って、まだあきらめてないカメラは生まれて初めて。

■パソコンについて考える■

いよいよIntel Core i3やCore i5搭載ノートが一気に出てきたけれど、まだ大型サイズばっかり。
Aspire 1410クラスは音沙汰なしで焦れったいかも。
ノートPCの進化も良いけれど、五月に日本でも発売開始される予定のiPadの成り行き次第で、まだ所有した事のないスタイルのマシン・・・Windows 7搭載タブレットPCに興味が移ってしまうかも。

■ゲーム機について考える■

Xbox360が人気ゲームソフト2本付き2万9800円版が出るみたい。ゲーム性能では、PS3よりも遥かに優れているのは魅力。
ただ、個人的に、PS3も含めてもう据え置きのゲーム機全般に興味が湧いて来ないのが悲しい。やはりプレイする場所と時間を拘束されるやつは、もういらないかなぁ。

もはや携帯機じゃないとだめか。携帯機の課題の性能の低さだって、今世代からは相当に改善されそうでワクワクしてます。
世の中の大本命は押しも押されもせぬ「任天堂3DS」だけれど、個人的にはソニーのPSP2(仮)にもまだまだ期待中。
もちろん、ソフト互換性問題始め、尽きることの無い配点を持つマシンだけど、純粋にPSPの性能がアップするだけでも良しとせねば。
いや、実は劣化ポイントを痛烈に抱えていたりするんじゃないかというオチがあるかも。しかしそりゃ。

世界を席巻しつつあるっぽいスマートフォン勢は、どうか。
iPhone 4G(仮)や、Windows Phone7など大物ぞろい。ただし、ハードもシステムも強力だけれど、どっちも電話会社との契約が必要だから、その点では微妙感あり。単体でゲーム機として発売されないものかな。無理か。

■クルマについて考える■

クルマをマシンとして考えると、パジェロミニやスポーツカーは最高だけれど、動く部屋としてとらえると、やはりワゴン好きな人の気持も分かる・・・。
電気自動車は、どうだろ。軽では、トルク不足が完璧に解消する素晴らしいメリットはあるけど、充電がどう考えても現実的じゃない。旅行とかは、実質的にはあと三年くらいはまだ不可能なのでは。
ガソリンスタンドに充電設備義務付けとか、地デジなみに力技を繰り出さないと厳しいかなぁ。

個人的に問題なのが、オートマチック嫌い(暇臭いから)な点をどうにかしないと、選べる車種が限りなく狭まる点。
でも、マニュアル操作って、楽しいだけじゃなくて、実は頭と体を結構使っているのです。
それらを一気にやめたら相当な反動が身体的に来るはずで、かなり怖いというのもある・・・

■地デジレコーダーについて■

ブルーレイレコーダーは、まだ高くて決定版が無いなぁという印象。
PS3だとtorneセットが4万2000円くらいだからいざとなったらこれかなぁと思っていたけれど、ここまで来たらば、もっとずっとずっと色々出来るマシンでやってみたい気持が強くなった。
ぶっちゃけ、HDMI端子装備のCULVノートパソコンで何とかレコーダー代わりにならないかなぁ・・・と考え中。
Core i3搭載CULVノートが出たら、一段階ブレイクしそうなんだけれど。

現状、手持ちのAspire 1410でなんとか地デジレコーダー化ならないかと思って調べてみると、性能は未知数ながら、かなりそれらしい周辺機器が発売されていました。

モバイルにぴったりのUSB地デジチューナー。ワンセグと地デジ同時録画で、ワンセグをPSPにムーブ可能!! そういうのでいいんだよー。

バッファローのポータブル・ブルーレイドライブ!!
読むだけのPS3と違って、ちゃんと書き込みも可能。ただしまだちょっとお高い。

安定性や性能が心配だけれど、かなり惹かれますねー。

この件は後日、単独記事を書かせていただくかも知れないです。

2010/04/23

SQL-Server 2008 Expressで、時間の計算を便利にしてみる(2)




前回の記事に引き続いて、SQL-Server 2008 Expressで、時間の計算を便利にしてみるの第二回目です。

前回は、"時間:分"文字列を分に換算した数値にすることによって、時間の計算を電卓感覚で便利にしてしまう(願いをこめた)関数SQLCLR_T()を作りました。

今回は、そのSQLCLR_T()で得られる分に換算した数値の結果を、"時間:分"の文字列に変換する関数SQLCLR_TFormat()を作ってみます。
また、前回作ったSQLCLR_T()から、繰り返し計算回数のパラメータを取り外し、シンプルに書けるようにしてみました。

確かにまだまだオールマイティに対応できはしませんが、まず、このSQLCLR_T()と、SQLCLR_TFormat()の二つの組み合わせで、勤怠とかの計算は電卓感覚で便利に出来るかなぁと。

SQLCLRの登録などは過去の記事をご参考になさって下さい。

■実行例■

--前回作ったSQL_CLR_T関数から、繰り返し計算パラメータ取り外しました!

SELECT
dbo.SQLCLR_T('01:00') +
dbo.SQLCLR_T('00:15') * 10 AS [01:00 + 00:15を10回の計算結果]

SELECT
dbo.SQLCLR_TFormat(
dbo.SQLCLR_T('01:00') +
dbo.SQLCLR_T('00:15') * 10) AS [01:00 + 00:15を10回の計算結果を時間:分文字列に変換]


■コード■
(インデントは消えております)
(無償版のVisual C# 2008でプログラムを書けます)
(全角の<と>は、半角に読み替えて下 さい)

//*******************************************************************************
// * ローカル関数
//*******************************************************************************
//------------------------------------
//TimeSpan用の日時分配列作成
//前回のSQLCLR_T()の時と同じ関数です。
//------------------------------------
private static Int32[] CreateTimeSpanSource(
Int32 p_day,
Int32 p_hour,
Int32 p_minute
)
{
//結果格納エリア
Int32[] intArr_result = new Int32[3];

try
{
//値の格納
intArr_result[0] = p_day; //日
intArr_result[1] = p_hour; //時
intArr_result[2] = p_minute; //分

//分の時間への繰上げ計算
intArr_result[1] = intArr_result[1]+
(Int32)Math.Floor((Double)intArr_result[2]/(Double)60);
//分の調整計算
intArr_result[2] = intArr_result[2] -
(Int32)Math.Floor((Double)intArr_result[2]/(Double)60)*60;
//時間の日への繰上げ計算
intArr_result[0] = intArr_result[0] +
(Int32)Math.Floor((Double)intArr_result[1] / (Double)24);
//時間の調整計算
intArr_result[1] = intArr_result[1] -
(Int32)Math.Floor((Double)intArr_result[1] / (Double)24) * 24;
}
catch (System.Exception obj_err)
{
throw obj_err;
}

return intArr_result;
}

//*******************************************************************************
//* SQL関数
//*******************************************************************************
//------------------------------------
//分に換算した数値を時間:分形式に変換する
//------------------------------------
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString SQLCLR_TFormat(
SqlInt32 p_value
)
{
//結果格納エリア
string str_result = "";
//日時分計算配列
Int32[] intArr_ts = new Int32[3];
//時間基礎エリア
TimeSpan obj_base;
try
{
//自作関数CreateTimeSpanSource()を利用して、日時分計算配列作成
intArr_ts = CreateTimeSpanSource(
0,
0,
(Int32)p_value
);
//時間基礎エリア作成
obj_base = new TimeSpan(
intArr_ts[0],
intArr_ts[1],
intArr_ts[2],
0
);
//結果エリア作成(時間:分形式)
str_result =
(obj_base.Days * 24 + obj_base.Hours).ToString() + ":" +
obj_base.Minutes.ToString("00");
}
catch (System.Exception obj_err)
{
throw obj_err;
}
return (SqlString)str_result;
}

//(前回の修正版です)
//------------------------------------
//日.時間:分文字列を分に変換する関数
//------------------------------------
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlInt32 SQLCLR_T(
SqlString p_value
)
{
//入力値作業エリア
string str_value;
//結果格納エリア
Int32 int_result = 0;
//インデックス
Int32 i;
//チェック用書式1
Regex obj_rx1 = new Regex(@"^\d{1,4}\.\d{1,4}:\d{1,4}$");
//チェック用書式2
Regex obj_rx2 = new Regex(@"^\d{1,4}:\d{1,4}$");
//チェック用書式3
Regex obj_rx3 = new Regex(@"^\d+$");
//時間基礎エリア
TimeSpan obj_base;
//時間結果エリア
char[] charArr_c = new char[2]{'.',':'};
//日時分文字列格納配列
string[] strArr_ts = new string[3];
//日時分計算配列
Int32[] intArr_ts;

try
{
str_value = (string)p_value;
//書式チェック
if (!(obj_rx1.IsMatch(str_value)))
{
if (obj_rx2.IsMatch(str_value))
{ //書式2にマッチした場合は、日要素を補完して先に進む。
str_value = "0." + str_value;
}
else if (obj_rx3.IsMatch(str_value))
{ //書式3にマッチした場合は、日.時間要素を補完して先に進む。
str_value = "0.0:" + str_value;
}
else
{ //全書式アンマッチならエラー
throw new System.Exception("書式エラー。日(最大4桁).時間(最大4桁):分(最大4桁)でお願いします。");
}
}

//入力値を日時分配列に分解して格納
strArr_ts = str_value.Split(charArr_c);
//日時分配列の内容を自作関数CreateTimeSpanSource()で調整計算し、計算配列にセット
intArr_ts = CreateTimeSpanSource(
Int32.Parse(strArr_ts[0]),
Int32.Parse(strArr_ts[1]),
Int32.Parse(strArr_ts[2])
);

//時間基礎エリアにセット
obj_base = new TimeSpan(
intArr_ts[0],
intArr_ts[1],
intArr_ts[2],
0
);

//結果を分に換算して取得
int_result = (Int32)obj_base.TotalMinutes;

}
catch (System.Exception obj_err)
{
throw obj_err;
}

return (SqlInt32)int_result;
}


■SQL-Server関数■
(環境はご自分のものに読み替えお願いいたします)

-- *******************************************************
-- SQLCLRの関数インターフェース
-- *******************************************************
-- ----------------------------------------------
-- 分の数字を"時間:分"文字列に変換する。
-- (パラメータ説明)
-- @p_value :分の数値(整数)
-- ----------------------------------------------
create function SQLCLR_TFormat(
@p_value int
)
RETURNS nvarchar(14)
AS EXTERNAL NAME ASSEMBLY_SQLCLR.CLS_SQLCLR.SQLCLR_TFormat;
GO

--前回の修正版です。
-- ----------------------------------------------
-- 時間文字列を分に換算する
-- (パラメータ説明)
-- @p_value :"日.時間:分"
-- もしくは、"時間:分。"
-- ただし、各要素は数値最大4桁
-- @p_magnification:繰り返し計算数
-- ----------------------------------------------
create function SQLCLR_T(
@p_value nvarchar(14)
)
RETURNS int
AS EXTERNAL NAME ASSEMBLY_SQLCLR.CLS_SQLCLR.SQLCLR_T;
GO


SQL-Server 2008 Expressで、時間の計算を便利にしてみる(1)




今回の記事は、SQL-Server 2008 Expressで、時間の計算を便利にしてみようという特集の第一回目です。

時間の計算を電卓感覚で便利にしようというのは、以前、Windows Power Shellでやってみた事なのですが、あのノリをSQL-Server 2008にも持ち込めないかなと考えました。

しかし、Windows Power Shellと違って、SQL-Server 2008には、TimeSpan型に該当する型が存在していないため、C#言語でプログラムしたところで、直接は結果として返せないのです。

そこで、ちょっと悩んだのですが今回はこうしました。
まずは勤怠の計算とかに使うのが主目的と考え、時間:分の文字列をパラメータとして渡したら、結果はTimeSpanにこだわらず、シンプルに分に換算した数値で返してしまう関数をSQLCLR作ろうかなと。

たとえば、文字列で"01:00"と入力すれば、これは一時間だと判断して60と返す関数を作る。
"01:00" + "08:15"みたいな、時間:分文字列での計算も、分に換算しているから可能になるなぁと。
結果も分に換算した数値で出てくるけど、これは後々変換します。

あと、同じ時間を10回とか繰り返すのに備えて、繰り返し計算の回数パラメータも用意したんですが、結果は分に換算して返されるわけですから、単純に*10とか*20とか計算すれば良いだけだから、特に必要はなかったかも。コードの練習として今回はこのまま行きます。

SQLCLRの登録などについては、過去の記事をご参考になさって下さい。

■実行例■

SELECT dbo.SQLCLR_T('48:30',1) AS [48:30の結果];
SELECT dbo.SQLCLR_T('00:120',1) AS [00:120の結果];
SELECT dbo.SQLCLR_T('08:00',10) AS [08:00を10回の結果];

SELECT
dbo.SQLCLR_T('01:00',1) +
dbo.SQLCLR_T('00:15',10) AS [01:00 + 00:15を10回の計算結果]

■コード■
(インデントは消えております)
(無償版のVisual C# 2008でプログラムを書けます)
(全角の<と>は、半角に読み替えて下さい)
//*******************************************************************************
// * ローカル関数
//*******************************************************************************
//------------------------------------
//TimeSpan用の日時分配列作成
//このローカル関数は今後も使い回します
//------------------------------------
private static Int32[] CreateTimeSpanSource(
Int32 p_day,
Int32 p_hour,
Int32 p_minute
)
{
//結果格納エリア
Int32[] intArr_result = new Int32[3];

try
{
//値の格納
intArr_result[0] = p_day; //日
intArr_result[1] = p_hour; //時
intArr_result[2] = p_minute; //分

//分の時間への繰上げ計算
intArr_result[1] = intArr_result[1]+
(Int32)Math.Floor((Double)intArr_result[2]/(Double)60);
//分の調整計算
intArr_result[2] = intArr_result[2] -
(Int32)Math.Floor((Double)intArr_result[2]/(Double)60)*60;
//時間の日への繰上げ計算
intArr_result[0] = intArr_result[0] +
(Int32)Math.Floor((Double)intArr_result[1] / (Double)24);
//時間の調整計算
intArr_result[1] = intArr_result[1] -
(Int32)Math.Floor((Double)intArr_result[1] / (Double)24) * 24;
}
catch (System.Exception obj_err)
{
throw obj_err;
}

return intArr_result;
}

//*******************************************************************************
//* SQL関数
//*******************************************************************************
//------------------------------------
//日.時間:分文字列を分に変換する関数
//------------------------------------
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlInt32 SQLCLR_T(
SqlString p_value,
Int32 p_magnification
)
{
//入力値作業エリア
string str_value;
//結果格納エリア
Int32 int_result = 0;
//インデックス
Int32 i;
//チェック用書式1
Regex obj_rx1 = new Regex(@"^\d{1,4}\.\d{1,4}:\d{1,4}$");
//チェック用書式2
Regex obj_rx2 = new Regex(@"^\d{1,4}:\d{1,4}$");
//チェック用書式3
Regex obj_rx3 = new Regex(@"^\d+$");
//時間基礎エリア
TimeSpan obj_base;
//時間結果エリア
TimeSpan obj_result = new TimeSpan(0, 0, 0, 0);
//日時分文字列分解用キャラクタ配列
char[] charArr_c = new char[2]{'.',':'};
//日時分文字列格納配列
string[] strArr_ts = new string[3];
//日時分計算配列
Int32[] intArr_ts;

try
{
str_value = (string)p_value;
//書式チェック
if (!(obj_rx1.IsMatch(str_value)))
{
if (obj_rx2.IsMatch(str_value))
{ //書式2にマッチした場合は、日要素を補完して先に進む。
str_value = "0." + str_value;
}
else if (obj_rx3.IsMatch(str_value))
{ //書式3にマッチした場合は、日.時間要素を補完して先に進む。
str_value = "0.0:" + str_value;
}
else
{ //全書式アンマッチならエラー
throw new System.Exception("書式エラー。日(最大4桁).時間(最大4桁):分(最大4桁)でお願いします。");
}
}

//入力値を日時分配列に分解して格納
strArr_ts = str_value.Split(charArr_c);
//日時分配列の内容を自作関数CreateTimeSpanSource()で調整計算し、計算配列にセット
intArr_ts = CreateTimeSpanSource(
Int32.Parse(strArr_ts[0]),
Int32.Parse(strArr_ts[1]),
Int32.Parse(strArr_ts[2])
);

//時間基礎エリアにセット
obj_base = new TimeSpan(
intArr_ts[0],
intArr_ts[1],
intArr_ts[2],
0
);

//時間結果エリアにセット(倍率計算機能付き)
//@@@@@@@@@@[LOOP-START]@@@@@@@@@@
for (i = 0; i < (Int32)p_magnification; i++)
{
obj_result = obj_result.Add(obj_base);
}
//@@@@@@@@@@[LOOP-END ]@@@@@@@@@@

//結果を分に換算して取得
int_result = (Int32)obj_result.TotalMinutes;

}
catch (System.Exception obj_err)
{
throw obj_err;
}

return (SqlInt32)int_result;
}




■SQL-Server関数■
(環境はご自分のものに読み替えお願いいたします。)

-- *******************************************************
-- SQLCLRの関数インターフェース
-- *******************************************************
-- ----------------------------------------------
-- 時間文字列を分に換算する
-- (パラメータ説明)
-- @p_value :"日.時間:分"
-- もしくは、"時間:分。"
-- ただし、各要素は数値最大4桁
-- @p_magnification:繰り返し計算数
-- ----------------------------------------------
create function SQLCLR_T(
@p_value nvarchar(14),
@p_magnification int
)
RETURNS int
AS EXTERNAL NAME ASSEMBLY_SQLCLR.CLS_SQLCLR.SQLCLR_T;
GO

2010/04/22

SQL-Server 2008 Expressで、正規表現を使ってマッチした文字列を抜き出す関数を作ってみる




今回の記事も、SQL-Server 2008 Expressの正規表現について書かせていただきたいと思います。
前回までは、正規表現パターンで条件を検索する関数SQLCLR_Regex()、正規表現パターンで文字列をリプレース(置換)するSQLCLR_RegexReplace()を作りました。

今回は、正規表現パターンで一体どの文字列がマッチしたのか?を実際に抜き出す関数を作ります。
これは、SQLCLR_RegexSelect()という名前にしてみます。

元々SQL-Serverに備わっているlikeもそうなんですが、条件がマッチしたのは良いけれど、実際にマッチした文字列をそのまま抜き出して利用したい・・・というところまでは出来ません。
今回の関数を使えば、それが可能になります。

ただ、正規表現の書き方によっては、もちろん複数の文字列がマッチすることもあります。
どんな形で結果を得られるようにすれば良いか悩んだのですが、CSV形式の文字列で結果が得られるようにしてみました。

SQLCLRの登録などは過去の記事を参考になさって下さい。

■使用例■

--ゲーム名テーブル#T_BASEにおいて、
--ゲーム名に「冒険」か「伝説」か「物語」がつくものを抽出
--
--※条件はSQL_Regex()を使っています。
SELECT
GAME_NAME AS [元のゲーム名],
dbo.SQLCLR_RegexSelect(GAME_NAME,'.*(冒険|伝説|物語)') AS [マッチした文字列]
FROM #T_GAME
WHERE dbo.SQLCLR_Regex(GAME_NAME,'.*(冒険|伝説|物語)') = 1;


--ゲーム名に、アルファベットが付くゲームのアルファベットを抽出
SELECT
GAME_NAME AS [元のゲーム名],
dbo.SQLCLR_RegexSelect(GAME_NAME,'[a-zA-Z]') AS [マッチした文字列]
FROM #T_GAME
WHERE dbo.SQLCLR_Regex(GAME_NAME,'[a-zA-Z]') = 1;


■コード■
(インデントが消えています)
(無償版のVisual C# 2008でプログラムを書けます)
(不等号記号は全角で記述していますが実際は半角です)

//*******************************************************************************
// * ローカル関数
// * SQLCLR_RegexReplaceと共通で使います。
//*******************************************************************************
//------------------------------------
//正規表現で取得したパターンをList<>で返却
//p_value:検査したい文字列
//p_pat :正規表現パターン
//------------------------------------
private static List<string> GetMatchList(
string p_value,
string p_pat
)
{
//結果格納エリア
List<string> list_str_result = new List<string>();
//正規表現コア
Regex obj_rx;
//正規表現マッチコレクション
MatchCollection col_match;
//正規表現マッチ結果格納配列
string[] strArr_match;
//比較エリア
string str_comp_match = "";
//インデックス
Int32 i;

try
{
obj_rx = new Regex(p_pat);

col_match = obj_rx.Matches(p_value);

if (col_match.Count > 0)
{
//配列要素数決定
strArr_match = new string[col_match.Count];
//取得したマッチ文字列を配列に格納
//@@@@@@@@@@[LOOP-START]@@@@@@@@@@
for (i = 0; i < col_match.Count; i++)
{
strArr_match[i] = col_match[i].Value;
}
//@@@@@@@@@@[LOOP-END ]@@@@@@@@@@

//配列をソート
Array.Sort(strArr_match);

//@@@@@@@@@@[LOOP-START]@@@@@@@@@@
for (i = 0; i < strArr_match.Length; i++)
{
//マッチ文字列のうち、重複していない文字列だけを結果にセット
if (!(str_comp_match.Equals(strArr_match[i])))
{
list_str_result.Add(strArr_match[i]);
str_comp_match = strArr_match[i];
}
}
//@@@@@@@@@@[LOOP-END ]@@@@@@@@@@
}

}
catch (System.Exception obj_err)
{
throw obj_err;
}

return list_str_result;
}


//*******************************************************************************
//* SQL関数
//*******************************************************************************
//------------------------------------
//正規表現による文字列抜き出し
//------------------------------------
//using System.Text.RegularExpressions;を記述して下さい。
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString SQLCLR_RegexSelect(
SqlString p_value,
SqlString p_pat
)
{
//書式チェック用
Regex obj_rx = new Regex(@"^.*"".*$");
//マッチ結果取得エリア
List<string> list_str_value = new List<string>();
//結果格納エリア
string str_result = "";
//インデックス
Int32 i;

try
{
//SQL-ServerからNULLが来ない時に処理する。
if (!(p_value.Equals(SqlString.Null)))
{
//書式チェック
if(obj_rx.IsMatch((string)p_pat))
{
throw new System.Exception("ダブルクォーテーションが含まれた文字列は処理できません。");
}

//自作関数GetMatchListで正規表現にマッチした文字列をList<>で取得
list_str_value = GetMatchList((string)p_value, (string)p_pat);

//マッチした文字列分をCSV形式で組み立てる
//@@@@@@@@@@[LOOP-START]@@@@@@@@@@
for (i = 0; i < list_str_value.Count; i++)
{
str_result += "\"" + list_str_value[i] + "\"" + ",";
}
//@@@@@@@@@@[LOOP-END ]@@@@@@@@@@
str_result = str_result.Substring(0, str_result.Length - 1);
}
}
catch (System.Exception obj_err)
{ //例外が発生したらSQL-Serverに投げつけて強制終了させる。
throw obj_err;
}

return (SqlString)str_result;
}


■SQL-Server関数インターフェース■
(ご自分の環境に読み替えお願いいたします。)

-- ----------------------------------------------
-- 正規表現による文字列抜き出し
-- (パラメータ説明)
-- @p_value:判定したい文字列
-- @p_pat:正規表現パターン
-- ----------------------------------------------
create function SQLCLR_RegexSelect(
@p_value nvarchar(max),
@p_pat nvarchar(max)
)
RETURNS nvarchar(max)
AS EXTERNAL NAME ASSEMBLY_SQLCLR.CLS_SQLCLR.SQLCLR_RegexSelect;
GO


それにつけても、C#言語の応用範囲は本当に広いですよね・・・。

2010/04/21

SQL-Server 2008 Expressで、正規表現を使って文字列をリプレース(置換)する関数を作ってみる




今回の記事は、SQL-Server 2008 Expressにおいて、正規表現を使って文字列をリプレース(置換)する関数を、SQLCLRで作ってみます。

前回の記事では、元々SQL-Serverに備わっている文字列検索用のlikeの代わりに、正規表現で文字列パターンを判定してデータを抽出するSQLCLR_Regex()という関数を作りました。

しかし、likeの時もそうなんですが、データが抽出できるのは良いのですが、その先が問題です。
たとえば、抽出したデータを他の文字列でリプレース(置換)したいというのは結構ありがちだと思うのですが、これがまたやっかいだと思います。

そこで、それを実現する関数をSQLCLRで作ってみます。
今回の関数名は、SQLCLR_RegexReplace()としてみます。

ちなみに、処理の一部をローカル関数にしていますが、他の処理でも使いたいので共通化の意味でばらしました。

SQLCLRの登録などは過去の記事をご参考になさって下さい

■実行例■

--ゲーム名テーブル#T_BASEにおいて、
--ゲーム名の末尾に「伝説」か「物語」のどちらかがつくものを抽出し、
--「伝説」と「物語」を「○」でリプレースする。
--
--※条件はSQL_Regex()を使っています。

SELECT
GAME_NAME AS [元のゲーム名],
dbo.SQLCLR_RegexReplace(GAME_NAME,'○','(伝説|物語)$') AS [リプレース後のゲーム名]
FROM #T_GAME
WHERE dbo.SQLCLR_Regex(GAME_NAME,'(伝説|物語)$') = 1;


■コード■
(インデントは消えています)
(無償版のVisual C# 2008でプログラムを書けます)
(全角の<と>は、半角に読み替えて下さい)

//*******************************************************************************
// * ローカル関数
// * SQLCLR_RegexSelectと共通で使います。
//*******************************************************************************
//------------------------------------
//正規表現で取得したパターンをList<>で返却
//p_value:検査したい文字列
//p_pat :正規表現パターン
//------------------------------------
private static List<string> GetMatchList(
string p_value,
string p_pat
)
{
//結果格納エリア
List<string> list_str_result = new List<string>();
//正規表現コア
Regex obj_rx;
//正規表現マッチコレクション
MatchCollection col_match;
//正規表現マッチ結果格納配列
string[] strArr_match;
//比較エリア
string str_comp_match = "";
//インデックス
Int32 i;

try
{
obj_rx = new Regex(p_pat);

col_match = obj_rx.Matches(p_value);

if (col_match.Count > 0)
{
//配列要素数決定
strArr_match = new string[col_match.Count];
//取得したマッチ文字列を配列に格納
//@@@@@@@@@@[LOOP-START]@@@@@@@@@@
for (i = 0; i < col_match.Count; i++)
{
strArr_match[i] = col_match[i].Value;
}
//@@@@@@@@@@[LOOP-END ]@@@@@@@@@@

//配列をソート
Array.Sort(strArr_match);

//@@@@@@@@@@[LOOP-START]@@@@@@@@@@
for (i = 0; i < strArr_match.Length; i++)
{
//マッチ文字列のうち、重複していない文字列だけを結果にセット
if (!(str_comp_match.Equals(strArr_match[i])))
{
list_str_result.Add(strArr_match[i]);
str_comp_match = strArr_match[i];
}
}
//@@@@@@@@@@[LOOP-END ]@@@@@@@@@@
}

}
catch (System.Exception obj_err)
{
throw obj_err;
}

return list_str_result;
}


//*******************************************************************************
//* SQL関数
//*******************************************************************************
//------------------------------------
//正規表現による文字列リプレース
//------------------------------------
//using System.Text.RegularExpressions;を記述して下さい。
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString SQLCLR_RegexReplace(
SqlString p_value,
SqlString p_replace,
SqlString p_pat
)
{
//マッチ結果取得エリア
List<string> list_str_value = new List<string>();
//結果格納エリア
string str_result = "";
//置き換えエリア
string str_replace;
//インデックス
Int32 i;
try
{
//SQL-ServerからNULLが来ない時に処理する。
if (!(p_value.Equals(SqlString.Null)))
{
str_result = (string)p_value;
str_replace = (string)p_replace;
//自作関数GetMatchListで正規表現にマッチした文字列をList<>で取得
list_str_value = GetMatchList(str_result, (string)p_pat);

//マッチした文字列分をリプレースする。
//@@@@@@@@@@[LOOP-START]@@@@@@@@@@
for (i = 0; i < list_str_value.Count; i++)
{
str_result = str_result.Replace(list_str_value[i], str_replace);
}
//@@@@@@@@@@[LOOP-END ]@@@@@@@@@@
}
}
catch (System.Exception obj_err)
{ //例外が発生したらSQL-Serverに投げつけて強制終了させる。
throw obj_err;
}

return (SqlString)str_result;
}

■SQL-Server 2008 Express側のインターフェース■
(環境はご自分のものに読み替えお願いします。)

-- ----------------------------------------------
-- 正規表現による文字列リプレース
-- (パラメータ説明)
-- @p_value:判定したい文字列
-- @p_replace:リプレースしたい文字列
-- @p_pat:リプレースするための正規表現パターン
-- ----------------------------------------------
create function SQLCLR_RegexReplace(
@p_value nvarchar(max),
@p_replace nvarchar(max),
@p_pat nvarchar(max)
)
RETURNS nvarchar(max)
AS EXTERNAL NAME ASSEMBLY_SQLCLR.CLS_SQLCLR.SQLCLR_RegexReplace;
GO


SQL-Server 2008 Expressで、正規表現で文字列のパターン判定をする関数をSQLCLRで作ってみる(2)




今回の記事は、先日書かせていただいた、「SQL-Server 2008 Expressで、正規表現で文字列のパターン判定をする関数をSQLCLRで作ってみる」の続編です。

前回は、SQL-Server 2008 Expressにおいて、正規表現を使った文字列検索をする関数を作りましたが、nullのデータが入ってくるとエラーになってしまいます。
それを回避するバージョンを作ってみました。

正規表現をlikeと同じ使い勝手で利用できるようになると、仕事でもプライベートでも、とにかく分析作業などは段違いに効率が良くなります。
また、SQL-Serverならではといいましょうが、条件を複数に書き分けて、肯定と否定を織り交ぜた複雑な条件もさくさく書く事が出来るわけです。

正規表現は、本当に強力です。

■使用例■

--先頭が数字で始まるゲーム名。
--しかし、末尾は数字では終わらない。


SELECT
GAME_NAME
FROM #T_GAME
WHERE dbo.SQLCLR_Regex(GAME_NAME,'^\d+') = 1 --肯定と
AND dbo.SQLCLR_Regex(GAME_NAME,'\d+$') = 0 --否定の組み合わせ


■コード■
(インデントは消えています)
(無償版のVisual C# 2008でプログラムを書けます)

//------------------------------------
//正規表現による文字列パターン判定
//------------------------------------
//using System.Text.RegularExpressions;を記述して下さい。
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlBoolean SQLCLR_Regex(
SqlString p_value,
SqlString p_pat
)
{
//正規表現
Regex obj_rx;
//結果格納エリア
SqlBoolean Qbol_result = false;
try
{
//SQL-ServerからNULLが来ない時に処理する。
if (!(p_value.Equals(SqlString.Null)))
{
obj_rx = new Regex((string)p_pat);
if (obj_rx.IsMatch((string)p_value))
{
Qbol_result = true;
}
}
}
catch (System.Exception obj_err)
{ //例外が発生したらSQL-Serverに投げつけて強制停止する。
throw obj_err;
}

return Qbol_result;
}

春の雪の中に咲く桜。EF-S 17-85mm F4-5.6 IS USMレンズで撮る。






先週の週末は、まさかの春なのに大雪。気温もしゃれにならず、真冬に逆戻りするというおかしな天候になりましたね。

その朝に撮影した、仙台市内の桜です。
この日は、この後、福島県に旅行に行ったのですが、悪天候のためにレンズは一本だけしか持ち出しませんでした。キヤノン純正の万能型ズームレンズEF-S 17-85mm F4-5.6 IS USMです。

カメラはEOS KISS X2。撮影モードはいつものように全てマニュアルモードです。

なるべく雪が画角に入るような構図で撮影してみました。
しかしこのレンズ、確かに単焦点レンズと比べると描写力に劣る部分は多々あれど、複数の焦点距離をすぐに交換できるズームの良さを堪能できますね。

この時は、17mm、70mm、85mmの三焦点で撮影してみましたが、レンズ交換が難しい悪天候の中では特にありがたい。
リングを回して目盛りを合わせるだけでレンズ交換に等しいわけですから、撮影時間もかなり短縮になってたりします。

ボケ味は、どうだろ。うーん。ちょっとゴワゴワしているかなぁ。でも、このレンズには、いつもいざという時に助けられているのでありがたい存在。

SQL-Server 2008 Expressで、正規表現で文字列のパターン判定をする関数をSQLCLRで作ってみる



今回の記事は、SQL-Server 2008 Expressにおいて、正規表現を使って文字列のパターン判定をする関数をSQLCLRで作ってみます。

SQL-Serverにおいて文字列のパターン判定を行う場合は、「like」を使うのですが、これはごく簡単なパターンしか扱えない上に、同時に複数のパターンを記述すると、SQL文が極めて複雑になりがちで、結構涙目になる事って多いんじゃないかと思います。

そこで、SQLCLR_Regex()という関数を作り、正規表現そのものをダイレクトで使えるようにしようと思います。コードは極めて簡単で、正規表現を実現するクラス「Regex」を利用するだけ。
SQLCLRの恩恵ですね。
ヒットすればbit型で1、しなければ0が返るようにします。これで判定可能です。

たとえば、こんな感じです。
「日時の書式で、日.時間:分という形になってるかどうかチェック。ただし、日、時間、分の要素はそれぞれ数値1桁から4桁まであること」
こんなのはlikeではとても書ききれませんが、正規表現ならば、「^\d{1,4}\.\d{1,4}:\d{1,4}$」というように書く事が可能です。(\は¥記号)

SELECT dbo.SQLCLR_Regex('1.08:15','^\d{1,4}\.\d{1,4}:\d{1,4}$')
これはOKなので1が返ります。

SQLCLRの登録については過去の記事をご参考になさって下さい。

■コード■
(無償版のVisual C# 2008でプログラムを書けます)
(ブログではインデントが消えております)


//------------------------------------
//正規表現
//------------------------------------
//using System.Text.RegularExpressions;を記述して下さい。
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlBoolean SQLCLR_Regex(
SqlString p_value,
SqlString p_pat
)
{
//正規表現
Regex obj_rx;
//結果格納エリア
SqlBoolean Qbol_result = true;

try
{
obj_rx = new Regex((string)p_pat);
if (!(obj_rx.IsMatch((string)p_value)))
{
Qbol_result = false;
}
}
catch (System.Exception obj_err)
{ //例外が発生したらSQL-Serverに投げつけて強制停止する。
throw obj_err;
}

return Qbol_result;
}


■SQL-Server 2008 Express側の関数インターフェース記述■
(環境はご自分に合わせて読み替えて下さいませ)

-- *******************************************************
-- SQLCLRの関数インターフェース
-- *******************************************************
-- ----------------------------------------------
-- 正規表現による条件判定
-- (パラメータ説明)
-- @p_value:判定したい文字列

-- @p_pat:正規表現パターン
-- ----------------------------------------------
create function SQLCLR_Regex(
@p_value nvarchar(max),
@p_pat nvarchar(max)
) RETURNS bit
AS EXTERNAL NAME ASSEMBLY_SQLCLR.CLS_SQLCLR.SQLCLR_Regex;

ちなみに、マイクロソフトによると、Regexの読みは「レジェックス」か「レグエクス」どっちでも好きな方で良いとのことです。

2010/04/20

Windows Phone 7に期待

先日正式発表されたWindows Phone 7ですが、ゲームプラットフォームとしても、相当期待が出来そうです。

Xbox360のファミリーとみなされ、XNA Framework上での開発が可能!!

配信は有料であり、勝手アプリは不可能なのが残念ですが、一般ユーザーに開発の道を開いているのは素晴らしい。

配信は無理でも、Windows 7 PCなどで動作するプログラミングを勉強できるメリットはあります。無償版の開発環境もあり、当ブログでも過去に簡単なプログラムを記述してみる記事を書かせていただいておりました。かように、開発者の裾野を広げようというマイクロソフトの熱意と努力には頭が下がります。

Windows Phone 7は、800x480ドットという高い解像度でのフル3Dゲームデモを行っており、同じ方向へ進むであろうソニーPSP2への牽制にもなっている感があります。

しかし、PSP2は厳しい状況かも知れませんね。

任天堂3DSは言うに及ばず、新型iPhoneや、Windows Phone7など、強力なライバルが続々とその姿を現そうとしています。PSP2は、期待されるスペックや部材の大半を、すでにライバルに先出しされている状態になっており、よほどのサプライズが無ければ・・・。

2010/04/18

SQL-Server 2008 Expressで、数値の桁数を求める関数をSQLCLRで作る



今回の記事は、SQL-Server 2008 Expressにおいて、数値の桁数を求める関数をSQLCLRで作ってみます。

123という数値ならば3桁、141000ならば6桁と求まるようにする関数です。
こういうのは、あれこれ悩まずにもうC#言語(SQLCLR)でさくっと作ってしまうのが早道かなぁと想います。


SQLCLRの登録については過去の記事をご参考になさって下さい。


■プログラムコード(インデントが消えています)
(無償版のVisual C# 2008 Expressで書く事が出来ます。)
(環境に依存する箇所は、ご自分の環境に合わせて読んで下さい。)

//------------------------------------ //数値の桁数 //------------------------------------ [Microsoft.SqlServer.Server.SqlFunction]
public static SqlInt32 SQLCLR_Digits(

SqlDouble p_value

)
{
Int32 int_result = 0;
try {
int_result = (Int32)((Double)p_value).ToString().Length;
}

catch (System.Exception obj_err)
{ //例外が発生したらSQL-Serverに投げつけて強制終了させる。
throw obj_err;
}
return (SqlInt32)int_result;
}


■SQL関数によるラッピング
(環境に依存する箇所は、ご自分の環境に合わせて読んで下さい。)

-- ----------------------------------------------
-- 数値の桁数を求める -- (パラメータ説明)
-- @p_value:数値

-- ----------------------------------------------

create function SQLCLR_Digits( @p_value float )
RETURNS int
AS EXTERNAL NAME ASSEMBLY_SQLCLR.CLS_SQLCLR.SQLCLR_Digits;
GO

HDR-XR500Vで撮る、生まれて初めて!!春の雪の「花見山」









季節外れの春の雪。気温も何もかも真冬に逆戻りの一日でしたが、前々から予定していた旅行はドタキャンできず、出掛けてきました。

福島県の「夜の森公園」や「花見山」に旅行に行ってみますと、災い転じて福となすと言ったら変ですけれど、生まれて初めて雪の中に桜咲く光景を見ることが出来て幸運この上なし、だったかも知れません。

一眼レフで写真撮影もして来ましたけれど、今回の記事では、写真ではなくて、ハイビジョンカメラHDR-XR500Vで撮影した映像から印象的なシーンを掲載させて頂きます。

しかし、毎回毎回恐縮ですけれど、このHDR-XR500Vの素晴らしさといったら何でしょう。
ホワイトバランスだけは手動ですが、その他はフルオートで実に満足な結果が得られます。
撮影者の「仕事」は、おおむね、人様のジャマにならぬ位置で、ベストだと思う構図を考える事に集中できます。

それにつけても、小型カメラでこれだけの映像が撮影できる時代というのは、本当に大変なことだなぁと。
職業で映像をお客様に納品する義務を背負わないアマチュアに限って言えば、もはや大型のハイビジョンカメラは買わなくて良いと言い切れるのかも知れない。
むしろ、これ以上の映像は、キヤノンのEOSムービーとかに行くべきであろうか?

それと、最近の必殺技、プラズマテレビTH-P37X1で視聴すると、例によってとてつもなく美しく、またまたまた大騒ぎです。
立体感や色の美しさが真に迫っていて、このテレビにおいては、映像というよりも、窓から現実の景色を肉眼で観光しているかのようなのです。

適度な映像の丸めが起こるハーフHDのプラズマテレビというのは、映像の圧縮ノイズの心配もいらぬ事だし、実のところ、現世代のハイビジョンテレビとしては、これがベストだと思わせられますね。

※今回掲載させていただいた映像は、1枚目が「夜の森公園」。降雪がピークで、掛け値なしに真冬の状態と化しております。その他は全て「花見山」で、この時点では雪はやんでおりました。

2010/04/17

春の雪の中、旅行に出ました

全く予想外の春の雪。でも前々から予定があったので旅行に出ました。
私も連れも、気分の乗りがいまひとつ悪い・・・。
でも、雪と桜の組み合わせが見られるかもって前向きに行こう。

悪天候なんで、レンズはズームのEF-S 17-85mm F4-5.6 IS USM一本だけ。
花の季節の旅行にズームだけって、初めてかも知れない。EF 100mm F2.8Lよ、留守番すまぬ。

旅行のメモは、W-ZERO3に入っているExcelでバッチリ。
メモ系は色々試しましたが、Excelが一番ですね。
ソートとかも一発だし。電話にExcelが入っている幸せ。

困った季節はずれの雪を、EF 50mm F1.8 IIレンズで撮る







今日は旅行だぞっと張り切って目を覚ましたら、なんと積雪しているではないですか。
クルマ夏タイヤに交換したばっかりなのに、涙目とはまさにこのこと。

でも、嘆いていてもしょうがないので、EOS KISS X2に、EF 50mm F1.8 IIレンズを装着して、写真撮ってきました。

撮影モードは全てマニュアル。

X2と、EF 50mm F1.8 IIのコンビは、システムがとても小さくまとまるので、傘をさしただけでもカメラに雪がかかる心配が少なくて大丈夫でした。

しかし寒い。春だからと甘く見て素手で出たら、途中で指が動かなくなってしまいました。
親指AFボタン(*ボタン)と、絞りボタンの指の移動さえ、辛かった。

2010/04/15

SQL-Server 2008 ExpressのMERGEクエリーの便利さに感動。2つのテーブルを1つにマージする!!





今回の記事は、SQL-Server 2008 (Express)における、MERGEクエリーについて書かせて頂きたいと思います。

古いバージョンであるSQL-Server 2000では、二つのテーブルを一つに併合(マージ)したいなぁと思ったら、INSERT文とUPDATE文に分けて処理する必要がありました。

SQL-Server 2008 (Express)からは、ついに一文で書く事が出来るMERGE文が誕生しました。
たとえば、#T_TABLE1と#T_TABLE2という2つのテーブルがあったとして、#T_TABLE2の内容を#T_TABLE1に併合するためには、従来は以下のように書く必要がありました。

-- --------------------------
-- テストで使ったテーブル
-- --------------------------
CREATE TABLE #T_TABLE1
(
ITEM_CD int,
ITEM_NM nvarchar(40),
SURYO int,
CONSTRAINT T_TABLE1_MAIN_KEY Primary Key (ITEM_CD)
);

CREATE TABLE #T_TABLE2
(
ITEM_CD int,
ITEM_NM nvarchar(40),
SURYO int,
CONSTRAINT T_TABLE2_MAIN_MAIN_KEY Primary Key (ITEM_CD)
);

INSERT INTO #T_TABLE1
(ITEM_CD,ITEM_NM,SURYO)
VALUES(111111,'TEST-1',100),(222222,'TEST-2',200),(444444,'TEST-4',400),(777777,'TEST-7',700);

INSERT INTO #T_TABLE2
(ITEM_CD,ITEM_NM,SURYO)
VALUES(111111,'TEST-1',1),(333333,'TEST-3',3),(555555,'TEST-5',5),(666666,'TEST-6',6);

-- ----------------------
-- MERGE文が無かった場合
-- ----------------------
--重複したデータは更新
UPDATE M
SET
M.SURYO = T.SURYO
FROM #T_TABLE1 AS M
INNER JOIN #T_TABLE2 AS T
ON(M.ITEM_CD = T.ITEM_CD)
WHERE M.SURYO <> T.SURYO;

--不一致データは挿入
INSERT INTO #T_TABLE1
(ITEM_CD,ITEM_NM,SURYO)
SELECT
M.ITEM_CD,
M.ITEM_NM,
M.SURYO
FROM #T_TABLE2 AS M
LEFT JOIN #T_TABLE1 AS T
ON(M.ITEM_CD = T.ITEM_CD)
WHERE T.ITEM_CD IS NULL;

-- ----------------------
-- MERGE文
-- ----------------------
MERGE #T_TABLE1 AS M
USING #T_TABLE2 AS T
ON(M.ITEM_CD = T.ITEM_CD)
WHEN MATCHED THEN
UPDATE
SET
M.SURYO = T.SURYO
WHEN NOT MATCHED THEN
INSERT (ITEM_CD,ITEM_NM,SURYO)
VALUES(T.ITEM_CD,T.ITEM_NM,T.SURYO);


MERGE文であれば、こんなに短く書く事が出来るんです。
ちなみに、INSERT文やUPDATE文などは、文末にセミコロン(;)が無くともエラーにならないのですが、新しく誕生したMERGE文は文末にセミコロンが無いと容赦なくエラーになりますので注意が必要です。

それと、このMERGE文は、ただマージしてくれるだけでも便利で助かるのですけれど、さらにその先があります。
なんと、どういう挙動をしたのかログを書く事が出来るんです。
どのデータをUPDATEして、どれをINSERTしたんだ、というのが一発で分かるわけです。
ログのテーブルは自分で自由に設計できるので、使いやすいようにしておけるのも魅力。

-- -----------------------------
-- ログ用テーブルの定義
-- -----------------------------
CREATE TABLE #T_LOG
(
SEQ int IDENTITY(0,1),
MERGE_DT datetime2,
MERGE_KEY int,
MERGE_ACTION nvarchar(6),
CONSTRAINT T_LOG_MAIN_KEY Primary Key (SEQ)
);
-- ----------------------
-- MERGE文
-- ----------------------
MERGE #T_TABLE1 AS M
USING #T_TABLE2 AS T
ON(M.ITEM_CD = T.ITEM_CD)
WHEN MATCHED THEN
UPDATE
SET
M.SURYO = T.SURYO
WHEN NOT MATCHED THEN
INSERT (ITEM_CD,ITEM_NM,SURYO)
VALUES(T.ITEM_CD,T.ITEM_NM,T.SURYO)
OUTPUT
SYSDATETIME() AS "MERGE_DT",
INSERTED.ITEM_CD AS "MERGE_ITEM", --DELETED.ITEM_CDだと更新したキーのみ抽出できます
$action AS "MERGE_ACTION"
INTO #T_LOG;


$actionという変数を参照すると、UPDATEされたのか、INSERTされたのかを知る事が出来ます。
同じ処理を作りこもうとすると、やはりそれなりのコードが必要ですから、MERGE文の便利さが身に染みる瞬間です。

会社では、まだSQL-Server 2000なのが辛い・・・。
企業用のすごいバージョンなんですけど、書けるクエリーが無償版の2008 Expressに全然負けるし、SQLCLRも使えないしなぁ・・・。でも頑張るぞ。