为什么使用with LIKE关键字时SQL DELETE查询不起作用?
我想从我的表中删除一些数据,所以写一个查询来删除它。因此,首先,我使用这个查询选择了要删除的数据,它向我显示了正确的数据为什么使用with LIKE关键字时SQL DELETE查询不起作用?,sql,sql-server,Sql,Sql Server,我想从我的表中删除一些数据,所以写一个查询来删除它。因此,首先,我使用这个查询选择了要删除的数据,它向我显示了正确的数据 select * from PATS.Discipline where Code like '%DHA-DIS%' 然后我使用相同的where条件编写delete,但它不起作用 DELETE FROM PATS.Discipline WHERE Code LIKE '%DHA-DIS%' 在这里,我在执行查询时共享一些屏幕截图 下面是一些示例数据 这是最后一次执行结果
select * from PATS.Discipline where Code like '%DHA-DIS%'
然后我使用相同的where条件编写delete,但它不起作用
DELETE FROM PATS.Discipline WHERE Code LIKE '%DHA-DIS%'
在这里,我在执行查询时共享一些屏幕截图
下面是一些示例数据
这是最后一次执行结果,我已经等待了1分钟,最后一次停止执行
添加表结构
更新日期:2019年10月15日
今天我尝试了相同的场景,我将5000条记录导入到表中,并尝试使用相同的查询删除这5000条记录,令人惊讶的是,它居然能工作。这两个案子我都试过了
1.数据不存在任何外键,工作正常。这是截图
包含外键的数据将显示错误。
这两种情况现在都可以使用了,我不知道SQL server那天发生了什么事情,它应该可以正常使用,我看不出查询有任何问题,请尝试在新的查询窗口中写入新的查询,以确保查询是干净的 对我来说,它工作得很好,可以从表中删除测试数据
select * from Discipline
select * from Discipline where Code like '%DHA-DIS%'
您可以看到上面的查询工作正常,它删除了匹配查询的2行。它应该工作正常,我看不出查询有任何问题,请尝试在新查询窗口中写入新查询,以确保查询是干净的 对我来说,它工作得很好,可以从表中删除测试数据
select * from Discipline
select * from Discipline where Code like '%DHA-DIS%'
您可以看到上面的查询工作正常,它删除了匹配查询的2行。1您有5000行要删除,但这不一定是整个表。表中有多少行 2您的LIKE语句需要进行表格扫描才能满足要求。如果有大量的行或大型列,这将需要很长时间 3在它使用的表上发布查询计划和统计数据
4如果取消删除,则数据库将回滚。这就是为什么您看到它什么也不做。1您有5000行要删除,但这不一定是整个表。表中有多少行 2您的LIKE语句需要进行表格扫描才能满足要求。如果有大量的行或大型列,这将需要很长时间 3在它使用的表上发布查询计划和统计数据
4如果取消删除,则数据库将回滚。这就是为什么您看到它什么也不做。可能是另一个进程锁定了表规程 通过运行此脚本,可以找到表上的锁
declare @lock table (spid int, dbid int, objId int, indId int, Type char(4), resource nchar(32), Mode char(8), status char(6))
declare @who table (spid int, ecid int, status char(30), loginname char(128), hostname char(128), blk char(5), dbname char(128), cmd char(16), request_id INT)
declare @LockSummary table (loginname varchar(28), DB varchar(128), object varchar(30), ToLevel varchar(20), How_Many int, Xclusive_lock_for_command char(16), spid int, hostname char(128))
insert into @lock exec sp_lock
insert into @who exec sp_who
insert into @LockSummary
select loginname,
db_name(dbid) as DB,
object_name(objID) as object,
max(mode) as [ToLevel],
Count(*) as [How Many],
Max(Case When mode= 'X' Then cmd Else null End) as [Xclusive lock for command],
l.spid,
hostname
from @lock l
join @who w on l.spid = w.spid
where dbID != db_id('tempdb')
and l.status = 'GRANT'
group by dbID, objID, l.spid, hostname, loginname
select *
from @LockSummary
where object like '%Discipline%'
order by [ToLevel] Desc, [How_Many] Desc, loginname, DB, object
另一个进程可能会锁定表规程 通过运行此脚本,可以找到表上的锁
declare @lock table (spid int, dbid int, objId int, indId int, Type char(4), resource nchar(32), Mode char(8), status char(6))
declare @who table (spid int, ecid int, status char(30), loginname char(128), hostname char(128), blk char(5), dbname char(128), cmd char(16), request_id INT)
declare @LockSummary table (loginname varchar(28), DB varchar(128), object varchar(30), ToLevel varchar(20), How_Many int, Xclusive_lock_for_command char(16), spid int, hostname char(128))
insert into @lock exec sp_lock
insert into @who exec sp_who
insert into @LockSummary
select loginname,
db_name(dbid) as DB,
object_name(objID) as object,
max(mode) as [ToLevel],
Count(*) as [How Many],
Max(Case When mode= 'X' Then cmd Else null End) as [Xclusive lock for command],
l.spid,
hostname
from @lock l
join @who w on l.spid = w.spid
where dbID != db_id('tempdb')
and l.status = 'GRANT'
group by dbID, objID, l.spid, hostname, loginname
select *
from @LockSummary
where object like '%Discipline%'
order by [ToLevel] Desc, [How_Many] Desc, loginname, DB, object
您是否在编辑模式下尝试了相同的查询。 你可以这样做 右键单击Pats.规程表。 选择“编辑前200…行” 按Ctrl+3编辑查询。 将查询替换为select*from规程,其中代码为“%DHA-DIS%” 单击下图中的第一个顶部单元格以选择所有行 点击删除按钮 如果执行时间太长,请尝试将查询更改为以下内容 从代码为“%DHA-DIS%”的规程中选择top 1000* 如果成功,请重复该步骤
您是否在编辑模式下尝试了相同的查询。 你可以这样做 右键单击Pats.规程表。 选择“编辑前200…行” 按Ctrl+3编辑查询。 将查询替换为select*from规程,其中代码为“%DHA-DIS%” 单击下图中的第一个顶部单元格以选择所有行 点击删除按钮 如果执行时间太长,请尝试将查询更改为以下内容 从代码为“%DHA-DIS%”的规程中选择top 1000* 如果成功,请重复该步骤
有两件事可能会减慢你的删除速度 您在Pats.规程表中引用PK的外键上有级联删除。通过运行下面的查询,您可以检查是否有任何启用了cascade delete的键。 Pats.规程表的主键在其他行数非常多的表中用作外键。删除规程表中具有这些字段的记录将触发对引用此键的所有表的引用完整性检查,这可能是一个漫长的过程,具体取决于某些因素。 如果您知道此删除没有违反引用完整性,则可以删除外键,然后运行delete命令,然后重新创建外键。
有两件事可能会减慢你的删除速度 您在Pats.规程表中引用PK的外键上有级联删除。通过运行下面的查询,您可以检查是否有任何启用了cascade delete的键。 Pats.规程表的主键在其他行数非常多的表中用作外键。删除规程表中具有这些字段的记录将触发引用完整性检查 n引用此键的所有表,根据某些因素,这可能是一个漫长的过程。 如果您知道此删除没有违反引用完整性,则可以删除外键,然后运行delete命令,然后重新创建外键。 注意:收回 如果可能,将PATSDiscipline更改为此 或者改变任何可能的列 CreatedBY可以通过首先手动连接关注点表来转换为INT。 然后是纠错码 我不是在讨论这一点,像“%DHA-DIS%”这样的代码是不可取的。 或者为什么你不应该使用。 以及代码列是否应为非聚集索引 改变表设计将在各个方面帮助您,无论是选择查询还是DML操作,甚至是永远 或者你也可以这样做 将选择结果集放入临时表中,然后加入并删除
create table #temp (id uniqueidentifier not null primary key)
insert into #temp
select id from PATS.Discipline where Code like '%DHA-DIS%'
delete from PATS.Discipline
where exists(select 1 from #temp where #temp.id=PATS.Discipline.id )
这两步你都可以走
如果删除数据的单位为百万,则可以使用分页
DECLARE @TopSize INT = 10000
DECLARE @BatchSize INT = 10000
DECLARE @MaxLimit INT = 1
DECLARE @RowCount INT = 0
BEGIN TRY
WHILE (@TopSize <= @MaxLimit)
BEGIN
delete TOP (@TopSize) from PATS.Discipline
where exists(select 1 from #temp where #temp.id=PATS.Discipline.id )
SET @RowCount = @@RowCount
--PRINT @TopSize
IF (
@RowCount = 0
OR @RowCount IS NULL
)
BREAK;
ELSE
SET @TopSize = @TopSize + @BatchSize
END
END TRY
BEGIN CATCH
--catch error
END CATCH
注意:收回
如果可能,将PATSDiscipline更改为此
或者改变任何可能的列
CreatedBY可以通过首先手动连接关注点表来转换为INT。
然后是纠错码
我不是在讨论这一点,像“%DHA-DIS%”这样的代码是不可取的。
或者为什么你不应该使用。
以及代码列是否应为非聚集索引
改变表设计将在各个方面帮助您,无论是选择查询还是DML操作,甚至是永远
或者你也可以这样做
将选择结果集放入临时表中,然后加入并删除
create table #temp (id uniqueidentifier not null primary key)
insert into #temp
select id from PATS.Discipline where Code like '%DHA-DIS%'
delete from PATS.Discipline
where exists(select 1 from #temp where #temp.id=PATS.Discipline.id )
这两步你都可以走
如果删除数据的单位为百万,则可以使用分页
DECLARE @TopSize INT = 10000
DECLARE @BatchSize INT = 10000
DECLARE @MaxLimit INT = 1
DECLARE @RowCount INT = 0
BEGIN TRY
WHILE (@TopSize <= @MaxLimit)
BEGIN
delete TOP (@TopSize) from PATS.Discipline
where exists(select 1 from #temp where #temp.id=PATS.Discipline.id )
SET @RowCount = @@RowCount
--PRINT @TopSize
IF (
@RowCount = 0
OR @RowCount IS NULL
)
BREAK;
ELSE
SET @TopSize = @TopSize + @BatchSize
END
END TRY
BEGIN CATCH
--catch error
END CATCH
这个答案是基于我个人的经验
您正在将uniqueidentifier存储为表的Id,并使其成为主聚集键。删除这样数量的行需要时间,因为需要重新索引表。因此,我建议-
删除主键索引
执行delete语句
重新添加主键索引
在类似的情况下,它帮助了我。为什么?因为在这种策略中,该表的索引只被操作了两次。删除时,不会对表进行重新索引。因此,您将看到执行删除操作的显著改进
所以,您的查询应该是这样的-
ALTER TABLE PATS.Discipline DROP CONSTRAINT [PK_Discipline]
GO
DELETE FROM PATS.Discipline WHERE Code LIKE '%DHA-DIS%'
GO
ALTER TABLE PATS.Discipline DROP CONSTRAINT [PK_Discipline] PRIMARY KEY CLUSTERED
GO
注意:这种删除策略只适用于表有许多索引或主键是uniqueidentifier并且您试图从该表中删除更多行的情况。但在正常情况下,应使用相同的旧删除查询。此答案基于我的个人经验
您正在将uniqueidentifier存储为表的Id,并使其成为主聚集键。删除这样数量的行需要时间,因为需要重新索引表。因此,我建议-
删除主键索引
执行delete语句
重新添加主键索引
在类似的情况下,它帮助了我。为什么?因为在这种策略中,该表的索引只被操作了两次。删除时,不会对表进行重新索引。因此,您将看到执行删除操作的显著改进
所以,您的查询应该是这样的-
ALTER TABLE PATS.Discipline DROP CONSTRAINT [PK_Discipline]
GO
DELETE FROM PATS.Discipline WHERE Code LIKE '%DHA-DIS%'
GO
ALTER TABLE PATS.Discipline DROP CONSTRAINT [PK_Discipline] PRIMARY KEY CLUSTERED
GO
注意:这种删除策略只适用于表有许多索引或主键是uniqueidentifier并且您试图从该表中删除更多行的情况。但在正常情况下,应该应用相同的旧删除查询。LIKE关键字可能没有问题。SELECT似乎返回了很多匹配的行—我想是相对较快的—所以问题是什么比较慢,或者是什么阻止了删除?试一试
DELETE TOP 1 FROM PATS.Discipline WHERE Code LIKE '%DHA-DIS%'
如果这是有效的,试试前10/100
一个有根据的猜测是,由于重新索引和/或跨表关系外键约束和/或只是建立了一个非常大的事务,所以速度很慢
如何加速?在已经发布的答案中有很多很好的建议,我也建议大家看看这个:LIKE关键字可能没有问题。SELECT似乎返回了很多匹配的行—我想是相对较快的—所以问题是什么比较慢,或者是什么阻止了删除?试一试
DELETE TOP 1 FROM PATS.Discipline WHERE Code LIKE '%DHA-DIS%'
如果这是有效的,试试前10/100
一个有根据的猜测是,由于重新索引和/或跨表关系外键约束和/或只是建立了一个非常大的事务,所以速度很慢
如何加速?在已经发布的答案中,有很多很好的建议,我也建议大家看看这个:其他所有我不认为您最初使用的代码有任何问题,尽管在删除查询中使用like语句会影响性能。如果我知道我只删除了几千行,我将采用CTE方法,并将其连接回源表:
;With DeleteCTE as
(
select
[ID],
Code
from Discipline
where Code like '%DHA-DIS%'
)
Delete
from Discipline D
Inner Join
DeleteCTE DC
on DC.ID = D.ID
其他所有我不认为t有任何问题 虽然在delete查询中使用like语句会影响性能,但他会在最初使用的位置为您编码。如果我知道我只删除了几千行,我将采用CTE方法,并将其连接回源表:
;With DeleteCTE as
(
select
[ID],
Code
from Discipline
where Code like '%DHA-DIS%'
)
Delete
from Discipline D
Inner Join
DeleteCTE DC
on DC.ID = D.ID
我想你更关心这里的执行时间,因为它需要很长时间,所以你取消了执行。我过去也遇到过同样的问题,我的解决方案是重新启动SQL Management Studio并尝试相同的查询,它将正常工作。我认为您更关心执行时间,因为它需要很长时间,所以您取消了执行。我以前也遇到过同样的问题,我的解决方案是重新启动SQL Management Studio并尝试相同的查询,它会正常工作。您使用的查询没有问题 可能有几个原因。网络电缆可能已经断开,数据库可能在执行的中间脱机,可能有电源断电,或者由于另一个事务等的锁定而访问表。 当您的查询失败时,有时甚至需要超过1分钟,对吗?但当它成功时,执行速度非常快。当查询失败时,一定有另一个通过网络访问该表的权限
在处理大量数据(如5000)时,可以添加带有事务块的存储过程 您使用的查询没有问题 可能有几个原因。网络电缆可能已经断开,数据库可能在执行的中间脱机,可能有电源断电,或者由于另一个事务等的锁定而访问表。 当您的查询失败时,有时甚至需要超过1分钟,对吗?但当它成功时,执行速度非常快。当查询失败时,一定有另一个通过网络访问该表的权限
在处理大量数据(如5000)时,可以添加带有事务块的存储过程 不工作是什么意思?你需要给我们一个可复制的例子来处理这个问题吗。如果第一个select返回记录,那么第二个delete应该是删除某些内容。您确定您的命令连接到同一个数据库吗?检查表上是否存在触发器以及它们的作用是否有其他使用此表的应用程序?可能在VisualStudio的调试会话中?如果另一个应用程序正在使用该表,那么我可以在该表上设置一个锁,在这种情况下,您的delete语句将不得不等待该锁终止,这意味着什么不工作?你需要给我们一个可复制的例子来处理这个问题吗。如果第一个select返回记录,那么第二个delete应该是删除某些内容。您确定您的命令连接到同一个数据库吗?检查表上是否存在触发器以及它们的作用是否有其他使用此表的应用程序?可能在VisualStudio的调试会话中?如果另一个应用程序正在使用该表,那么我可以在该表上设置一个锁,在这种情况下,您的delete语句必须等待该锁终止。即使使用表扫描,也不应该花费那么长的时间,因为表中只有5000行。我的猜测是,另一个进程在表上有一个锁,即使使用表扫描,也不应该花费那么长的时间,因为表中只有5000行。我的猜测是,另一个processComments在表上有一个锁,评论不用于扩展讨论;此对话已结束。评论不用于扩展讨论;这段对话已经结束。我也会检查。我也会检查。它是这样工作的,问题是它没有删除批量数据。你是否尝试删除前100名?如果它有效,那么我发布的链接中的讨论解释了为什么要删除批量,您应该分小块进行。有一些例子说明了如何巧妙地做到这一点。DELETE是以事务方式执行的,即DB在事务日志文件中写入它将要执行的所有操作,以便在提交结果之前,在出现问题时可以撤消。在没有其他证据(例如锁定)的情况下,这可能就是删除会运行很长时间的原因。谷歌成本sql删除更多。欢迎您。如果你的问题得到了回答,请标出最好的一个。如果没有,但是你自己找到了解决方案,请发布。它是这样工作的,问题是它没有删除批量数据。你是否尝试删除前100名?如果它有效,那么我发布的链接中的讨论解释了为什么要删除批量,您应该分小块进行。有一些例子说明了如何巧妙地做到这一点。DELETE是以事务方式执行的,即DB在事务日志文件中写入它将要执行的所有操作,以便在提交结果之前,在出现问题时可以撤消。在没有o的情况下
例如锁定的证据,这可能就是删除运行很长时间的原因。谷歌成本sql删除更多。欢迎您。如果你的问题得到了回答,请标出最好的一个。如果不是,但您自己已经找到了解决方案,请发布。@ganesh,重新启动sql server不是一个好的解决方案。服务器中可能正在运行其他进程。@ganesh,重新启动sql server不是一个好的解决方案。服务器中可能正在运行某些其他进程。