2013-08-20 2 views
2

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' 

그것은 오류 발생 :

Error converting data type varchar to int.

을 내가 @RowNum INT@RowNum varchar(max)에 변경하면 다음과 같은 오류 메시지가 나타납니다.

Error converting data type varchar to 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 절에?

답변

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 더 나은 수행합니다 나는 당신을 보장합니다.

+0

어디서 CREATE TYPE dbo.Integers 부분을 넣어야합니까? Create Procedure 부분에 있어야합니까? 나는 그것을 시도하고 그것은 잘못된 구문을 근처에 '('. –

+0

@ CaressCastañares 한 번에 별도의 명령으로 실행합니다. 그것은 당신의 절차 내에서 사용하는'dbo.Integers' 테이블 매개 변수의 "유형"을 설정합니다. –

+1

@Caress 아니요, 저장 프로 시저 내부가 아닌 TYPE * once *를 만듭니다. 테이블을 만드는 것과 같습니다. –

0

이 표현은 당신이하지 생각하지 않습니다 : 그것은 @RowNum'1,2'되는 경우를 찾고 있습니다

WHERE RN IN (@RowNum) 

. 그리고 '1,2'을 정수로 변환 할 수 없으므로 이로 인해 문제가 발생합니다. 프로 시저를 정의 할 때 매개 변수를 정수로 선언했지만 문자열로 호출하십시오. 여분의 쉼표가 "1"은 "10"과 일치하지 않도록

WHERE ','[email protected]+',' like '%,'+RN+',%' 

:

당신은 당신이 원하는 것을 할 수 있습니다.

편집 :

(쿼리 정수를 사용하기 때문에 더 나은) 실제 정수로 쉼표로 구분 정수의 문자열을 처리하기위한 세 가지 방법이 (내가 생각할 수있는) 기본적으로 있습니다

.

하나는 split() 함수를 사용하는 것으로, 구분 된 문자열 요소의 테이블을 반환합니다. 당신은 그것의 다양한 구현을위한 구글 수 있습니다.

둘째는 동적 SQL을 사용하는 것입니다. 이것은 즉각적인 쿼리 일 필요가 없습니다. 쿼리를 컴파일하는 데 추가 오버 헤드가 발생할 수 있으며 트랜잭션 시스템에서 눈에 띄게 될 수 있습니다.

세 번째는 재귀 CTE를 사용하여 문자열을 구문 분석하는 것입니다. 아마도이 방법을 저장 프로 시저에 사용할 것입니다.

+0

이것은 작동하지 않습니다. 행 "1"또는 "2"는 절대로'%, 1,2, %'와 같지 않습니다. 오류는'1,2'가'int'가 아니라는 것입니다. 매개 변수를 varchar로 만들고 split 함수를 사용하고 그런 다음 분할 행에 대한 삭제에 참여하십시오. –

+0

네, 맞습니다. LIKE 명령을 사용하고 싶지만 문제가 생성 될 것입니다. 정확한 숫자 만 검색하고 유사점을 검색하는 방법이 있습니까? –

+0

@KM,이 샘플 코드를 만들 수 있습니까? 당신이 말하는 스플릿 기능이라 할지라도 이것은 큰 도움이 될 것입니다. 감사! –

관련 문제