2011-01-07 3 views
2

데이터가 들어있는 표가 있다고 가정 해 보겠습니다.SQL Server 2000에서 기본 키가없는 테이블의 지정된 행을 삭제하는 방법은 무엇입니까?

IF OBJECT_ID('dbo.table1') IS NOT NULL 
BEGIN 
    DROP TABLE dbo.table1; 
END 
CREATE TABLE table1 (DATA INT); 

--------------------------------------------------------------------- 
-- Generating testing data 
--------------------------------------------------------------------- 
INSERT INTO dbo.table1(data) 
SELECT 100 
UNION ALL 
SELECT 200 
UNION ALL 
SELECT NULL 
UNION ALL 
SELECT 400 
UNION ALL 
SELECT 400 
UNION ALL 
SELECT 500 
UNION ALL 
SELECT NULL; 

테이블의 두 번째, 다섯 번째, 여섯 번째 레코드를 삭제하는 방법은 무엇입니까? 순서는 다음 쿼리로 정의됩니다.

SELECT data 
FROM dbo.table1 
ORDER BY data DESC; 

참고,이 SQL 서버 2000 환경입니다.

감사합니다.

+1

데이터베이스 스키마가 그런식이 아닙니다. @Mitch Wheat이 말했듯이 - 당신의 * 진짜 * 시나리오를 시도해보십시오. 그렇지 않으면 우리의 삶이 어려워집니다. – RPM1984

+1

* 기본 키가 없으면 테이블이 아닙니다! * (Joe Celko) - 기본 키를 추가하면 모든 문제가 마술처럼 사라집니다. –

답변

2

알고 계신대로 row_number을 사용하는 이후 버전에서는이 작업을 매우 쉽게 수행 할 수 있습니다.

delete t from 
(select ROW_NUMBER() over (order by data) r from table1) t 
where r in (2,5,6) 

그것도없이 내가 그 생각 SQL 서버 2000에서 사용할 수있는 생각하지 않습니다이 동일한 행

SELECT data,%%LOCKRES%% 
FROM dbo.table1` 

구분하는 문서화되지 않은 %%LOCKRES%% 기능을 사용할 수 있습니다.

SQL Set에는 순서가 없지만 커서가 있기 때문에 아래와 같이 사용할 수 있습니다. NB : DELETE ... WHERE CURRENT OF을 사용할 수 있기를 기대했지만 PK를 사용하므로 행을 삭제하는 코드가 원하는만큼 간단하지 않습니다.

삭제할 데이터가 중복 된 경우 CURRENT OF과 같은 행이 삭제된다는 보장이 없습니다. 그러나이 우발적 인 상황에서 묶인 행의 순서는 어쨌든 임의의 행이므로 어떤 행이든 삭제됩니다 도 커서 순서대로 해당 행 번호를 부여 할 수 있습니다.

DECLARE @RowsToDelete TABLE 
(
rowidx INT PRIMARY KEY 
) 
INSERT INTO @RowsToDelete SELECT 2 UNION SELECT 5 UNION SELECT 6 

DECLARE @PrevRowIdx int 
DECLARE @CurrentRowIdx int 
DECLARE @Offset int 
SET @CurrentRowIdx = 1 
DECLARE @data int 

DECLARE ordered_cursor SCROLL CURSOR FOR 
SELECT data 
FROM dbo.table1 
ORDER BY data 

OPEN ordered_cursor 

FETCH NEXT FROM ordered_cursor INTO @data 

WHILE EXISTS(SELECT * FROM @RowsToDelete) 
BEGIN 
SET @PrevRowIdx = @CurrentRowIdx 
SET @CurrentRowIdx = (SELECT TOP 1 rowidx FROM @RowsToDelete ORDER BY rowidx) 
SET @Offset = @CurrentRowIdx - @PrevRowIdx 
DELETE FROM @RowsToDelete WHERE rowidx = @CurrentRowIdx 

FETCH RELATIVE @Offset FROM ordered_cursor INTO @data 

/*Can't use DELETE ... WHERE CURRENT OF as here that requires a PK*/ 
SET ROWCOUNT 1 
DELETE FROM dbo.table1 WHERE ([email protected] OR data IS NULL OR @data IS NULL) 
SET ROWCOUNT 0 

END 

CLOSE ordered_cursor 
DEALLOCATE ordered_cursor 
0

행 세트에 대한 조치 (예 : h 제)를 수행하려면 해당 행을 식별하는 내용을 알아야합니다.

그래서 에 삭제하려는 행을 식별하는 기준이 있어야합니다.

위와 같은 장난감 예제를 제공하는 것은별로 유용하지 않습니다.

0

미리 계획을 세우십시오. 예상되는 경우 대리 키 열 또는 일부를 추가 할 수 있습니다.

일반적으로 PK가없는 테이블을 만들지 않도록하십시오.

"길을 건너기 전에 양방향으로 보지 말고 버스 앞에서 밟아 라."라고 묻는 것과 같습니다.

3

간단히 말해서, 순서를 나타 내기 위해 테이블에 무엇인가가 필요합니다. "두 번째 행"은 시퀀스를 실행하는 것이 아무것도 없을 때 비 연속입니다. 당신이 원하는하지만 개념은 당신이 얻을 것이다 최고로

If object_id('tempdb..#NumberedData') Is Not Null 
    Drop Table #NumberedData 

Create Table #NumberedData 
(
Id int not null identity(1,1) primary key clustered 
, data int null 
) 

Insert #NumberedData(data) 
SELECT 100 
UNION ALL SELECT 200 
UNION ALL SELECT NULL 
UNION ALL SELECT 400 
UNION ALL SELECT 400 
UNION ALL SELECT 500 
UNION ALL SELECT NULL 

Begin Tran 

Delete table1 

Insert table1(data) 
Select data 
From #NumberedData 
Where Id Not In(2,5,6) 

If @@Error <> 0 
    Commit Tran 
Else 
    Rollback Tran 

물론, 이러한 유형의 솔루션이 정확히 작동하지 않을 수있다 : 그러나, 가능한 해결책은 (장난감 예 => 장난감 용액) 일 수 있습니다. 본질적으로, 행을 식별 C 럼이있는 테이블에 채우고이를 사용하여 제거 할 행을 식별합니다.행을 제거하면 원래 표가 비워지고 원하는 행만 다시 채워집니다. 어떤 종류의 고유 한 키가 없으면이 문제를 처리 할 수있는 명확한 방법이 없습니다.

+0

동일한 목표를 달성 할 때 + 1ed 그러나 특정 행만 h 제하는 f}에 대한 질문에는 대답하지 않습니다. –