2011-01-07 98 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; 

如何刪除表中的第2,第5,第6條記錄?訂單由以下查詢定義。

SELECT data 
FROM dbo.table1 
ORDER BY data DESC; 

注意,這是SQL Server 2000中環境。

謝謝。

+1

你的數據庫模式不可能是這樣的。正如@米奇小麥所說 - 請儘量提供你真實的情景,否則你的生活會變得比他們的生活更困難。 – RPM1984 2011-01-07 04:36:19

+1

*如果它沒有主鍵,它不是一張桌子!*(Joe Celko) - 添加一個主鍵,所有問題都會自動消失...... – 2011-01-07 07:45:04

回答

2

正如你可能知道你可以在以後的版本中使用row_number非常簡單地做到這一點。

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

即使沒有,有可能使用無證%%LOCKRES%%功能2點相同的行

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

區分,我不認爲這是在SQL Server 2000中提供,但。

在SQL集沒有順序,但遊標這樣做,你可以使用類似下面的東西。注:我期望能夠使用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

要對一組行執行任何操作(例如刪除它們),您需要知道標識這些行的標識。

因此,必須拿出標識你想刪除的行的標準。

提供一個玩具的例子,就像上面的例子一樣,並不是特別有用。

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 

顯然,這種類型的解決方案不能保證準確地工作,只要你想,但這個概念是,你會得到最好的。實質上,您可以將行填入具有標識列的表中,並使用它來標識要刪除的行。刪除行需要清空原始表並僅使用所需的行重新填充。沒有某種獨特的鑰匙,就沒有辦法解決這個問題。