ソースファイルに、ヘッダコメントを残すルールになっていてリリースファイルの際バージョンがチェックされるんだけど、今回これが不正だった。
で、見てみると、
/*
Ver.01.00 20090701 担当者A 新規作成
Ver.01.01 20090805 担当者B ○○対応
Ver.01.02 20090813 私の名前 ○×対応
Ver.01.03 20090908 私の名前 ○×対応
Ver.01.03 20090913 私の名前 ○×対応
*/
で、今回01.03でバージョンがあがっていない変更ソースファイルがあるというエラー。
そもそも、私は、01.02しか触っていないのに・・・。他の担当者がヘッダをコピペして内容を変えいないままとなってる。
名前も修正内容もコピペ。さらに今回のはバージョンも変更していないためエラーになっちゃった。
修正担当者がいなくなったので01.03と(01.04)の修正は何だったのかははわからず、リリースまで時間がなかったためソースコメントはそのままでリリース。
間違ったコメントよりもコメントが少ないほうがまだマシなので、バージョンと日付だけ残してあとは消してくれればよかったのに。。。
2009年9月19日土曜日
2009年9月15日火曜日
リンクサーバのトランザクション設定有効化ってどうやるんだったっけ?
SQL Server 2005でリモートサーバへ、DBリンクを張って、
select * from [リモートサーバ名].[データベース名].[スキーマ名].[テーブル名]
で、アクセスすることはできた。また、insert文
insert [テーブル名]
select * from [リモートサーバ名].[データベース名].[スキーマ名].[テーブル名]
で、リモートサーバにある同名のテーブル名をローカルにコピーすることもできた。
ただ、
begin tran
insert [テーブル名]
select * from [リモートサーバ名].[データベース名].[スキーマ名].[テーブル名]
とやると、エラーとなった。(エラーメッセージは覚えていないが、nliが、とかトランザクションがなんとかとかいうメッセージだった。)
たぶん、リモートサーバのMSDTCの設定の問題だと思うのだけれど、なんだろう?
まさかリンクサーバアクセスではトランザクション処理ができないってことはないとと思うんだけど。
select * from [リモートサーバ名].[データベース名].[スキーマ名].[テーブル名]
で、アクセスすることはできた。また、insert文
insert [テーブル名]
select * from [リモートサーバ名].[データベース名].[スキーマ名].[テーブル名]
で、リモートサーバにある同名のテーブル名をローカルにコピーすることもできた。
ただ、
begin tran
insert [テーブル名]
select * from [リモートサーバ名].[データベース名].[スキーマ名].[テーブル名]
とやると、エラーとなった。(エラーメッセージは覚えていないが、nliが、とかトランザクションがなんとかとかいうメッセージだった。)
たぶん、リモートサーバのMSDTCの設定の問題だと思うのだけれど、なんだろう?
まさかリンクサーバアクセスではトランザクション処理ができないってことはないとと思うんだけど。
2009年9月13日日曜日
バッチの作り
月末までに引き継がなきゃいけないものの1つに、C#で作られたバッチがあります。(バッチの部分については、実際に携わったのは1日ぐらいですが、他に知っている人がいないもので。。)
で、このバッチプログラムはメイン処理では、テンプレートメソッドっぽい作り、機能群では、ストラテジっぽい作りでした。テンプレートメソッドはis-a,継承とオーバーライドによる処理の変更、ストラテジはhas-a,インターフェースとコンポジションによる処理の変更の意味で話していますが、デザインパターンは使ったことがないのでデザインパターンの理解が間違っているかも。。。
で、後任がオブジェクト指向の言語に慣れていないとちょっと戸惑うかも。
非オブジェクト指向の言語では、静的解析でも、充分に追跡可能だけども、オブジェクト指向言語だと、静的解析では追跡不可能になってしまう。
具体的に言うと、非オブジェクト指向言語では、問題のプログラムの最初から、呼び出し先に移動→呼び出し元に戻るという操作を繰り返していけば、最後まで到達可能だけれど、オブジェクト指向言語で作られている場合、呼び出し先に移動したところでベースクラスのメソッドやインターフェースのメソッド宣言に移動してしまい、ベースクラスの処理の中で(サブクラスでオーバーライドする処理でも)、ベースクラスのメソッドに移動してしまう。静的解析の場合は、これが限界のような気がします。
トラブルが起きたときに、普通にピンポイントで見たり、流れを順に追っていくとつらいことになりそう。
スーパークラスの役割を理解しておかないと何をやっているかさっぱり分からなくなるからね。
だから、デザインパターンは私にとって使うメリットがさっぱり理解できないです。私はアンチオブジェクト指向派です。
さらにこのスーパークラスで、サブクラスから呼び出すメソッドがあったりして、間違ったデザインパターンの作りになっています。
(テンプレートメソッドでは、スーパークラスに処理の流れが書いてあって、処理の流れの一部、他と違う処理をする機能のメソッドだけをサブクラスでオーバーライドする形で作りこむんだけど、今回のはスーパークラスに何故かユーティリティクラスみたいな機能を追加しています。ユーティリティの機能については、継承関係は全くないので、保守時の混乱を取り除くために別途ユーティリティクラスを起こすべきなのに。。。)
・・・わたくし、コピペ万歳の人なので。。。でも、コピペの作法を間違っているプログラムの作りをしてあって、さらにコピペ処理を失敗しているのを見るともっといらいらしてしまうのだけれど。。。
コピペの作法について、
コピペって、極力変更しないで使うもので、コピー元のプログラムの作りに工夫しておかなきゃいけないのに、その辺の工夫を全くしていないと酷いことになってしまう。(さらに変更しなきゃいけなくなった部分で変更していなかったりしてね。)
で、このバッチプログラムはメイン処理では、テンプレートメソッドっぽい作り、機能群では、ストラテジっぽい作りでした。テンプレートメソッドはis-a,継承とオーバーライドによる処理の変更、ストラテジはhas-a,インターフェースとコンポジションによる処理の変更の意味で話していますが、デザインパターンは使ったことがないのでデザインパターンの理解が間違っているかも。。。
で、後任がオブジェクト指向の言語に慣れていないとちょっと戸惑うかも。
非オブジェクト指向の言語では、静的解析でも、充分に追跡可能だけども、オブジェクト指向言語だと、静的解析では追跡不可能になってしまう。
具体的に言うと、非オブジェクト指向言語では、問題のプログラムの最初から、呼び出し先に移動→呼び出し元に戻るという操作を繰り返していけば、最後まで到達可能だけれど、オブジェクト指向言語で作られている場合、呼び出し先に移動したところでベースクラスのメソッドやインターフェースのメソッド宣言に移動してしまい、ベースクラスの処理の中で(サブクラスでオーバーライドする処理でも)、ベースクラスのメソッドに移動してしまう。静的解析の場合は、これが限界のような気がします。
トラブルが起きたときに、普通にピンポイントで見たり、流れを順に追っていくとつらいことになりそう。
スーパークラスの役割を理解しておかないと何をやっているかさっぱり分からなくなるからね。
だから、デザインパターンは私にとって使うメリットがさっぱり理解できないです。私はアンチオブジェクト指向派です。
さらにこのスーパークラスで、サブクラスから呼び出すメソッドがあったりして、間違ったデザインパターンの作りになっています。
(テンプレートメソッドでは、スーパークラスに処理の流れが書いてあって、処理の流れの一部、他と違う処理をする機能のメソッドだけをサブクラスでオーバーライドする形で作りこむんだけど、今回のはスーパークラスに何故かユーティリティクラスみたいな機能を追加しています。ユーティリティの機能については、継承関係は全くないので、保守時の混乱を取り除くために別途ユーティリティクラスを起こすべきなのに。。。)
・・・わたくし、コピペ万歳の人なので。。。でも、コピペの作法を間違っているプログラムの作りをしてあって、さらにコピペ処理を失敗しているのを見るともっといらいらしてしまうのだけれど。。。
コピペの作法について、
コピペって、極力変更しないで使うもので、コピー元のプログラムの作りに工夫しておかなきゃいけないのに、その辺の工夫を全くしていないと酷いことになってしまう。(さらに変更しなきゃいけなくなった部分で変更していなかったりしてね。)
2009年9月11日金曜日
10月から別プロジェクトへ異動
今日上司に聞いたらそういうことらしい。
てっきり10月以降もいるものだと思っていろいろなものを引き継いだのに、すぐに引き継ぎをしなきゃいけないみたい。
でも、プロパーでそれなりに.netを知っている人がいなくなってしまうんだけどいいのかなぁ。。。
てっきり10月以降もいるものだと思っていろいろなものを引き継いだのに、すぐに引き継ぎをしなきゃいけないみたい。
でも、プロパーでそれなりに.netを知っている人がいなくなってしまうんだけどいいのかなぁ。。。
2009年9月8日火曜日
なんてこったい
昨日リリースしたバッチプログラムがおかしくなった。
ログからは、int64型の値をint32型の変数に格納できないとのメッセージが。
で、前回のソースファイルを見比べたら、~Designer.csの型が1箇所おかしい。前回リリースしたバージョンの~Designer.csでは、BigInt,Int64型のパラメータ引渡しになってるのに、今回のものはInt,Int32型になってた。
で、元となる~.xsdファイルでは、パラメタライズドクエリのパラメータの1つが、、、、Int32型になってた。
考えられるのは、~Designer.csファイルを手で修正したこと。
~Desinger.csは、VisualStudio2005が自動生成するファイルで、手で触っちゃいけないファイルなのです。また、~.xsdを更新すると~Designer.csが再生成されるのです。
で、今回~.xsdでSQL文をちょっと直したら、別のSQL文の方でで問題が発覚。しかもビルド時エラーじゃなく実行時エラーなので困ったものです。
あ~あ、前任者のトラップに引っかかっちゃった。
で、今回は、~.xsdの受け渡しパラメータを変更して、対応完了。
でも、なんだったんでしょうねぇ?
ログからは、int64型の値をint32型の変数に格納できないとのメッセージが。
で、前回のソースファイルを見比べたら、~Designer.csの型が1箇所おかしい。前回リリースしたバージョンの~Designer.csでは、BigInt,Int64型のパラメータ引渡しになってるのに、今回のものはInt,Int32型になってた。
で、元となる~.xsdファイルでは、パラメタライズドクエリのパラメータの1つが、、、、Int32型になってた。
考えられるのは、~Designer.csファイルを手で修正したこと。
~Desinger.csは、VisualStudio2005が自動生成するファイルで、手で触っちゃいけないファイルなのです。また、~.xsdを更新すると~Designer.csが再生成されるのです。
で、今回~.xsdでSQL文をちょっと直したら、別のSQL文の方でで問題が発覚。しかもビルド時エラーじゃなく実行時エラーなので困ったものです。
あ~あ、前任者のトラップに引っかかっちゃった。
で、今回は、~.xsdの受け渡しパラメータを変更して、対応完了。
でも、なんだったんでしょうねぇ?
2009年9月3日木曜日
久しぶりの更新。今回もSQL_20090906追記
今日はSQLのチューニングに終始してました。
こんなテーブルがあって、
受付(受付ID,受付日時,担当者ID,ステータス),担当者マスタ(担当者ID,担当者名)
受付日時の直近5か月前から未来まで一カ月毎の各ステータスの合計を出すっていうもの。
元のSQLを1時間調べてたんだけど、解釈内容に自信が持てず、全部作り直ししました。
FROM句に副々問い合わせ、SELECT句にも副問い合わせな感じで130行OVERのSQLだったので。。。
で、作り直した最終的なSQLは、こんな感じ(他の条件を全部はしょっているのだけれど。。)。共通テーブル式を使ってて、文字列加工をした列の値を2段目のselect文でgroupbyを掛けているので、たぶん内部では一時的にテーブルを作っているはず。なのでこの部分が改良の余地がありそうだけど。。
WITH 共通テーブル式 (受付月,担当者ID,担当者名,ステータス) AS
(select
substring(convert(varchar,受付日時,111),1,7),
受付.担当者ID,
担当者名,
ステータス
from 受付 left outer join 担当者マスタ
on 受付.担当者ID=担当者マスタ.担当者ID
where 受付日時 >=convert(datetime,substring(convert(varchar,dateadd(m,-5,getdate()),111),1,7)+'/01')
)
select
担当月,
担当者ID,
担当者名,
count(case when ステータス='1' then 担当月 end) as ステータス_1合計,
count(case when ステータス='2' then 担当月 end) as ステータス_2合計,
count(case when ステータス='3' then 担当月 end) as ステータス_3合計,
count(case when ステータス='4' then 担当月 end) as ステータス_4合計
from
共通テーブル式
group by 担当月,担当者ID, 担当者名
order by ....
ま、PIVOTは使っても使わなくても変わりなさそうだし、元は10分かかってたものが2秒になったので、これ以上はいいよね?
こんなものかな。
ついでに思い出せるだけ、昔のSQLを書いてみる。
確か、範囲内の全受付に対して、いちいち担当者毎に月のカウントを取ってdistinctをしていたはずだから、、、
select distinct
substring(convert(varchar,受付_O.受付日時,111),1,7) as 担当月,
受付_O.担当者ID,
担当者名,
(select count(受付_I.受付日時) from 受付 AS 受付_I
where 受付_I.受付日時 >=convert(datetime,substring(convert(varchar,dateadd(m,-5,getdate(),111),1,7)+'/01') and
受付_I.担当者ID=受付_O.担当者ID and 受付_I.ステータス='1' and
受付_I.受付日時 >=convert(datetime,substring(convert(varchar,受付_O.受付日時,111),1,7)+'/01') and
受付_I.受付日時 < convert(datetime,substring(convert(varchar,dateadd(m,1,受付_O.受付日時),111),1,7)+'/01') and
受付_I.ステータス= 受付_O.ステータス
) as ステータス_1合計,
(select count(受付_I.受付日時) from 受付 AS 受付_I
where 受付_I.受付日時 >= convert(datetime,substring(convert(varchar,dateadd(m,-5,getdate(),111),1,7)+'/01') and
受付_I.担当者ID=受付_O.担当者ID and 受付_I.ステータス='2' and
受付_I.受付日時 >=convert(datetime,substring(convert(varchar,受付_O.受付日時,111),1,7)+'/01') and
受付_I.受付日時 < convert(datetime,substring(convert(varchar,dateadd(m,1,受付_O.受付日時),111),1,7)+'/01') and
受付_I.ステータス= 受付_O.ステータス ) as ステータス_2合計,
(select count(受付_I.受付日時) from 受付 AS 受付_I
where 受付_I.受付日時 >= convert(datetime,substring(convert(varchar,dateadd(m,-5,getdate(),111),1,7)+'/01') and
受付_I.担当者ID=受付_O.担当者ID and 受付_I.ステータス='3' and
受付_I.受付日時 >= convert(datetime,substring(convert(varchar,受付_O.受付日時,111),1,7)+'/01') and
受付_I.受付日時 < convert(datetime,substring(convert(varchar,dateadd(m,1,受付_O.受付日時),111),1,7)+'/01') and
受付_I.ステータス= 受付_O.ステータス ) as ステータス_3合計,
(select count(受付_I.受付日時) from 受付 AS 受付_I
where 受付_I.受付日時 >= convert(datetime,substring(convert(varchar,dateadd(m,-5,getdate(),111),1,7)+'/01') and
受付_I.担当者ID=受付_O.担当者ID and 受付_I.ステータス='4' and
受付_I.受付日時 >= convert(datetime,substring(convert(varchar,受付_O.受付日時,111),1,7)+'/01') and
受付_I.受付日時 < convert(datetime,substring(convert(varchar,dateadd(m,1,受付_O.受付日時),111),1,7)+'/01') and
受付_I.ステータス= 受付_O.ステータス ) as ステータス_4合計
from 受付 as 受付_O left outer join 担当者マスタ
on 受付_O.担当者ID = 担当者マスタ.担当者ID and
受付_O.受付日時 >= convert(datetime,substring(convert(varchar,dateadd(m,-5,getdate(),111),1,7)+'/01')
集計するつもりのない、group byとか、distinctとか、union allと動きの異なるunionって、最終手段であって、他の方法が無いかを考えなくちゃ、だね。上の場合は、その月に同じ担当者で、ステータス1のデータが1000件あったら、1000回、同じカウントを行って、出力された同一行をdistinct処理してるってことですよね。なので、残り999回のカウントは不要ってことかい、ってなるはずなんだけど。。。
こんなテーブルがあって、
受付(受付ID,受付日時,担当者ID,ステータス),担当者マスタ(担当者ID,担当者名)
受付日時の直近5か月前から未来まで一カ月毎の各ステータスの合計を出すっていうもの。
元のSQLを1時間調べてたんだけど、解釈内容に自信が持てず、全部作り直ししました。
FROM句に副々問い合わせ、SELECT句にも副問い合わせな感じで130行OVERのSQLだったので。。。
で、作り直した最終的なSQLは、こんな感じ(他の条件を全部はしょっているのだけれど。。)。共通テーブル式を使ってて、文字列加工をした列の値を2段目のselect文でgroupbyを掛けているので、たぶん内部では一時的にテーブルを作っているはず。なのでこの部分が改良の余地がありそうだけど。。
WITH 共通テーブル式 (受付月,担当者ID,担当者名,ステータス) AS
(select
substring(convert(varchar,受付日時,111),1,7),
受付.担当者ID,
担当者名,
ステータス
from 受付 left outer join 担当者マスタ
on 受付.担当者ID=担当者マスタ.担当者ID
where 受付日時 >=convert(datetime,substring(convert(varchar,dateadd(m,-5,getdate()),111),1,7)+'/01')
)
select
担当月,
担当者ID,
担当者名,
count(case when ステータス='1' then 担当月 end) as ステータス_1合計,
count(case when ステータス='2' then 担当月 end) as ステータス_2合計,
count(case when ステータス='3' then 担当月 end) as ステータス_3合計,
count(case when ステータス='4' then 担当月 end) as ステータス_4合計
from
共通テーブル式
group by 担当月,担当者ID, 担当者名
order by ....
ま、PIVOTは使っても使わなくても変わりなさそうだし、元は10分かかってたものが2秒になったので、これ以上はいいよね?
こんなものかな。
ついでに思い出せるだけ、昔のSQLを書いてみる。
確か、範囲内の全受付に対して、いちいち担当者毎に月のカウントを取ってdistinctをしていたはずだから、、、
select distinct
substring(convert(varchar,受付_O.受付日時,111),1,7) as 担当月,
受付_O.担当者ID,
担当者名,
(select count(受付_I.受付日時) from 受付 AS 受付_I
where 受付_I.受付日時 >=convert(datetime,substring(convert(varchar,dateadd(m,-5,getdate(),111),1,7)+'/01') and
受付_I.担当者ID=受付_O.担当者ID and 受付_I.ステータス='1' and
受付_I.受付日時 >=convert(datetime,substring(convert(varchar,受付_O.受付日時,111),1,7)+'/01') and
受付_I.受付日時 < convert(datetime,substring(convert(varchar,dateadd(m,1,受付_O.受付日時),111),1,7)+'/01') and
受付_I.ステータス= 受付_O.ステータス
) as ステータス_1合計,
(select count(受付_I.受付日時) from 受付 AS 受付_I
where 受付_I.受付日時 >= convert(datetime,substring(convert(varchar,dateadd(m,-5,getdate(),111),1,7)+'/01') and
受付_I.担当者ID=受付_O.担当者ID and 受付_I.ステータス='2' and
受付_I.受付日時 >=convert(datetime,substring(convert(varchar,受付_O.受付日時,111),1,7)+'/01') and
受付_I.受付日時 < convert(datetime,substring(convert(varchar,dateadd(m,1,受付_O.受付日時),111),1,7)+'/01') and
受付_I.ステータス= 受付_O.ステータス ) as ステータス_2合計,
(select count(受付_I.受付日時) from 受付 AS 受付_I
where 受付_I.受付日時 >= convert(datetime,substring(convert(varchar,dateadd(m,-5,getdate(),111),1,7)+'/01') and
受付_I.担当者ID=受付_O.担当者ID and 受付_I.ステータス='3' and
受付_I.受付日時 >= convert(datetime,substring(convert(varchar,受付_O.受付日時,111),1,7)+'/01') and
受付_I.受付日時 < convert(datetime,substring(convert(varchar,dateadd(m,1,受付_O.受付日時),111),1,7)+'/01') and
受付_I.ステータス= 受付_O.ステータス ) as ステータス_3合計,
(select count(受付_I.受付日時) from 受付 AS 受付_I
where 受付_I.受付日時 >= convert(datetime,substring(convert(varchar,dateadd(m,-5,getdate(),111),1,7)+'/01') and
受付_I.担当者ID=受付_O.担当者ID and 受付_I.ステータス='4' and
受付_I.受付日時 >= convert(datetime,substring(convert(varchar,受付_O.受付日時,111),1,7)+'/01') and
受付_I.受付日時 < convert(datetime,substring(convert(varchar,dateadd(m,1,受付_O.受付日時),111),1,7)+'/01') and
受付_I.ステータス= 受付_O.ステータス ) as ステータス_4合計
from 受付 as 受付_O left outer join 担当者マスタ
on 受付_O.担当者ID = 担当者マスタ.担当者ID and
受付_O.受付日時 >= convert(datetime,substring(convert(varchar,dateadd(m,-5,getdate(),111),1,7)+'/01')
集計するつもりのない、group byとか、distinctとか、union allと動きの異なるunionって、最終手段であって、他の方法が無いかを考えなくちゃ、だね。上の場合は、その月に同じ担当者で、ステータス1のデータが1000件あったら、1000回、同じカウントを行って、出力された同一行をdistinct処理してるってことですよね。なので、残り999回のカウントは不要ってことかい、ってなるはずなんだけど。。。
2009年8月1日土曜日
SQL Server Developpers Edition
アマゾンでみると、2005、2008とも5千円~6千円で買えるのか。。。
Evaluation Editionをダウンロードするのが億劫なので、勉強用に買ってみてもいいのかな?
Evaluation Editionをダウンロードするのが億劫なので、勉強用に買ってみてもいいのかな?
登録:
投稿 (Atom)