次の問題があります。UpdateData と呼ばれる DB にデータを更新または挿入するために使用するストアド プロシージャがあります。おおよそ次のようになります (簡略化されていますが)。
CREATE PROCEDURE [dbo].[UpdateData]
@dataId as int,
@data as int,
AS
BEGIN
SET NOCOUNT ON;
declare @count int
select @count = (select COUNT(*) from DataTable data where data.id = @dataId)
if @count = 1
begin
update DataTable set data = @data from DataTable where data.id = @dataId
select 'Updated' [operation] , @@ROWCOUNT [count]
end
else
begin
insert into DataTable (id, data) values(@dataId, @data)
select 'Inserted' [operation] , @@ROWCOUNT [count]
end
END
DBI を使用して、このストアド プロシージャを perl から呼び出し、準備済みステートメントを介してデータを反復処理します。次に、fetchrow_array への呼び出しを使用して、実行された操作に関する情報を取得します。
my $dbh = getDBHandle($debug);
foreach (@Data) {
$updateData->execute($->[0], $_->[1]);
my @row = $updateData->fetchrow_array;
my ($action, $count) = ($row[0], $row[1]);
print $row[0] .",$action, $count\n";
}
何が起こるかというと、更新ステートメントが実行されると、その後、アクションが挿入されたすべての説明が「挿入」から「挿入」に切り捨てられます。これは、文字列「updated」の文字が「inserted」よりも 1 文字少なく、列内のその文字列で fetchrow_array が呼び出されると、何らかの制限がリセットされるために発生していると思います。2 つの説明文字列の違いが 1 つ以上ある場合は、ストア プロシージャを変更して、「更新済み」ではなく「更新」を使用するようにします (「挿入済み」に対する 2 文字の違い)。
select 'Update' [operation] , @@ROWCOUNT [count]
エラーが発生します:
DBD::ODBC::st fetchrow_array failed: [Microsoft][ODBC SQL Server Driver]String data, right truncation (SQL-01004)
要約すると、出力は次のようになります
1,挿入,10
2,更新,15
3、挿入、20
4,更新,5
実行が独立していない理由と、この問題を解決する最善の方法についてのアイデア。アクションを同じにすることができることはわかっていますが、より良い解決策が必要です。
編集:フォローアップの質問。UpdateData プロシージャが、データを返す別のプロシージャを呼び出す必要がある場合。Perl で両方の結果セットを取得することは可能ですか? 1 つは内側の手順から、もう 1 つは外側の手順から来ます。現在、>fetchrow_array は内部の結果セットのみを取得します。
編集 2: データの切り捨ての元の問題に関して、実行ごとに $updateData->finish を呼び出しても、実行ごとに幅がリセットされないのはなぜだろうかと思っています。IE
foreach (@Data) {
$updateData->execute($->[0], $_->[1]);
my @row = $updateData->fetchrow_array;
my ($action, $count) = ($row[0], $row[1]);
print $row[0] .",$action, $count\n";
$updateData->finish;
}