3

WinFormから渡された行番号に従って行を削除したい。もちろん、ROW_NUMBER()行を削除すると計算の出力は常に更新されるため、行番号も変更されるため、ループではなく一発で実行したいと考えています。

私はこのコードを持っています:

CREATE PROCEDURE Delete_Record (@RowNum INT)
AS     
  ;WITH REC_ROW AS
  (
    SELECT *, ROW_NUMBER() OVER (ORDER BY [Record Number]) AS RN
        FROM User_Data
  )
  DELETE
    FROM REC_ROW
    WHERE RN IN (@RowNum)

そして、私が入力すると:

 exec Delete_Record @RowNum = '1,2'

次のエラーが発生します。

データ型 varchar を int に変換中にエラーが発生しました。

に変更@RowNum INTすると@RowNum varchar(max)、次のエラー メッセージが表示されます。

データ型 varchar を bigint に変換中にエラーが発生しました。

値をハードコーディングすると:

;WITH REC_ROW AS
(
    SELECT *, ROW_NUMBER() OVER (ORDER BY [Record Number]) AS RN
        FROM User_Data
)
DELETE
  FROM REC_ROW
  WHERE RN IN (1,2)

行 1 と 2 が正常に削除されます。問題は、これをストアド プロシージャに統合し、句'1,2'に渡すように入力するにはどうすればよいかということです。IN

4

2 に答える 2

2

より複雑な文字列を渡す場合は1,2、テーブル値パラメーター (TVP) の使用を検討してください。

CREATE TYPE dbo.Integers AS TABLE
(
  RowNumber INT PRIMARY KEY
);

これで、ストアド プロシージャを作成し、アプリケーションから DataTable やその他のコレクションを渡すことができます。カンマ区切りの文字列を作成したり、それらを分解したりする必要はありません。

CREATE PROCEDURE dbo.Delete_Record
  @RowNums dbo.Integers READONLY
AS
BEGIN
  SET NOCOUNT ON;

  ;WITH REC_ROW AS (...your CTE unchanged here...)
  DELETE REC_ROW
   FROM REC_ROW INNER JOIN @RowNums AS r
   ON r.RowNumber = REC_ROW.RN;
END
GO

本当に分割機能を使用したい場合:

CREATE FUNCTION dbo.SplitInts
(
   @List      VARCHAR(MAX),
   @Delimiter VARCHAR(255)
)
RETURNS TABLE WITH SCHEMABINDING 
AS
  RETURN 
  (  
    SELECT Item = y.i.value('(./text())[1]', 'int')
    FROM ( SELECT x = CONVERT(XML, '<i>' 
        + REPLACE(@List, @Delimiter, '</i><i>') 
        + '</i>').query('.')) AS a 
    CROSS APPLY x.nodes('i') AS y(i));
GO

今あなたのストアドプロシージャ:

CREATE PROCEDURE dbo.Delete_Record -- always use a schema prefix!
  @RowNums VARCHAR(MAX)
AS 
BEGIN
  SET NOCOUNT ON;

  ;WITH REC_ROW AS
  (
    SELECT *, ROW_NUMBER() OVER (ORDER BY [Record Number]) AS RN
        FROM dbo.User_Data
  )
  DELETE REC_ROW
    FROM REC_ROW 
    INNER JOIN dbo.SplitInts(@RowNums, ',') AS r
    ON r.Item = REC_ROW.RN;
END
GO

しかし、TVP のパフォーマンスが向上することを保証します。

于 2013-08-20T16:43:23.900 に答える
0

この式は、あなたが思っていることをしません:

 WHERE RN IN (@RowNum)

の場合を探してい@RowNumます'1,2''1,2'整数に変換できないため、これが問題を引き起こします。プロシージャを定義するときにパラメータを整数として宣言しましたが、文字列で呼び出しています。

あなたがやりたいことをすることができます:

WHERE ','+@RowNum+',' like '%,'+RN+',%'

追加のコンマにより、「1」が「10」と一致しないことが保証されます。

編集:

コンマで区切られた整数の文字列を実際の整数として処理するには、基本的に 3 つの方法 (私が考えることができます) があります (クエリが整数を使用するため、これの方が優れています)。

split()1 つは、区切り文字列の要素のテーブルを返す関数を使用することです。さまざまな実装についてグーグルで検索できます。

2 つ目は、動的 SQL を使用することです。これは、即時である必要のないクエリには適しています。クエリをコンパイルする際に追加のオーバーヘッドが発生する可能性があり、これはトランザクション システムで顕著になる場合があります。

3 つ目は、再帰的な CTE を使用して文字列を解析することです。おそらく、このメソッドをストアド プロシージャに使用するでしょう。

于 2013-08-20T16:36:39.023 に答える