以下は、評価エンジンテーブルからの更新された保険料で毎月支払われた保険証券レコードを更新するためにvb.netで何ができるのかを示す擬似コードです。しかし、私はこれをSQL Serverデータベースのストアドプロシージャ内で実行できる必要があります。私が知る限り、2つのカーソル、外側のループ用と内側のループ用のカーソルを使用する必要があります。私の問題は、内側のカーソルを埋めるSQLクエリを構築するためには、Transact SQLの構文について十分な知識がないということです。ここでは擬似コードです:私は2つのカーソルを作成するよりも、これを行うには良い方法があると確信してvb.netで使用しているレコードセットのネストループをトランザクションSQLでどのようにレプリケートしますか?
Dim rsouter as ADODB.Recordset = New ADODB.Recordset
Dim rsinner as ADODB.Recordset = New ADODB.Recordset
Dim strSQL as string
Dim Paycol as string
‘ first of all open a recordset to get the records for updating
Rsouter.open(Select area, [payment method], suminsured, scpremium from tblpolicy where [payment method] = ‘monthly’), CurrentProject.Connection
‘ then loop through this outer recordset
Do while not rsouter.eof
‘ set the Paycol variable value to being a column name concatenated from the string “SC” and the value of the field “suminsured” from the open recordset, e.g. "SC12000"
Paycol = ‘SC’ & rsouter.fields(‘suminsured’).value
‘ now build the string to create the inner recordset
strSQL = ‘Select area, ‘ & Paycol & ‘ as sc from re where area = ‘ & rsouter.fields(‘area’).value
' the string should read something like; "select area, sc12000 from re where area = 5"
‘ open the inner recordset against the query string
Rsinner.open(strSQL), CurrentProject.Connection
‘ update the outer recordset premium field with the value from the inner recordset
Rsouter.fields(‘scpremium’).value = rsinner.fields(‘sc’).value
‘ close the inner recordset
Rsinner.close
‘ commit the change to the outer recordset
rsouter.update()
‘ move to the next record in the outer recordset
If not rsouter.eof then rsouter.movenext()
loop
‘ close the outer recordset
rsouter.close()
が、私のSQLは助けなしでそれを行うことができるのに十分強力ではありません。
YADS、あなたの答えのための
多くのおかげで、それは私が持っている問題を解決するための長い道のりを行きます。残念ながら、私の問題は私の元の要求で書いた擬似コードよりも少し複雑です。実際には、内側のカーソルから複数の値を取得して外側のカーソルに戻す必要があります。私は毎年のプレミアム、毎月のプレミアム、2週間ごとのプレミアム、週ごとのプレミアム、およびデビットプレミアムをreテーブルから取得し、それらのすべてを使用して外側のカーソルのポリシーテーブルレコードの対応するフィールドを更新する必要があります。あなたのコードが新しいプロシージャを作成し、カラム名と領域の一部を渡していることを理解しています。プロシージャを実行すると、渡された列の値が戻され、ポリシー表のその列の値を更新するために使用されます。
私は私が読むためにEXECステートメントを変更することができると思います:
EXEC ('select ' & @premiumColName & ' from re where re.area = ''' & @area & ''')
私はその後、何度EXEC
ステートメントを実行しますが、異なるカラム名にそれぞれの時間を渡すことができます。その後、各プレミアム列を順番に更新するために、SET
ステートメントを繰り返し実行する必要があります。
だから、私の次の質問は、これらは以下のとおりです。
- 私はGetPremium手順に私の外にカーソルがループするたびに作成およびドロップする必要がありますか?
- 更新ステートメントは更新するレコードをどのように知っていますか、または一致する領域を持つテーブルの(外部カーソルではなく)すべてのレコードを更新しますか?
- GetPremiumで要求されている列の内容を検証して、値をゼロに戻してから外側のカーソルのプレミアム列を更新する方法を確認するにはどうすればよいですか?
ダミアン、
私はあなたの助けのために非常に感謝しています。残念ながら私は他の誰かのVB6プログラムをVB.NETに変換しています。これを行う過程で、データストレージを設計した元のプログラマーは、元の6つのAccessデータベースを1つのSQL Serverデータベースに連結することに決めました。そうすることで、彼はいくつかのテーブルを再設計し、オリジナルの年次プレミアム、月額プレミアム、2週間ごとのプレミアム、週ごとのプレミアム、および口座引き落としプレミアムテーブルを、すべての列を別々に追加して1つのテーブルに連結しました。したがって、すべての年間プレミアム列は、プレフィックス 'AC'を持つ新しい評価エンジンテーブルに追加されます。すべての2週間のプレミアム列には接頭辞「FC」が付いています。私は彼が外部ソフトウェア供給者であり、プログラムとそのデータ構造に対する知的財産権を所有しているので、これがどのように機能するかを変えることはできません。私ができることは、可能な限りアドバイスし、VB.NET自身のスピードを上げず、当社の製品が必要なので、VBコード変換作業を引き受けます。
現在の非常に遅い更新プロセスのスピードアップを試みる方法として、私はVBプログラムのフォームを置き換えるストアドプロシージャを作成しようと努力してきました。これは現在、別々のデータベース、レートの変更については、ポリシーテーブルの既存のレコード(データベースの「コア」テーブルと呼ばれます)に適用されます。これは非常に非効率的であるだけでなく、月の最初の日にプログラムを開く最初の人は誰でも、コードを実行する前に更新フォームが待つ(時には数時間かかる)ことを意味します。さらに、誰も更新プロセスの実行中に何もできません。私は毎月1日に一晩実行するようにスケジュールすることができるようにストアドプロシージャを設定し、ポリシーを行くと、すべての既存の賃金にプレミアムの変更を適用するつもりこれを置き換えるために
。うまくいけば、これは、プログラムを使用して作業を行うことができる前に終日待機することを意味し、更新プロセス中に意図しない人の介入を防ぐことを意味します。
これまでのところ、2つのストアドプロシージャがあります。最初のものは 'UpdateAll'と呼ばれ、更新が必要なポリシーのみを使用して一時テーブルを埋めるためのコードが含まれています。現在、合計約103,000件のうち約6000件が更新されています。このテーブルは、次に、カーソルを埋めるように照会され、各レコードについて、収集された列の値を変数に入れる。私は、接頭辞 'AC'、 'FC'などをsuminsured列の値に連結し、結果の文字列を変数に代入することができます。だから、例えば、必要な年間プレミアム列を構築するためのコードは次のとおりです。私は今YADSが早く送らGetPremiumストアドプロシージャを少し変更したバージョンを呼び出すことができます行わこれにより
set @ansum = 'AC' + ltrim(str(@suminsured))
。これは出力変数を満たします。この変数は '@ansumval'という変数です。それを呼び出すためのコードは次のとおりです。
EXECUTE dbo.GetPremium @ansum, @area, @ansumval
私はカーソルを閉じた後など、毎月、隔週、毎週政策、プレミアムの情報を更新するために、他の列ごとにこれを繰り返します。私はその後、tmpcore2テーブルに6000かそこらのレコードを新しいカーソル、およびループを開き、証明書なしにマッチしたレコードを更新するために、それぞれのいずれかを使用することができます。コアテーブル内(certno)とtmpcore2レコードのマッチング列からの値で、必要な列を更新します。この後、私はカーソルを閉じ、すべてが完了します。
これはテーブル結合を行うほど効率的ではありませんが、列名を動的に作成することができますし、更新値をチェックして正しい値を上書きしないようにすることもできます支払額はゼロです。各カーソルの作業ビットの簡略リストは以下の通りである。
open cursor1
select * from tmpcore2 order by area
Fetch Next From Cursor1 into @area, @HA, @cert, @status, @paymeth, @suminsured, @anprem, @monprem, @fortprem, @dprem, @wprem
While @@Fetch_status = 0
Begin
set @ansum = 'AC' + ltrim(str(@suminsured))
set @mnsum = 'SC' + ltrim(str(@suminsured))
set @ftsum = 'FN' + ltrim(str(@suminsured))
set @dsum = 'DD' + ltrim(str(@suminsured))
set @wksum = 'WK' + ltrim(str(@suminsured))
EXECUTE GetPremium @ansum, @area, @ansumval
EXECUTE GetPremium @mnsum, @area, @mnsumval
EXECUTE GetPremium @ftsum, @area, @ftsumval
EXECUTE GetPremium @wksum, @area, @dsumval
EXECUTE GetPremium @dsum, @area, @wksumval
if @ansumval > 0 UPDATE tmpcore2 SET [Annual premium] = @ansumval
if @mnsumval > 0 UPDATE tmpcore2 SET [Monthly premium] = @mnsumval
if @ftsumval > 0 UPDATE tmpcore2 SET [Fortnightly premium] = @ftsumval
if @dsumval > 0 UPDATE tmpcore2 SET dpremium = @dsumval
if @wksumval > 0 UPDATE tmpcore2 SET wpremium = @wksumval
-- loop through until all records updated
close cursor1
open cursor2
select * from tmpcore2 order by certno
Fetch Next From Cursor2 into @area, @HA, @cert, @status, @paymeth, @suminsured, @anprem, @monprem, @fortprem, @dprem, @wprem
While @@Fetch_status = 0
Begin
Update core
SET [annual premium] = @anprem,
[monthly premium] = @monprem,
[fortnightly premium] = @fortprem,
dpremium = @dprem,
wpremium = @wprem
WHERE certno = @cert
-- loop through until all records updated
End
close Cursor2
できる場合は、データベーススキーマを変更することを強くお勧めします。 SCを開始してからデータ値を持つ別の名前の列は存在してはいけません。余分な列は「suminsured」を表し、1つのsc列は検索された値を表す必要があります。それはまた、この現在のクエリのSQLを書くのが簡単になります。 –