在SQL Server 2000中,如何删除没有主键的表中的指定行?
假设我们有一张包含一些数据的表格。在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中环境。
谢谢。
正如你可能知道你可以在以后的版本中使用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
要对一组行执行任何操作(例如删除它们),您需要知道标识这些行的标识。
因此,你必须拿出标识你想删除的行的标准。
提供一个玩具的例子,就像上面的例子一样,并不是特别有用。
你提前计划,如果你预计这是可能的,你可以添加一个代理键列或其他类似的东西。
一般来说,您一定要确保不创建没有PK的表格。
这就像问道:“说我在过马路之前看不到两个方向,我走在公共汽车前面。”
总之,你需要表中的东西来表示顺序。当没有任何东西强制顺序的时候,“第二排”是一个不起作用的东西。然而,一个可能的解决方案(例如玩具=>玩具溶液):
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
显然,这种类型的解决方案不能保证准确地工作,只要你想,但这个概念是,你会得到最好的。实质上,您可以将行填入具有标识列的表中,并使用它来标识要删除的行。删除行需要清空原始表并仅使用所需的行重新填充。没有某种独特的钥匙,就没有办法解决这个问题。
你的数据库模式不可能是这样的。正如@米奇小麦所说 - 请尽量提供你真实的情景,否则你的生活会变得比他们的生活更困难。 – RPM1984 2011-01-07 04:36:19
*如果它没有主键,它不是一张桌子!*(Joe Celko) - 添加一个主键,所有问题都会自动消失...... – 2011-01-07 07:45:04